"github.com/bytom/errors"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
+ "github.com/bytom/protocol/state"
"github.com/bytom/protocol/validation"
)
// ErrBadTx is returned for transactions failing validation
var ErrBadTx = errors.New("invalid transaction")
+// GetTransactionStatus return the transaction status of give block
+func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
+ return c.store.GetTransactionStatus(hash)
+}
+
+// GetTransactionsUtxo return all the utxos that related to the txs' inputs
+func (c *Chain) GetTransactionsUtxo(view *state.UtxoViewpoint, txs []*bc.Tx) error {
+ return c.store.GetTransactionsUtxo(view, txs)
+}
+
// ValidateTx validates the given transaction. A cache holds
// per-transaction validation results and is consulted before
// performing full validation.
-func (c *Chain) ValidateTx(tx *types.Tx) error {
- newTx := tx.Tx
- block := types.MapBlock(c.BestBlock())
- if ok := c.txPool.HaveTransaction(&newTx.ID); ok {
- return c.txPool.GetErrCache(&newTx.ID)
+func (c *Chain) ValidateTx(tx *types.Tx) (bool, error) {
+ if ok := c.txPool.HaveTransaction(&tx.ID); ok {
+ return false, c.txPool.GetErrCache(&tx.ID)
}
- // validate the UTXO
view := c.txPool.GetTransactionUTXO(tx.Tx)
- if err := c.GetTransactionsUtxo(view, []*bc.Tx{newTx}); err != nil {
- c.txPool.AddErrCache(&newTx.ID, err)
- return err
+ if err := c.GetTransactionsUtxo(view, []*bc.Tx{tx.Tx}); err != nil {
+ return true, err
}
- if err := view.ApplyTransaction(block, newTx, false); err != nil {
- c.txPool.AddErrCache(&newTx.ID, err)
- return err
+
+ bh := c.BestBlockHeader()
+ block := types.MapBlock(&types.Block{BlockHeader: *bh})
+ if err := view.ApplyTransaction(block, tx.Tx, false); err != nil {
+ return true, err
}
- // validate the BVM contract
- gasOnlyTx := false
- gasStatus, err := validation.ValidateTx(newTx, block)
- if err != nil {
- if gasStatus == nil || !gasStatus.GasVaild {
- c.txPool.AddErrCache(&newTx.ID, err)
- return err
- }
- gasOnlyTx = true
+ gasStatus, err := validation.ValidateTx(tx.Tx, block)
+ if gasStatus.GasValid == false {
+ c.txPool.AddErrCache(&tx.ID, err)
+ return false, err
}
- _, err = c.txPool.AddTransaction(tx, gasOnlyTx, block.BlockHeader.Height, gasStatus.BTMValue)
- return err
+ _, err = c.txPool.AddTransaction(tx, err != nil, block.BlockHeader.Height, gasStatus.BTMValue)
+ return false, err
}