OSDN Git Service

f24f95a64ce0e207217c26fee788c89e990dc2b7
[bytom/vapor.git] / protocol / tx.go
1 package protocol
2
3 import (
4         log "github.com/sirupsen/logrus"
5
6         "github.com/vapor/errors"
7         "github.com/vapor/protocol/bc"
8         "github.com/vapor/protocol/bc/types"
9         "github.com/vapor/protocol/state"
10         "github.com/vapor/protocol/validation"
11 )
12
13 // GetTransactionStatus return the transaction status of give block
14 func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
15         return c.store.GetTransactionStatus(hash)
16 }
17
18 // GetTransactionsUtxo return all the utxos that related to the txs' inputs
19 func (c *Chain) GetTransactionsUtxo(view *state.UtxoViewpoint, txs []*bc.Tx) error {
20         return c.store.GetTransactionsUtxo(view, txs)
21 }
22
23 // ValidateTx validates the given transaction. A cache holds
24 // per-transaction validation results and is consulted before
25 // performing full validation.
26 func (c *Chain) ValidateTx(tx *types.Tx) (bool, error) {
27         if c.hasSeenTx(tx) {
28                 return false, nil
29         }
30
31         c.markTransactions(tx)
32
33         return c.validateTx(tx)
34 }
35
36 // validateTx validates the given transaction without checking duplication.
37 func (c *Chain) validateTx(tx *types.Tx) (bool, error) {
38         if ok := c.txPool.HaveTransaction(&tx.ID); ok {
39                 return false, c.txPool.GetErrCache(&tx.ID)
40         }
41
42         if c.txPool.IsDust(tx) {
43                 c.txPool.AddErrCache(&tx.ID, ErrDustTx)
44                 return false, ErrDustTx
45         }
46
47         bh := c.BestBlockHeader()
48         blockHash := bh.Hash()
49         consensusResult, err := c.GetConsensusResultByHash(&blockHash)
50         if err != nil {
51                 return false, err
52         }
53
54         if err := consensusResult.ApplyTransaction(tx); err != nil {
55                 return false, errors.Wrap(validation.ErrVoteOutputAmount, err)
56         }
57
58         gasStatus, err := validation.ValidateTx(tx.Tx, types.MapBlock(&types.Block{BlockHeader: *bh}))
59         if !gasStatus.GasValid {
60                 c.txPool.AddErrCache(&tx.ID, err)
61                 return false, err
62         }
63
64         if err != nil {
65                 log.WithFields(log.Fields{"module": logModule, "tx_id": tx.Tx.ID.String(), "error": err}).Info("transaction status fail")
66         }
67
68         return c.txPool.ProcessTransaction(tx, err != nil, bh.Height, gasStatus.BTMValue)
69 }