diff --git a/core/ledger/validator.go b/core/ledger/validator.go index 42d5b7686..e18c6f53c 100644 --- a/core/ledger/validator.go +++ b/core/ledger/validator.go @@ -54,13 +54,13 @@ func TransactionCheck(block *Block) error { if errCode := tx.VerifyTransaction(txn); errCode != ErrNoError { return errors.New("transaction sanity check failed") } - if errCode := tx.VerifyTransactionWithBlock(TransactionArray(block.Transactions)); errCode != ErrNoError { - return errors.New("transaction block check failed") - } if errCode := tx.VerifyTransactionWithLedger(txn); errCode != ErrNoError { return errors.New("transaction history check failed") } } + if errCode := tx.VerifyTransactionWithBlock(TransactionArray(block.Transactions)); errCode != ErrNoError { + return errors.New("transaction block check failed") + } return nil } diff --git a/core/transaction/pool/pool.go b/core/transaction/pool/pool.go index fb84138d3..8ae74ad0a 100644 --- a/core/transaction/pool/pool.go +++ b/core/transaction/pool/pool.go @@ -51,10 +51,6 @@ func (tp *TxnPool) AppendTxnPool(txn *Transaction) ErrCode { log.Info("Transaction verification failed", txn.Hash()) return errCode } - if errCode := VerifyTransactionWithBlock(TransactionMap(tp.txnList)); errCode != ErrNoError { - log.Info("Transaction verification with block failed", txn.Hash()) - return errCode - } if errCode := VerifyTransactionWithLedger(txn); errCode != ErrNoError { log.Info("Transaction verification with ledger failed", txn.Hash()) return errCode @@ -72,7 +68,16 @@ func (tp *TxnPool) AppendTxnPool(txn *Transaction) ErrCode { } //add the transaction to process scope - tp.addtxnList(txn) + if tp.addtxnList(txn) { + // Check duplicate UTXO reference after append successful + if errCode := VerifyTransactionWithBlock(TransactionMap(tp.txnList)); errCode != ErrNoError { + log.Info("Transaction verification with block failed", txn.Hash()) + tp.deltxnList(txn) // Revert previous append action + return errCode + } + } else { + return ErrDuplicatedTx // Don't broadcast this txn if hash duplicated + } return ErrNoError } diff --git a/core/transaction/validator.go b/core/transaction/validator.go index 74a38db51..8a7bb2ca6 100644 --- a/core/transaction/validator.go +++ b/core/transaction/validator.go @@ -180,15 +180,13 @@ func VerifyTransactionWithLedger(Tx *Transaction) ErrCode { //validate the transaction of duplicate UTXO input func CheckDuplicateInput(tx *Transaction) error { - if len(tx.Inputs) == 0 { - return nil - } - for i, utxoin := range tx.Inputs { - for j := 0; j < i; j++ { - if utxoin.ReferTxID == tx.Inputs[j].ReferTxID && utxoin.ReferTxOutputIndex == tx.Inputs[j].ReferTxOutputIndex { - return errors.New("invalid transaction") - } + dupMap := make(map[string]struct{}) + for _, utxoin := range tx.Inputs { + k := utxoin.ToString() + if _, ok := dupMap[k]; ok { // ok means duplicate + return errors.New("invalid transaction") } + dupMap[k] = struct{}{} } return nil } diff --git a/db/store.go b/db/store.go index aa32f635a..d9432fadf 100644 --- a/db/store.go +++ b/db/store.go @@ -251,11 +251,7 @@ func (cs *ChainStore) InitLedgerStoreWithGenesisBlock(genesisBlock *Block) (uint func (cs *ChainStore) IsTxHashDuplicate(txhash Uint256) bool { prefix := []byte{byte(DATA_Transaction)} _, err_get := cs.st.Get(append(prefix, txhash.ToArray()...)) - if err_get != nil { - return false - } else { - return true - } + return err_get == nil } func (cs *ChainStore) IsDoubleSpend(tx *tx.Transaction) bool {