OSDN Git Service

Merge pull request #935 from Bytom/dev
[bytom/bytom.git] / protocol / tx.go
index 3d8020d..38a5ab9 100644 (file)
@@ -1,70 +1,51 @@
 package protocol
 
 import (
-       "sync"
-
-       "github.com/golang/groupcache/lru"
-
        "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")
 
-// ValidateTx validates the given transaction. A cache holds
-// per-transaction validation results and is consulted before
-// performing full validation.
-func (c *Chain) ValidateTx(tx *bc.Tx) error {
-       err := c.checkIssuanceWindow(tx)
-       if err != nil {
-               return err
-       }
-       var ok bool
-       err, ok = c.prevalidated.lookup(tx.ID)
-       if !ok {
-               //TODO: fix the cache level things
-               _, err = validation.ValidateTx(tx, nil)
-               c.prevalidated.cache(tx.ID, err)
-       }
-       return errors.Sub(ErrBadTx, err)
+// GetTransactionStatus return the transaction status of give block
+func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
+       return c.store.GetTransactionStatus(hash)
 }
 
-type prevalidatedTxsCache struct {
-       mu  sync.Mutex
-       lru *lru.Cache
+// 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)
 }
 
-func (c *prevalidatedTxsCache) lookup(txID bc.Hash) (err error, ok bool) {
-       c.mu.Lock()
-       v, ok := c.lru.Get(txID)
-       c.mu.Unlock()
-       if !ok {
-               return err, ok
-       }
-       if v == nil {
-               return nil, ok
+// 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) (bool, error) {
+       if ok := c.txPool.HaveTransaction(&tx.ID); ok {
+               return false, c.txPool.GetErrCache(&tx.ID)
        }
-       return v.(error), ok
-}
 
-func (c *prevalidatedTxsCache) cache(txID bc.Hash, err error) {
-       c.mu.Lock()
-       c.lru.Add(txID, err)
-       c.mu.Unlock()
-}
+       view := c.txPool.GetTransactionUTXO(tx.Tx)
+       if err := c.GetTransactionsUtxo(view, []*bc.Tx{tx.Tx}); err != nil {
+               return true, err
+       }
 
-func (c *Chain) checkIssuanceWindow(tx *bc.Tx) error {
-       if c.MaxIssuanceWindow == 0 {
-               return nil
+       bh := c.BestBlockHeader()
+       block := types.MapBlock(&types.Block{BlockHeader: *bh})
+       if err := view.ApplyTransaction(block, tx.Tx, false); err != nil {
+               return true, err
        }
-       for _, entryID := range tx.InputIDs {
-               if _, err := tx.Issuance(entryID); err == nil {
-                       if tx.MinTimeMs+bc.DurationMillis(c.MaxIssuanceWindow) < tx.MaxTimeMs {
-                               return errors.WithDetailf(ErrBadTx, "issuance input's time window is larger than the network maximum (%s)", c.MaxIssuanceWindow)
-                       }
-               }
+
+       gasStatus, err := validation.ValidateTx(tx.Tx, block)
+       if gasStatus.GasValid == false {
+               c.txPool.AddErrCache(&tx.ID, err)
+               return false, err
        }
-       return nil
+
+       _, err = c.txPool.AddTransaction(tx, err != nil, block.BlockHeader.Height, gasStatus.BTMValue)
+       return false, err
 }