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:
parent
6ab9b61557
commit
0066eee3ea
3 changed files with 43 additions and 5 deletions
33
wtxmgr/tx.go
33
wtxmgr/tx.go
|
@ -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,
|
||||||
if block == nil {
|
block *BlockMeta) error {
|
||||||
return s.insertMemPoolTx(ns, rec)
|
_, err := s.InsertTxCheckIfExists(ns, rec, block)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return s.insertMinedTx(ns, rec, block)
|
|
||||||
|
// 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 err = s.insertMemPoolTx(ns, rec); err == ErrDuplicateTx {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
|
@ -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
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue