[DEV-91] Increase mempool test coverage part 2 (#107)

* [DEV-91] add TestAddrIndex

* [DEV-91] add TestFeeEstimator

* [DEV-91] rename TestFeeEstimator -> TestFeeEstimatorCfg

* [DEV-91] added TestCount

* [DEV-91] add TestExtractRejectCode in mempool_test.go

* [DEV-91] get rid of fakeErr type and defer unpatching monkey patch

* [DEV-91] use the result of monkey.patch to unpatch
This commit is contained in:
Ori Newman 2018-10-25 18:13:02 +03:00 committed by Svarog
parent 499adbf046
commit c4a541d093
8 changed files with 307 additions and 120 deletions

View File

@ -83,7 +83,7 @@ type blockNode struct {
// diff is the UTXO representation of the block
// A block's UTXO is reconstituted by applying diffWith on every block in the chain of diffChildren
// from the virtual block down to the block. See diffChild
diff *utxoDiff
diff *UTXODiff
// diffChild is the child that diff will be built from. See diff
diffChild *blockNode

View File

@ -570,7 +570,7 @@ func (dag *BlockDAG) connectBlock(node *blockNode, block *util.Block) error {
// 5. Updates each of the tips' utxoDiff.
//
// This function MUST be called with the chain state lock held (for writes).
func (dag *BlockDAG) applyUTXOChanges(node *blockNode, block *util.Block) (utxoDiff *utxoDiff, acceptedTxData []*TxWithBlockHash, err error) {
func (dag *BlockDAG) applyUTXOChanges(node *blockNode, block *util.Block) (utxoDiff *UTXODiff, acceptedTxData []*TxWithBlockHash, err error) {
// Prepare provisionalNodes for all the relevant nodes to avoid modifying the original nodes.
// We avoid modifying the original nodes in this function because it could potentially
// fail if the block is not valid, thus bringing all the affected nodes (and the virtual)
@ -657,7 +657,7 @@ type provisionalNode struct {
selectedParent *provisionalNode
parents []*provisionalNode
children []*provisionalNode
diff *utxoDiff
diff *UTXODiff
diffChild *provisionalNode
transactions []*util.Tx
}
@ -946,7 +946,7 @@ func (dag *BlockDAG) SelectedTip() *blockNode {
}
// UTXOSet returns the DAG's UTXO set
func (dag *BlockDAG) UTXOSet() *fullUTXOSet {
func (dag *BlockDAG) UTXOSet() *FullUTXOSet {
return dag.virtual.utxoSet
}

View File

@ -785,8 +785,8 @@ func TestRestoreUTXOErrors(t *testing.T) {
testErrorThroughPatching(
t,
targetErrorMessage,
(*fullUTXOSet).WithDiff,
func(fus *fullUTXOSet, other *utxoDiff) (UTXOSet, error) {
(*FullUTXOSet).WithDiff,
func(fus *FullUTXOSet, other *UTXODiff) (UTXOSet, error) {
return nil, errors.New(targetErrorMessage)
},
)

View File

@ -613,7 +613,7 @@ func dbFetchUTXOEntry(dbTx database.Tx, outpoint wire.OutPoint) (*UTXOEntry, err
// in the database based on the provided UTXO view contents and state. In
// particular, only the entries that have been marked as modified are written
// to the database.
func dbPutUTXODiff(dbTx database.Tx, diff *utxoDiff) error {
func dbPutUTXODiff(dbTx database.Tx, diff *UTXODiff) error {
utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName)
for outPoint := range diff.toRemove {
key := outpointKey(outPoint)
@ -747,7 +747,7 @@ func (dag *BlockDAG) createDAGState() error {
genesisCoinbaseTxOut := genesisCoinbase.TxOut[0]
genesisCoinbaseOutpoint := *wire.NewOutPoint(&genesisCoinbaseTxIn.PreviousOutPoint.Hash, genesisCoinbaseTxIn.PreviousOutPoint.Index)
genesisCoinbaseUTXOEntry := NewUTXOEntry(genesisCoinbaseTxOut, true, 0)
node.diff = &utxoDiff{
node.diff = &UTXODiff{
toAdd: utxoCollection{genesisCoinbaseOutpoint: genesisCoinbaseUTXOEntry},
toRemove: utxoCollection{},
}

View File

@ -126,15 +126,15 @@ func (uc utxoCollection) clone() utxoCollection {
return clone
}
// utxoDiff represents a diff between two UTXO Sets.
type utxoDiff struct {
// UTXODiff represents a diff between two UTXO Sets.
type UTXODiff struct {
toAdd utxoCollection
toRemove utxoCollection
}
// NewUTXODiff creates a new, empty utxoDiff
func NewUTXODiff() *utxoDiff {
return &utxoDiff{
func NewUTXODiff() *UTXODiff {
return &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
}
@ -168,7 +168,7 @@ func NewUTXODiff() *utxoDiff {
// diffFrom results in an error
// 2. This diff contains a UTXO in toRemove, and the other diff does not contain it
// diffFrom results in the UTXO being added to toAdd
func (d *utxoDiff) diffFrom(other *utxoDiff) (*utxoDiff, error) {
func (d *UTXODiff) diffFrom(other *UTXODiff) (*UTXODiff, error) {
result := NewUTXODiff()
// Note that the following cases are not accounted for, as they are impossible
@ -245,7 +245,7 @@ func (d *utxoDiff) diffFrom(other *utxoDiff) (*utxoDiff, error) {
// WithDiff results in nothing being added
// 2. This diff contains a UTXO in toRemove, and the other diff does not contain it
// WithDiff results in the UTXO being added to toRemove
func (d *utxoDiff) WithDiff(diff *utxoDiff) (*utxoDiff, error) {
func (d *UTXODiff) WithDiff(diff *UTXODiff) (*UTXODiff, error) {
result := NewUTXODiff()
// All transactions in d.toAdd:
@ -294,15 +294,15 @@ func (d *utxoDiff) WithDiff(diff *utxoDiff) (*utxoDiff, error) {
}
// clone returns a clone of this utxoDiff
func (d *utxoDiff) clone() *utxoDiff {
return &utxoDiff{
func (d *UTXODiff) clone() *UTXODiff {
return &UTXODiff{
toAdd: d.toAdd.clone(),
toRemove: d.toRemove.clone(),
}
}
//RemoveTxOuts marks the transaction's outputs to removal
func (d *utxoDiff) RemoveTxOuts(tx *wire.MsgTx) {
func (d *UTXODiff) RemoveTxOuts(tx *wire.MsgTx) {
for idx := range tx.TxOut {
hash := tx.TxHash()
d.toRemove.add(*wire.NewOutPoint(&hash, uint32(idx)), nil)
@ -310,11 +310,11 @@ func (d *utxoDiff) RemoveTxOuts(tx *wire.MsgTx) {
}
//AddEntry adds an UTXOEntry to the diff
func (d *utxoDiff) AddEntry(outpoint wire.OutPoint, entry *UTXOEntry) {
func (d *UTXODiff) AddEntry(outpoint wire.OutPoint, entry *UTXOEntry) {
d.toAdd.add(outpoint, entry)
}
func (d utxoDiff) String() string {
func (d UTXODiff) String() string {
return fmt.Sprintf("toAdd: %s; toRemove: %s", d.toAdd, d.toRemove)
}
@ -347,9 +347,9 @@ func NewUTXOEntry(txOut *wire.TxOut, isCoinbase bool, blockHeight int32) *UTXOEn
// 7. Convert (meld) the new virtual's diffUTXOSet into a fullUTXOSet. This updates the DAG's fullUTXOSet
type UTXOSet interface {
fmt.Stringer
diffFrom(other UTXOSet) (*utxoDiff, error)
WithDiff(utxoDiff *utxoDiff) (UTXOSet, error)
diffFromTx(tx *wire.MsgTx, node *blockNode) (*utxoDiff, error)
diffFrom(other UTXOSet) (*UTXODiff, error)
WithDiff(utxoDiff *UTXODiff) (UTXOSet, error)
diffFromTx(tx *wire.MsgTx, node *blockNode) (*UTXODiff, error)
AddTx(tx *wire.MsgTx, blockHeight int32) (ok bool)
clone() UTXOSet
Get(outPoint wire.OutPoint) (*UTXOEntry, bool)
@ -359,7 +359,7 @@ type UTXOSet interface {
// for both diff-based and full UTXO sets
// Returns a diff that is equivalent to provided transaction,
// or an error if provided transaction is not valid in the context of this UTXOSet
func diffFromTx(u UTXOSet, tx *wire.MsgTx, containingNode *blockNode) (*utxoDiff, error) {
func diffFromTx(u UTXOSet, tx *wire.MsgTx, containingNode *blockNode) (*UTXODiff, error) {
diff := NewUTXODiff()
isCoinbase := IsCoinBaseTx(tx)
if !isCoinbase {
@ -382,21 +382,21 @@ func diffFromTx(u UTXOSet, tx *wire.MsgTx, containingNode *blockNode) (*utxoDiff
return diff, nil
}
// fullUTXOSet represents a full list of transaction outputs and their values
type fullUTXOSet struct {
// FullUTXOSet represents a full list of transaction outputs and their values
type FullUTXOSet struct {
utxoCollection
}
// NewFullUTXOSet creates a new utxoSet with full list of transaction outputs and their values
func NewFullUTXOSet() *fullUTXOSet {
return &fullUTXOSet{
func NewFullUTXOSet() *FullUTXOSet {
return &FullUTXOSet{
utxoCollection: utxoCollection{},
}
}
// diffFrom returns the difference between this utxoSet and another
// diffFrom can only work when other is a diffUTXOSet, and its base utxoSet is this.
func (fus *fullUTXOSet) diffFrom(other UTXOSet) (*utxoDiff, error) {
func (fus *FullUTXOSet) diffFrom(other UTXOSet) (*UTXODiff, error) {
otherDiffSet, ok := other.(*DiffUTXOSet)
if !ok {
return nil, errors.New("can't diffFrom two fullUTXOSets")
@ -410,12 +410,12 @@ func (fus *fullUTXOSet) diffFrom(other UTXOSet) (*utxoDiff, error) {
}
// WithDiff returns a utxoSet which is a diff between this and another utxoSet
func (fus *fullUTXOSet) WithDiff(other *utxoDiff) (UTXOSet, error) {
func (fus *FullUTXOSet) WithDiff(other *UTXODiff) (UTXOSet, error) {
return NewDiffUTXOSet(fus, other.clone()), nil
}
// AddTx adds a transaction to this utxoSet and returns true iff it's valid in this UTXO's context
func (fus *fullUTXOSet) AddTx(tx *wire.MsgTx, blockHeight int32) bool {
func (fus *FullUTXOSet) AddTx(tx *wire.MsgTx, blockHeight int32) bool {
isCoinbase := IsCoinBaseTx(tx)
if !isCoinbase {
if !fus.containsInputs(tx) {
@ -441,11 +441,11 @@ func (fus *fullUTXOSet) AddTx(tx *wire.MsgTx, blockHeight int32) bool {
// diffFromTx returns a diff that is equivalent to provided transaction,
// or an error if provided transaction is not valid in the context of this UTXOSet
func (fus *fullUTXOSet) diffFromTx(tx *wire.MsgTx, node *blockNode) (*utxoDiff, error) {
func (fus *FullUTXOSet) diffFromTx(tx *wire.MsgTx, node *blockNode) (*UTXODiff, error) {
return diffFromTx(fus, tx, node)
}
func (fus *fullUTXOSet) containsInputs(tx *wire.MsgTx) bool {
func (fus *FullUTXOSet) containsInputs(tx *wire.MsgTx) bool {
for _, txIn := range tx.TxIn {
outPoint := *wire.NewOutPoint(&txIn.PreviousOutPoint.Hash, txIn.PreviousOutPoint.Index)
if !fus.contains(outPoint) {
@ -457,23 +457,23 @@ func (fus *fullUTXOSet) containsInputs(tx *wire.MsgTx) bool {
}
// clone returns a clone of this utxoSet
func (fus *fullUTXOSet) clone() UTXOSet {
return &fullUTXOSet{utxoCollection: fus.utxoCollection.clone()}
func (fus *FullUTXOSet) clone() UTXOSet {
return &FullUTXOSet{utxoCollection: fus.utxoCollection.clone()}
}
func (fus *fullUTXOSet) Get(outPoint wire.OutPoint) (*UTXOEntry, bool) {
func (fus *FullUTXOSet) Get(outPoint wire.OutPoint) (*UTXOEntry, bool) {
utxoEntry, ok := fus.utxoCollection[outPoint]
return utxoEntry, ok
}
// DiffUTXOSet represents a utxoSet with a base fullUTXOSet and a UTXODiff
type DiffUTXOSet struct {
base *fullUTXOSet
UTXODiff *utxoDiff
base *FullUTXOSet
UTXODiff *UTXODiff
}
// NewDiffUTXOSet Creates a new utxoSet based on a base fullUTXOSet and a UTXODiff
func NewDiffUTXOSet(base *fullUTXOSet, diff *utxoDiff) *DiffUTXOSet {
func NewDiffUTXOSet(base *FullUTXOSet, diff *UTXODiff) *DiffUTXOSet {
return &DiffUTXOSet{
base: base,
UTXODiff: diff,
@ -482,7 +482,7 @@ func NewDiffUTXOSet(base *fullUTXOSet, diff *utxoDiff) *DiffUTXOSet {
// diffFrom returns the difference between this utxoSet and another.
// diffFrom can work if other is this's base fullUTXOSet, or a diffUTXOSet with the same base as this
func (dus *DiffUTXOSet) diffFrom(other UTXOSet) (*utxoDiff, error) {
func (dus *DiffUTXOSet) diffFrom(other UTXOSet) (*UTXODiff, error) {
otherDiffSet, ok := other.(*DiffUTXOSet)
if !ok {
return nil, errors.New("can't diffFrom diffUTXOSet with fullUTXOSet")
@ -496,7 +496,7 @@ func (dus *DiffUTXOSet) diffFrom(other UTXOSet) (*utxoDiff, error) {
}
// WithDiff return a new utxoSet which is a diffFrom between this and another utxoSet
func (dus *DiffUTXOSet) WithDiff(other *utxoDiff) (UTXOSet, error) {
func (dus *DiffUTXOSet) WithDiff(other *UTXODiff) (UTXOSet, error) {
diff, err := dus.UTXODiff.WithDiff(other)
if err != nil {
return nil, err
@ -573,7 +573,7 @@ func (dus *DiffUTXOSet) meldToBase() {
// diffFromTx returns a diff that is equivalent to provided transaction,
// or an error if provided transaction is not valid in the context of this UTXOSet
func (dus *DiffUTXOSet) diffFromTx(tx *wire.MsgTx, node *blockNode) (*utxoDiff, error) {
func (dus *DiffUTXOSet) diffFromTx(tx *wire.MsgTx, node *blockNode) (*UTXODiff, error) {
return diffFromTx(dus, tx, node)
}
@ -583,7 +583,7 @@ func (dus *DiffUTXOSet) String() string {
// clone returns a clone of this UTXO Set
func (dus *DiffUTXOSet) clone() UTXOSet {
return NewDiffUTXOSet(dus.base.clone().(*fullUTXOSet), dus.UTXODiff.clone())
return NewDiffUTXOSet(dus.base.clone().(*FullUTXOSet), dus.UTXODiff.clone())
}
// Get returns the UTXOEntry associated with provided outPoint in this UTXOSet.

View File

@ -81,7 +81,7 @@ func TestUTXODiff(t *testing.T) {
outPoint1 := *wire.NewOutPoint(hash1, 0)
utxoEntry0 := NewUTXOEntry(&wire.TxOut{PkScript: []byte{}, Value: 10}, true, 0)
utxoEntry1 := NewUTXOEntry(&wire.TxOut{PkScript: []byte{}, Value: 20}, false, 1)
diff := utxoDiff{
diff := UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{outPoint1: utxoEntry1},
}
@ -125,22 +125,22 @@ func TestUTXODiffRules(t *testing.T) {
// Note: an expected nil result means that we expect the respective operation to fail
tests := []struct {
name string
this *utxoDiff
other *utxoDiff
expectedDiffFromResult *utxoDiff
expectedWithDiffResult *utxoDiff
this *UTXODiff
other *UTXODiff
expectedDiffFromResult *UTXODiff
expectedWithDiffResult *UTXODiff
}{
{
name: "one toAdd in this, one toAdd in other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
expectedDiffFromResult: &utxoDiff{
expectedDiffFromResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -148,66 +148,66 @@ func TestUTXODiffRules(t *testing.T) {
},
{
name: "one toAdd in this, one toRemove in other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
expectedDiffFromResult: nil,
expectedWithDiffResult: &utxoDiff{
expectedWithDiffResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
},
{
name: "one toAdd in this, empty other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
expectedDiffFromResult: &utxoDiff{
expectedDiffFromResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
expectedWithDiffResult: &utxoDiff{
expectedWithDiffResult: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
},
{
name: "one toRemove in this, one toAdd in other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
expectedDiffFromResult: nil,
expectedWithDiffResult: &utxoDiff{
expectedWithDiffResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
},
{
name: "one toRemove in this, one toRemove in other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
expectedDiffFromResult: &utxoDiff{
expectedDiffFromResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -215,76 +215,76 @@ func TestUTXODiffRules(t *testing.T) {
},
{
name: "one toRemove in this, empty other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
expectedDiffFromResult: &utxoDiff{
expectedDiffFromResult: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
expectedWithDiffResult: &utxoDiff{
expectedWithDiffResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
},
{
name: "empty this, one toAdd in other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
expectedDiffFromResult: &utxoDiff{
expectedDiffFromResult: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
expectedWithDiffResult: &utxoDiff{
expectedWithDiffResult: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
},
{
name: "empty this, one toRemove in other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
expectedDiffFromResult: &utxoDiff{
expectedDiffFromResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
expectedWithDiffResult: &utxoDiff{
expectedWithDiffResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
},
{
name: "empty this, empty other",
this: &utxoDiff{
this: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
other: &utxoDiff{
other: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
expectedDiffFromResult: &utxoDiff{
expectedDiffFromResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
expectedWithDiffResult: &utxoDiff{
expectedWithDiffResult: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -338,7 +338,7 @@ func TestFullUTXOSet(t *testing.T) {
txOut1 := &wire.TxOut{PkScript: []byte{}, Value: 20}
utxoEntry0 := NewUTXOEntry(txOut0, true, 0)
utxoEntry1 := NewUTXOEntry(txOut1, false, 1)
diff := &utxoDiff{
diff := &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{outPoint1: utxoEntry1},
}
@ -370,7 +370,7 @@ func TestFullUTXOSet(t *testing.T) {
if ok = emptySet.AddTx(transaction0, 0); ok {
t.Errorf("addTx unexpectedly succeeded")
}
emptySet = &fullUTXOSet{utxoCollection: utxoCollection{outPoint0: utxoEntry0}}
emptySet = &FullUTXOSet{utxoCollection: utxoCollection{outPoint0: utxoEntry0}}
if ok = emptySet.AddTx(transaction0, 0); !ok {
t.Errorf("addTx unexpectedly failed")
}
@ -381,7 +381,7 @@ func TestFullUTXOSet(t *testing.T) {
}
// Test fullUTXOSet cloning
clonedEmptySet := emptySet.clone().(*fullUTXOSet)
clonedEmptySet := emptySet.clone().(*FullUTXOSet)
if !reflect.DeepEqual(clonedEmptySet, emptySet) {
t.Errorf("clone does not equal the original set")
}
@ -400,7 +400,7 @@ func TestDiffUTXOSet(t *testing.T) {
txOut1 := &wire.TxOut{PkScript: []byte{}, Value: 20}
utxoEntry0 := NewUTXOEntry(txOut0, true, 0)
utxoEntry1 := NewUTXOEntry(txOut1, false, 1)
diff := &utxoDiff{
diff := &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{outPoint1: utxoEntry1},
}
@ -446,14 +446,14 @@ func TestDiffUTXOSet(t *testing.T) {
name: "empty base, empty diff",
diffSet: &DiffUTXOSet{
base: NewFullUTXOSet(),
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
},
expectedMeldSet: &DiffUTXOSet{
base: NewFullUTXOSet(),
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -465,14 +465,14 @@ func TestDiffUTXOSet(t *testing.T) {
name: "empty base, one member in diff toAdd",
diffSet: &DiffUTXOSet{
base: NewFullUTXOSet(),
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{outPoint0: utxoEntry0},
toRemove: utxoCollection{},
},
},
expectedMeldSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{outPoint0: utxoEntry0}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{outPoint0: utxoEntry0}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -484,14 +484,14 @@ func TestDiffUTXOSet(t *testing.T) {
name: "empty base, one member in diff toRemove",
diffSet: &DiffUTXOSet{
base: NewFullUTXOSet(),
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
},
expectedMeldSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -502,20 +502,20 @@ func TestDiffUTXOSet(t *testing.T) {
{
name: "one member in base toAdd, one member in diff toAdd",
diffSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{outPoint0: utxoEntry0}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{outPoint0: utxoEntry0}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{outPoint1: utxoEntry1},
toRemove: utxoCollection{},
},
},
expectedMeldSet: &DiffUTXOSet{
base: &fullUTXOSet{
base: &FullUTXOSet{
utxoCollection: utxoCollection{
outPoint0: utxoEntry0,
outPoint1: utxoEntry1,
},
},
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -529,17 +529,17 @@ func TestDiffUTXOSet(t *testing.T) {
{
name: "one member in base toAdd, same one member in diff toRemove",
diffSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{outPoint0: utxoEntry0}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{outPoint0: utxoEntry0}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{outPoint0: utxoEntry0},
},
},
expectedMeldSet: &DiffUTXOSet{
base: &fullUTXOSet{
base: &FullUTXOSet{
utxoCollection: utxoCollection{},
},
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -685,8 +685,8 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
startHeight: 0,
toAdd: []*wire.MsgTx{transaction0},
expectedSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{outPoint1: utxoEntry0},
toRemove: utxoCollection{},
},
@ -698,8 +698,8 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
startHeight: 0,
toAdd: []*wire.MsgTx{transaction1},
expectedSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -708,8 +708,8 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
{
name: "add transaction to set with its input in base",
startSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{outPoint1: utxoEntry0}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{outPoint1: utxoEntry0}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -717,8 +717,8 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
startHeight: 1,
toAdd: []*wire.MsgTx{transaction1},
expectedSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{outPoint1: utxoEntry0}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{outPoint1: utxoEntry0}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{outPoint2: utxoEntry1},
toRemove: utxoCollection{outPoint1: utxoEntry0},
},
@ -728,7 +728,7 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
name: "add transaction to set with its input in diff toAdd",
startSet: &DiffUTXOSet{
base: NewFullUTXOSet(),
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{outPoint1: utxoEntry0},
toRemove: utxoCollection{},
},
@ -737,7 +737,7 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
toAdd: []*wire.MsgTx{transaction1},
expectedSet: &DiffUTXOSet{
base: NewFullUTXOSet(),
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{outPoint2: utxoEntry1},
toRemove: utxoCollection{},
},
@ -747,7 +747,7 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
name: "add transaction to set with its input in diff toAdd and its output in diff toRemove",
startSet: &DiffUTXOSet{
base: NewFullUTXOSet(),
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{outPoint1: utxoEntry0},
toRemove: utxoCollection{outPoint2: utxoEntry1},
},
@ -756,7 +756,7 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
toAdd: []*wire.MsgTx{transaction1},
expectedSet: &DiffUTXOSet{
base: NewFullUTXOSet(),
UTXODiff: &utxoDiff{
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -765,8 +765,8 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
{
name: "add two transactions, one spending the other, to set with the first input in base",
startSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{outPoint1: utxoEntry0}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{outPoint1: utxoEntry0}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
},
@ -774,8 +774,8 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
startHeight: 1,
toAdd: []*wire.MsgTx{transaction1, transaction2},
expectedSet: &DiffUTXOSet{
base: &fullUTXOSet{utxoCollection: utxoCollection{outPoint1: utxoEntry0}},
UTXODiff: &utxoDiff{
base: &FullUTXOSet{utxoCollection: utxoCollection{outPoint1: utxoEntry0}},
UTXODiff: &UTXODiff{
toAdd: utxoCollection{outPoint3: utxoEntry2},
toRemove: utxoCollection{outPoint1: utxoEntry0},
},
@ -912,7 +912,7 @@ func TestApplyUTXOChanges(t *testing.T) {
}
func TestDiffFromTx(t *testing.T) {
fus := &fullUTXOSet{
fus := &FullUTXOSet{
utxoCollection: utxoCollection{},
}
cbTx, err := createCoinbaseTx(1, 1)
@ -965,7 +965,7 @@ func TestDiffFromTx(t *testing.T) {
}
//Test that we get an error if the outpoint is inside diffUTXOSet's toRemove
dus := NewDiffUTXOSet(fus, &utxoDiff{
dus := NewDiffUTXOSet(fus, &UTXODiff{
toAdd: utxoCollection{},
toRemove: utxoCollection{},
})
@ -977,7 +977,7 @@ func TestDiffFromTx(t *testing.T) {
}
// collection returns a collection of all UTXOs in this set
func (fus *fullUTXOSet) collection() utxoCollection {
func (fus *FullUTXOSet) collection() utxoCollection {
return fus.utxoCollection.clone()
}

View File

@ -12,7 +12,7 @@ import (
type virtualBlock struct {
mtx sync.Mutex
phantomK uint32
utxoSet *fullUTXOSet
utxoSet *FullUTXOSet
blockNode
// selectedPathSet is a block set that includes all the blocks that belong to the chain of selected parents from the virtual block.
selectedPathSet blockSet
@ -34,7 +34,7 @@ func newVirtualBlock(tips blockSet, phantomK uint32) *virtualBlock {
func (v *virtualBlock) clone() *virtualBlock {
return &virtualBlock{
phantomK: v.phantomK,
utxoSet: v.utxoSet.clone().(*fullUTXOSet),
utxoSet: v.utxoSet.clone().(*FullUTXOSet),
blockNode: v.blockNode,
selectedPathSet: v.selectedPathSet,
}

View File

@ -7,6 +7,7 @@ package mempool
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"math"
"reflect"
@ -15,7 +16,9 @@ import (
"testing"
"time"
"bou.ke/monkey"
"github.com/daglabs/btcd/blockdag"
"github.com/daglabs/btcd/blockdag/indexers"
"github.com/daglabs/btcd/btcec"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/dagconfig/daghash"
@ -695,6 +698,72 @@ func TestProcessTransaction(t *testing.T) {
}
func TestAddrIndex(t *testing.T) {
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestAddrIndex")
if err != nil {
t.Fatalf("unable to create test pool: %v", err)
}
harness.txPool.cfg.AddrIndex = &indexers.AddrIndex{}
enteredAddUnconfirmedTx := false
guard := monkey.Patch((*indexers.AddrIndex).AddUnconfirmedTx, func(idx *indexers.AddrIndex, tx *util.Tx, utxoSet blockdag.UTXOSet) {
enteredAddUnconfirmedTx = true
})
defer guard.Unpatch()
enteredRemoveUnconfirmedTx := false
guard = monkey.Patch((*indexers.AddrIndex).RemoveUnconfirmedTx, func(idx *indexers.AddrIndex, hash *daghash.Hash) {
enteredRemoveUnconfirmedTx = true
})
defer guard.Unpatch()
tx, err := harness.createTx(spendableOuts[0], 0, 1)
if err != nil {
t.Fatalf("unable to create transaction: %v", err)
}
_, err = harness.txPool.ProcessTransaction(tx, true, false, 0)
if err != nil {
t.Errorf("ProcessTransaction: unexpected error: %v", err)
}
if !enteredAddUnconfirmedTx {
t.Errorf("TestAddrIndex: (*indexers.AddrIndex).AddUnconfirmedTx was not called")
}
err = harness.txPool.RemoveTransaction(tx, false, false)
if err != nil {
t.Errorf("TestAddrIndex: unexpected error: %v", err)
}
if !enteredRemoveUnconfirmedTx {
t.Errorf("TestAddrIndex: (*indexers.AddrIndex).RemoveUnconfirmedTx was not called")
}
}
func TestFeeEstimatorCfg(t *testing.T) {
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestFeeEstimatorCfg")
if err != nil {
t.Fatalf("unable to create test pool: %v", err)
}
harness.txPool.cfg.FeeEstimator = &FeeEstimator{}
enteredObserveTransaction := false
guard := monkey.Patch((*FeeEstimator).ObserveTransaction, func(ef *FeeEstimator, t *TxDesc) {
enteredObserveTransaction = true
})
defer guard.Unpatch()
tx, err := harness.createTx(spendableOuts[0], 0, 1)
if err != nil {
t.Fatalf("unable to create transaction: %v", err)
}
_, err = harness.txPool.ProcessTransaction(tx, true, false, 0)
if err != nil {
t.Errorf("ProcessTransaction: unexpected error: %v", err)
}
if !enteredObserveTransaction {
t.Errorf("TestFeeEstimatorCfg: (*FeeEstimator).ObserveTransaction was not called")
}
}
func TestDoubleSpends(t *testing.T) {
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestDoubleSpends")
if err != nil {
@ -1003,6 +1072,16 @@ func TestRemoveTransaction(t *testing.T) {
testPoolMembership(tc, chainedTxns[0], false, true)
testPoolMembership(tc, chainedTxns[1], false, false)
testPoolMembership(tc, chainedTxns[2], false, false)
fakeWithDiffErr := "error from WithDiff"
guard := monkey.Patch((*blockdag.DiffUTXOSet).WithDiff, func(_ *blockdag.DiffUTXOSet, _ *blockdag.UTXODiff) (blockdag.UTXOSet, error) {
return nil, errors.New(fakeWithDiffErr)
})
defer guard.Unpatch()
err = harness.txPool.RemoveTransaction(chainedTxns[0], false, false)
if err == nil || err.Error() != fakeWithDiffErr {
t.Errorf("RemoveTransaction: expected error %v but got %v", fakeWithDiffErr, err)
}
}
// TestOrphanEviction ensures that exceeding the maximum number of orphans
@ -1408,3 +1487,111 @@ func TestCheckSpend(t *testing.T) {
t.Fatalf("Unexpeced spend found in pool: %v", spend)
}
}
func TestCount(t *testing.T) {
harness, outputs, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestCount")
if err != nil {
t.Fatalf("unable to create test pool: %v", err)
}
if harness.txPool.Count() != 0 {
t.Errorf("TestCount: txPool should be initialized with 0 transactions")
}
chainedTxns, err := harness.CreateTxChain(outputs[0], 3)
if err != nil {
t.Fatalf("harness.CreateTxChain: unexpected error: %v", err)
}
for i, tx := range chainedTxns {
_, err = harness.txPool.ProcessTransaction(tx, true, false, 0)
if err != nil {
t.Errorf("ProcessTransaction: unexpected error: %v", err)
}
if harness.txPool.Count() != i+1 {
t.Errorf("TestCount: txPool expected to have %v transactions but got %v", i+1, harness.txPool.Count())
}
}
err = harness.txPool.RemoveTransaction(chainedTxns[0], false, false)
if err != nil {
t.Fatalf("harness.CreateTxChain: unexpected error: %v", err)
}
if harness.txPool.Count() != 2 {
t.Errorf("TestCount: txPool expected to have 2 transactions but got %v", harness.txPool.Count())
}
}
func TestExtractRejectCode(t *testing.T) {
tests := []struct {
blockdagRuleErrorCode blockdag.ErrorCode
wireRejectCode wire.RejectCode
}{
{
blockdagRuleErrorCode: blockdag.ErrDuplicateBlock,
wireRejectCode: wire.RejectDuplicate,
},
{
blockdagRuleErrorCode: blockdag.ErrBlockVersionTooOld,
wireRejectCode: wire.RejectObsolete,
},
{
blockdagRuleErrorCode: blockdag.ErrCheckpointTimeTooOld,
wireRejectCode: wire.RejectCheckpoint,
},
{
blockdagRuleErrorCode: blockdag.ErrDifficultyTooLow,
wireRejectCode: wire.RejectCheckpoint,
},
{
blockdagRuleErrorCode: blockdag.ErrBadCheckpoint,
wireRejectCode: wire.RejectCheckpoint,
},
{
blockdagRuleErrorCode: blockdag.ErrForkTooOld,
wireRejectCode: wire.RejectCheckpoint,
},
{
blockdagRuleErrorCode: math.MaxUint32,
wireRejectCode: wire.RejectInvalid,
},
}
for _, test := range tests {
err := blockdag.RuleError{ErrorCode: test.blockdagRuleErrorCode}
code, ok := extractRejectCode(err)
if !ok {
t.Errorf("TestExtractRejectCode: %v could not be extracted", test.blockdagRuleErrorCode)
}
if test.wireRejectCode != code {
t.Errorf("TestExtractRejectCode: expected %v to extract %v but got %v", test.blockdagRuleErrorCode, test.wireRejectCode, code)
}
}
txRuleError := TxRuleError{RejectCode: wire.RejectDust}
txExtractedCode, ok := extractRejectCode(txRuleError)
if !ok {
t.Errorf("TestExtractRejectCode: %v could not be extracted", txRuleError)
}
if txExtractedCode != wire.RejectDust {
t.Errorf("TestExtractRejectCode: expected %v to extract %v but got %v", wire.RejectDust, wire.RejectDust, txExtractedCode)
}
var nilErr error
nilErrExtractedCode, ok := extractRejectCode(nilErr)
if nilErrExtractedCode != wire.RejectInvalid {
t.Errorf("TestExtractRejectCode: expected %v to extract %v but got %v", wire.RejectInvalid, wire.RejectInvalid, nilErrExtractedCode)
}
if ok {
t.Errorf("TestExtractRejectCode: a nil error is expected to return false but got %v", ok)
}
nonRuleError := errors.New("nonRuleError")
fErrExtractedCode, ok := extractRejectCode(nonRuleError)
if fErrExtractedCode != wire.RejectInvalid {
t.Errorf("TestExtractRejectCode: expected %v to extract %v but got %v", wire.RejectInvalid, wire.RejectInvalid, nilErrExtractedCode)
}
if ok {
t.Errorf("TestExtractRejectCode: a nonRuleError is expected to return false but got %v", ok)
}
}