wtxmgr: add InsertTxCheckIfExsists to check if a tx already recorded

Adds new error `ErrDuplicateTx` and method `InserTxCheckIfExists` to check if a transaction to be inserted was already recorded.
This commit is contained in:
Bjarne Magnussen 2021-05-28 14:29:48 +02:00
parent 6ab9b61557
commit 0066eee3ea
No known key found for this signature in database
GPG key ID: B0A9ADF6B24CE67F
3 changed files with 43 additions and 5 deletions

View file

@ -55,6 +55,10 @@ var (
// ErrOutputUnlockNotAllowed is an error returned when an output unlock // ErrOutputUnlockNotAllowed is an error returned when an output unlock
// is attempted with a different ID than the one which locked it. // is attempted with a different ID than the one which locked it.
ErrOutputUnlockNotAllowed = errors.New("output unlock not alowed") ErrOutputUnlockNotAllowed = errors.New("output unlock not alowed")
// ErrDuplicateTx is returned when attempting to record a mined or
// unmined transaction that is already recorded.
ErrDuplicateTx = errors.New("transaction already exists")
) )
// Block contains the minimum amount of data to uniquely identify any block on // Block contains the minimum amount of data to uniquely identify any block on
@ -355,11 +359,30 @@ func (s *Store) deleteUnminedTx(ns walletdb.ReadWriteBucket, rec *TxRecord) erro
// InsertTx records a transaction as belonging to a wallet's transaction // InsertTx records a transaction as belonging to a wallet's transaction
// history. If block is nil, the transaction is considered unspent, and the // history. If block is nil, the transaction is considered unspent, and the
// transaction's index must be unset. // transaction's index must be unset.
func (s *Store) InsertTx(ns walletdb.ReadWriteBucket, rec *TxRecord, block *BlockMeta) error { func (s *Store) InsertTx(ns walletdb.ReadWriteBucket, rec *TxRecord,
block *BlockMeta) error {
_, err := s.InsertTxCheckIfExists(ns, rec, block)
return err
}
// InsertTxCheckIfExists records a transaction as belonging to a wallet's
// transaction history. If block is nil, the transaction is considered unspent,
// and the transaction's index must be unset. It will return true if the
// transaction was already recorded prior to the call.
func (s *Store) InsertTxCheckIfExists(ns walletdb.ReadWriteBucket,
rec *TxRecord, block *BlockMeta) (bool, error) {
var err error
if block == nil { if block == nil {
return s.insertMemPoolTx(ns, rec) if err = s.insertMemPoolTx(ns, rec); err == ErrDuplicateTx {
return true, nil
} }
return s.insertMinedTx(ns, rec, block) return false, err
}
if err = s.insertMinedTx(ns, rec, block); err == ErrDuplicateTx {
return true, nil
}
return false, err
} }
// RemoveUnminedTx attempts to remove an unmined transaction from the // RemoveUnminedTx attempts to remove an unmined transaction from the
@ -386,7 +409,7 @@ func (s *Store) insertMinedTx(ns walletdb.ReadWriteBucket, rec *TxRecord,
// If a transaction record for this hash and block already exists, we // If a transaction record for this hash and block already exists, we
// can exit early. // can exit early.
if _, v := existsTxRecord(ns, &rec.Hash, &block.Block); v != nil { if _, v := existsTxRecord(ns, &rec.Hash, &block.Block); v != nil {
return nil return ErrDuplicateTx
} }
// If a block record does not yet exist for any transactions from this // If a block record does not yet exist for any transactions from this

View file

@ -7,6 +7,7 @@ package wtxmgr
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
@ -192,6 +193,13 @@ func TestInsertsCreditsDebitsRollbacks(t *testing.T) {
return nil, err return nil, err
} }
// Check that the duplicate transaction is found.
if exists, _ := s.InsertTxCheckIfExists(ns, rec, nil); !exists {
return nil, fmt.Errorf(
"duplicate transaction was not found as already recorded",
)
}
err = s.AddCredit(ns, rec, nil, 0, false) err = s.AddCredit(ns, rec, nil, 0, false)
return s, err return s, err
}, },
@ -244,6 +252,13 @@ func TestInsertsCreditsDebitsRollbacks(t *testing.T) {
return nil, err return nil, err
} }
// Make sure the duplicate transaction is found.
if exists, _ := s.InsertTxCheckIfExists(ns, rec, TstRecvTxBlockDetails); !exists {
return nil, fmt.Errorf(
"duplicate transaction was not found as already recorded",
)
}
err = s.AddCredit(ns, rec, TstRecvTxBlockDetails, 0, false) err = s.AddCredit(ns, rec, TstRecvTxBlockDetails, 0, false)
return s, err return s, err
}, },

View file

@ -22,7 +22,7 @@ func (s *Store) insertMemPoolTx(ns walletdb.ReadWriteBucket, rec *TxRecord) erro
// TODO: compare serialized txs to ensure this isn't a hash // TODO: compare serialized txs to ensure this isn't a hash
// collision? // collision?
if txDetails, _ := s.TxDetails(ns, &rec.Hash); txDetails != nil { if txDetails, _ := s.TxDetails(ns, &rec.Hash); txDetails != nil {
return nil return ErrDuplicateTx
} }
// Since transaction records within the store are keyed by their // Since transaction records within the store are keyed by their