OSDN Git Service

merge with the dev
[bytom/bytom.git] / protocol / tx.go
1 package protocol
2
3 import (
4         "github.com/bytom/errors"
5         "github.com/bytom/protocol/bc"
6         "github.com/bytom/protocol/bc/legacy"
7         "github.com/bytom/protocol/validation"
8 )
9
10 // ErrBadTx is returned for transactions failing validation
11 var ErrBadTx = errors.New("invalid transaction")
12
13 // ValidateTx validates the given transaction. A cache holds
14 // per-transaction validation results and is consulted before
15 // performing full validation.
16 func (c *Chain) ValidateTx(tx *legacy.Tx) error {
17         newTx := tx.Tx
18         if err := c.checkIssuanceWindow(newTx); err != nil {
19                 return err
20         }
21         if ok := c.txPool.HaveTransaction(&newTx.ID); ok {
22                 return c.txPool.GetErrCache(&newTx.ID)
23         }
24
25         oldBlock, err := c.GetBlockByHash(c.state.hash)
26         if err != nil {
27                 return err
28         }
29         block := legacy.MapBlock(oldBlock)
30         fee, err := validation.ValidateTx(newTx, block)
31
32         if err != nil {
33                 c.txPool.AddErrCache(&newTx.ID, err)
34                 return err
35         }
36
37         c.txPool.AddTransaction(tx, block.BlockHeader.Height, fee)
38         return errors.Sub(ErrBadTx, err)
39 }
40
41 func (c *Chain) checkIssuanceWindow(tx *bc.Tx) error {
42         if c.MaxIssuanceWindow == 0 {
43                 return nil
44         }
45         for _, entryID := range tx.InputIDs {
46                 if _, err := tx.Issuance(entryID); err == nil {
47                         if tx.MinTimeMs+bc.DurationMillis(c.MaxIssuanceWindow) < tx.MaxTimeMs {
48                                 return errors.WithDetailf(ErrBadTx, "issuance input's time window is larger than the network maximum (%s)", c.MaxIssuanceWindow)
49                         }
50                 }
51         }
52         return nil
53 }