mempool_test.go raw

   1  package mempool
   2  
   3  import (
   4  	"encoding/hex"
   5  	"github.com/p9c/p9/pkg/amt"
   6  	"github.com/p9c/p9/pkg/btcaddr"
   7  	"reflect"
   8  	"runtime"
   9  	"sync"
  10  	"testing"
  11  	"time"
  12  	
  13  	"github.com/p9c/p9/pkg/blockchain"
  14  	"github.com/p9c/p9/pkg/chaincfg"
  15  	"github.com/p9c/p9/pkg/chainhash"
  16  	"github.com/p9c/p9/pkg/ecc"
  17  	"github.com/p9c/p9/pkg/txscript"
  18  	"github.com/p9c/p9/pkg/util"
  19  	"github.com/p9c/p9/pkg/wire"
  20  )
  21  
  22  // fakeChain is used by the pool harness to provide generated test utxos and a current faked chain height to the pool
  23  // callbacks. This, in turn, allows transactions to appear as though they are spending completely valid utxos.
  24  type fakeChain struct {
  25  	sync.RWMutex
  26  	utxos          *blockchain.UtxoViewpoint
  27  	currentHeight  int32
  28  	medianTimePast time.Time
  29  }
  30  
  31  // FetchUtxoView loads utxo details about the inputs referenced by the passed transaction from the point of view of the
  32  // fake chain. It also attempts to fetch the utxos for the outputs of the transaction itself so the returned view can be
  33  // examined for duplicate transactions. This function is safe for concurrent access however the returned view is NOT.
  34  func (s *fakeChain) FetchUtxoView(tx *util.Tx) (*blockchain.UtxoViewpoint, error) {
  35  	s.RLock()
  36  	defer s.RUnlock()
  37  	// All entries are cloned to ensure modifications to the returned view do not affect the fake chain's view. Add an
  38  	// entry for the tx itself to the new view.
  39  	viewpoint := blockchain.NewUtxoViewpoint()
  40  	prevOut := wire.OutPoint{Hash: *tx.Hash()}
  41  	for txOutIdx := range tx.MsgTx().TxOut {
  42  		prevOut.Index = uint32(txOutIdx)
  43  		entry := s.utxos.LookupEntry(prevOut)
  44  		viewpoint.Entries()[prevOut] = entry.Clone()
  45  	}
  46  	// Add entries for all of the inputs to the tx to the new view.
  47  	for _, txIn := range tx.MsgTx().TxIn {
  48  		entry := s.utxos.LookupEntry(txIn.PreviousOutPoint)
  49  		viewpoint.Entries()[txIn.PreviousOutPoint] = entry.Clone()
  50  	}
  51  	return viewpoint, nil
  52  }
  53  
  54  // BestHeight returns the current height associated with the fake chain instance.
  55  func (s *fakeChain) BestHeight() int32 {
  56  	s.RLock()
  57  	height := s.currentHeight
  58  	s.RUnlock()
  59  	return height
  60  }
  61  
  62  // SetHeight sets the current height associated with the fake chain instance.
  63  func (s *fakeChain) SetHeight(height int32) {
  64  	s.Lock()
  65  	s.currentHeight = height
  66  	s.Unlock()
  67  }
  68  
  69  // MedianTimePast returns the current median time past associated with the fake chain instance.
  70  func (s *fakeChain) MedianTimePast() time.Time {
  71  	s.RLock()
  72  	mtp := s.medianTimePast
  73  	s.RUnlock()
  74  	return mtp
  75  }
  76  
  77  // SetMedianTimePast sets the current median time past associated with the fake chain instance.
  78  func (s *fakeChain) SetMedianTimePast(mtp time.Time) {
  79  	s.Lock()
  80  	s.medianTimePast = mtp
  81  	s.Unlock()
  82  }
  83  
  84  // // CalcSequenceLock returns the current sequence lock for the passed transaction associated with the fake chain
  85  // // instance.
  86  // func (s *fakeChain) CalcSequenceLock(tx *util.Tx,
  87  // 	view *blockchain.UtxoViewpoint) (*blockchain.SequenceLock, error) {
  88  // 	return &blockchain.SequenceLock{
  89  // 		Seconds:     -1,
  90  // 		BlockHeight: -1,
  91  // 	}, nil
  92  // }
  93  
  94  // spendableOutput is a convenience type that houses a particular utxo and the amount associated with it.
  95  type spendableOutput struct {
  96  	outPoint wire.OutPoint
  97  	amount   amt.Amount
  98  }
  99  
 100  // txOutToSpendableOut returns a spendable output given a transaction and index of the output to use. This is useful as
 101  // a convenience when creating test transactions.
 102  func txOutToSpendableOut(tx *util.Tx, outputNum uint32) spendableOutput {
 103  	return spendableOutput{
 104  		outPoint: wire.OutPoint{Hash: *tx.Hash(), Index: outputNum},
 105  		amount:   amt.Amount(tx.MsgTx().TxOut[outputNum].Value),
 106  	}
 107  }
 108  
 109  // poolHarness provides a harness that includes functionality for creating and signing transactions as well as a fake
 110  // chain that provides utxos for use in generating valid transactions.
 111  type poolHarness struct {
 112  	// signKey is the signing key used for creating transactions throughout the tests. payAddr is the p2sh address for
 113  	// the signing key and is used for the payment address throughout the tests.
 114  	signKey     *ecc.PrivateKey
 115  	payAddr     btcaddr.Address
 116  	payScript   []byte
 117  	chainParams *chaincfg.Params
 118  	chain       *fakeChain
 119  	txPool      *TxPool
 120  }
 121  
 122  // CreateCoinbaseTx returns a coinbase transaction with the requested number of outputs paying an appropriate subsidy
 123  // based on the passed block height to the address associated with the harness. It automatically uses a standard
 124  // signature script that starts with the block height that is required by version 2 blocks.
 125  func (p *poolHarness) CreateCoinbaseTx(blockHeight int32, numOutputs uint32, version int32) (*util.Tx, error) {
 126  	// Create standard coinbase script.
 127  	extraNonce := int64(0)
 128  	coinbaseScript, e := txscript.NewScriptBuilder().
 129  		AddInt64(int64(blockHeight)).AddInt64(extraNonce).Script()
 130  	if e != nil {
 131  		return nil, e
 132  	}
 133  	tx := wire.NewMsgTx(wire.TxVersion)
 134  	tx.AddTxIn(
 135  		&wire.TxIn{
 136  			// Coinbase transactions have no inputs, so previous outpoint is zero hash and max index.
 137  			PreviousOutPoint: *wire.NewOutPoint(
 138  				&chainhash.Hash{},
 139  				wire.MaxPrevOutIndex,
 140  			),
 141  			SignatureScript: coinbaseScript,
 142  			Sequence:        wire.MaxTxInSequenceNum,
 143  		},
 144  	)
 145  	totalInput := blockchain.CalcBlockSubsidy(blockHeight, p.chainParams, version)
 146  	amountPerOutput := totalInput / int64(numOutputs)
 147  	remainder := totalInput - amountPerOutput*int64(numOutputs)
 148  	for i := uint32(0); i < numOutputs; i++ {
 149  		// Ensure the final output accounts for any remainder that might be left from splitting the input amount.
 150  		amount := amountPerOutput
 151  		if i == numOutputs-1 {
 152  			amount = amountPerOutput + remainder
 153  		}
 154  		tx.AddTxOut(
 155  			&wire.TxOut{
 156  				PkScript: p.payScript,
 157  				Value:    amount,
 158  			},
 159  		)
 160  	}
 161  	return util.NewTx(tx), nil
 162  }
 163  
 164  // CreateSignedTx creates a new signed transaction that consumes the provided inputs and generates the provided number
 165  // of outputs by evenly splitting the total input amount. All outputs will be to the payment script associated with the
 166  // harness and all inputs are assumed to do the same.
 167  func (p *poolHarness) CreateSignedTx(inputs []spendableOutput, numOutputs uint32) (*util.Tx, error) {
 168  	// Calculate the total input amount and split it amongst the requested number of outputs.
 169  	var totalInput amt.Amount
 170  	for _, input := range inputs {
 171  		totalInput += input.amount
 172  	}
 173  	amountPerOutput := int64(totalInput) / int64(numOutputs)
 174  	remainder := int64(totalInput) - amountPerOutput*int64(numOutputs)
 175  	tx := wire.NewMsgTx(wire.TxVersion)
 176  	for _, input := range inputs {
 177  		tx.AddTxIn(
 178  			&wire.TxIn{
 179  				PreviousOutPoint: input.outPoint,
 180  				SignatureScript:  nil,
 181  				Sequence:         wire.MaxTxInSequenceNum,
 182  			},
 183  		)
 184  	}
 185  	for i := uint32(0); i < numOutputs; i++ {
 186  		// Ensure the final output accounts for any remainder that might be left from splitting the input amount.
 187  		amount := amountPerOutput
 188  		if i == numOutputs-1 {
 189  			amount = amountPerOutput + remainder
 190  		}
 191  		tx.AddTxOut(
 192  			&wire.TxOut{
 193  				PkScript: p.payScript,
 194  				Value:    amount,
 195  			},
 196  		)
 197  	}
 198  	// Sign the new transaction.
 199  	for i := range tx.TxIn {
 200  		sigScript, e := txscript.SignatureScript(
 201  			tx, i, p.payScript,
 202  			txscript.SigHashAll, p.signKey, true,
 203  		)
 204  		if e != nil {
 205  			return nil, e
 206  		}
 207  		tx.TxIn[i].SignatureScript = sigScript
 208  	}
 209  	return util.NewTx(tx), nil
 210  }
 211  
 212  // CreateTxChain creates a chain of zero-fee transactions (each subsequent transaction spends the entire amount from the
 213  // previous one) with the first one spending the provided outpoint. Each transaction spends the entire amount of the
 214  // previous one and as such does not include any fees.
 215  func (p *poolHarness) CreateTxChain(firstOutput spendableOutput, numTxns uint32) ([]*util.Tx, error) {
 216  	txChain := make([]*util.Tx, 0, numTxns)
 217  	prevOutPoint := firstOutput.outPoint
 218  	spendableAmount := firstOutput.amount
 219  	for i := uint32(0); i < numTxns; i++ {
 220  		// Create the transaction using the previous transaction output and paying the full amount to the payment
 221  		// address associated with the harness.
 222  		tx := wire.NewMsgTx(wire.TxVersion)
 223  		tx.AddTxIn(
 224  			&wire.TxIn{
 225  				PreviousOutPoint: prevOutPoint,
 226  				SignatureScript:  nil,
 227  				Sequence:         wire.MaxTxInSequenceNum,
 228  			},
 229  		)
 230  		tx.AddTxOut(
 231  			&wire.TxOut{
 232  				PkScript: p.payScript,
 233  				Value:    int64(spendableAmount),
 234  			},
 235  		)
 236  		// Sign the new transaction.
 237  		sigScript, e := txscript.SignatureScript(
 238  			tx, 0, p.payScript,
 239  			txscript.SigHashAll, p.signKey, true,
 240  		)
 241  		if e != nil {
 242  			return nil, e
 243  		}
 244  		tx.TxIn[0].SignatureScript = sigScript
 245  		txChain = append(txChain, util.NewTx(tx))
 246  		// Next transaction uses outputs from this one.
 247  		prevOutPoint = wire.OutPoint{Hash: tx.TxHash(), Index: 0}
 248  	}
 249  	return txChain, nil
 250  }
 251  
 252  // newPoolHarness returns a new instance of a pool harness initialized with a fake chain and a TxPool bound to it that
 253  // is configured with a policy suitable for testing. Also the fake chain is populated with the returned spendable
 254  // outputs so the caller can easily create new valid transactions which podbuild off of it.
 255  func newPoolHarness(chainParams *chaincfg.Params) (*poolHarness, []spendableOutput, error) {
 256  	// Use a hard coded key pair for deterministic results.
 257  	keyBytes, e := hex.DecodeString(
 258  		"700868df1838811ffbdf918fb482c1f7e" +
 259  			"ad62db4b97bd7012c23e726485e577d",
 260  	)
 261  	if e != nil {
 262  		return nil, nil, e
 263  	}
 264  	signKey, signPub := ecc.PrivKeyFromBytes(ecc.S256(), keyBytes)
 265  	// Generate associated pay-to-script-hash address and resulting payment script.
 266  	pubKeyBytes := signPub.SerializeCompressed()
 267  	payPubKeyAddr, e := btcaddr.NewPubKey(pubKeyBytes, chainParams)
 268  	if e != nil {
 269  		return nil, nil, e
 270  	}
 271  	payAddr := payPubKeyAddr.PubKeyHash()
 272  	pkScript, e := txscript.PayToAddrScript(payAddr)
 273  	if e != nil {
 274  		return nil, nil, e
 275  	}
 276  	// Create a new fake chain and harness bound to it.
 277  	chain := &fakeChain{utxos: blockchain.NewUtxoViewpoint()}
 278  	harness := poolHarness{
 279  		signKey:     signKey,
 280  		payAddr:     payAddr,
 281  		payScript:   pkScript,
 282  		chainParams: chainParams,
 283  		chain:       chain,
 284  		txPool: New(
 285  			&Config{
 286  				Policy: Policy{
 287  					DisableRelayPriority: true,
 288  					FreeTxRelayLimit:     15.0,
 289  					MaxOrphanTxs:         5,
 290  					MaxOrphanTxSize:      1000,
 291  					MaxSigOpCostPerTx:    blockchain.MaxBlockSigOpsCost / 4,
 292  					MinRelayTxFee:        1000, // 1 Satoshi per byte
 293  					MaxTxVersion:         1,
 294  				},
 295  				ChainParams:    chainParams,
 296  				FetchUtxoView:  chain.FetchUtxoView,
 297  				BestHeight:     chain.BestHeight,
 298  				MedianTimePast: chain.MedianTimePast,
 299  				// CalcSequenceLock: chain.CalcSequenceLock,
 300  				SigCache:  nil,
 301  				AddrIndex: nil,
 302  			},
 303  		),
 304  	}
 305  	// Create a single coinbase transaction and add it to the harness chain's utxo set and set the harness chain height
 306  	// such that the coinbase will mature in the next block. This ensures the txpool accepts transactions which spend
 307  	// immature coinbases that will become mature in the next block.
 308  	numOutputs := uint32(1)
 309  	outputs := make([]spendableOutput, 0, numOutputs)
 310  	curHeight := harness.chain.BestHeight()
 311  	coinbase, e := harness.CreateCoinbaseTx(curHeight+1, numOutputs, 0)
 312  	if e != nil {
 313  		return nil, nil, e
 314  	}
 315  	harness.chain.utxos.AddTxOuts(coinbase, curHeight+1)
 316  	for i := uint32(0); i < numOutputs; i++ {
 317  		outputs = append(outputs, txOutToSpendableOut(coinbase, i))
 318  	}
 319  	harness.chain.SetHeight(int32(chainParams.CoinbaseMaturity) + curHeight)
 320  	harness.chain.SetMedianTimePast(time.Now())
 321  	return &harness, outputs, nil
 322  }
 323  
 324  // testContext houses a test-related state that is useful to pass to helper functions as a single argument.
 325  type testContext struct {
 326  	t       *testing.T
 327  	harness *poolHarness
 328  }
 329  
 330  // testPoolMembership tests the transaction pool associated with the provided test context to determine if the passed
 331  // transaction matches the provided orphan pool and transaction pool status. It also further determines if it should be
 332  // reported as available by the HaveTransaction function based upon the two flags and tests that condition as well.
 333  func testPoolMembership(tc *testContext, tx *util.Tx, inOrphanPool, inTxPool bool) {
 334  	txHash := tx.Hash()
 335  	gotOrphanPool := tc.harness.txPool.IsOrphanInPool(txHash)
 336  	if inOrphanPool != gotOrphanPool {
 337  		_, file, line, _ := runtime.Caller(1)
 338  		tc.t.Fatalf(
 339  			"%s:%d -- IsOrphanInPool: want %v, got %v", file,
 340  			line, inOrphanPool, gotOrphanPool,
 341  		)
 342  	}
 343  	gotTxPool := tc.harness.txPool.IsTransactionInPool(txHash)
 344  	if inTxPool != gotTxPool {
 345  		_, file, line, _ := runtime.Caller(1)
 346  		tc.t.Fatalf(
 347  			"%s:%d -- IsTransactionInPool: want %v, got %v",
 348  			file, line, inTxPool, gotTxPool,
 349  		)
 350  	}
 351  	gotHaveTx := tc.harness.txPool.HaveTransaction(txHash)
 352  	wantHaveTx := inOrphanPool || inTxPool
 353  	if wantHaveTx != gotHaveTx {
 354  		_, file, line, _ := runtime.Caller(1)
 355  		tc.t.Fatalf(
 356  			"%s:%d -- HaveTransaction: want %v, got %v", file,
 357  			line, wantHaveTx, gotHaveTx,
 358  		)
 359  	}
 360  }
 361  
 362  // TestSimpleOrphanChain ensures that a simple chain of orphans is handled properly. In particular, it generates a chain
 363  // of single input, single output transactions and inserts them while skipping the first linking transaction so they are
 364  // all orphans. Finally, it adds the linking transaction and ensures the entire orphan chain is moved to the transaction
 365  // pool.
 366  func TestSimpleOrphanChain(t *testing.T) {
 367  	t.Parallel()
 368  	harness, spendableOuts, e := newPoolHarness(&chaincfg.MainNetParams)
 369  	if e != nil {
 370  		t.Fatalf("unable to create test pool: %v", e)
 371  	}
 372  	tc := &testContext{t, harness}
 373  	// Create a chain of transactions rooted with the first spendable output provided by the harness.
 374  	maxOrphans := uint32(harness.txPool.cfg.Policy.MaxOrphanTxs)
 375  	chainedTxns, e := harness.CreateTxChain(spendableOuts[0], maxOrphans+1)
 376  	if e != nil {
 377  		t.Fatalf("unable to create transaction chain: %v", e)
 378  	}
 379  	// Ensure the orphans are accepted (only up to the maximum allowed so none are evicted).
 380  	for _, tx := range chainedTxns[1 : maxOrphans+1] {
 381  		var acceptedTxns []*TxDesc
 382  		acceptedTxns, e = harness.txPool.ProcessTransaction(
 383  			nil, tx, true,
 384  			false, 0,
 385  		)
 386  		if e != nil {
 387  			t.Fatalf(
 388  				"ProcessTransaction: failed to accept valid "+
 389  					"orphan %v", e,
 390  			)
 391  		}
 392  		// Ensure no transactions were reported as accepted.
 393  		if len(acceptedTxns) != 0 {
 394  			t.Fatalf(
 395  				"ProcessTransaction: reported %d accepted "+
 396  					"transactions from what should be an orphan",
 397  				len(acceptedTxns),
 398  			)
 399  		}
 400  		// Ensure the transaction is in the orphan pool, is not in the transaction pool, and is reported as available.
 401  		testPoolMembership(tc, tx, true, false)
 402  	}
 403  	// Add the transaction which completes the orphan chain and ensure they all get accepted. Notice the accept orphans
 404  	// flag is also false here to ensure it has no bearing on whether or not already existing orphans in the pool are
 405  	// linked.
 406  	acceptedTxns, e := harness.txPool.ProcessTransaction(
 407  		nil, chainedTxns[0],
 408  		false, false, 0,
 409  	)
 410  	if e != nil {
 411  		t.Fatalf(
 412  			"ProcessTransaction: failed to accept valid "+
 413  				"orphan %v", e,
 414  		)
 415  	}
 416  	if len(acceptedTxns) != len(chainedTxns) {
 417  		t.Fatalf(
 418  			"ProcessTransaction: reported accepted transactions "+
 419  				"length does not match expected -- got %d, want %d",
 420  			len(acceptedTxns), len(chainedTxns),
 421  		)
 422  	}
 423  	for _, txD := range acceptedTxns {
 424  		// Ensure the transaction is no longer in the orphan pool, is now in the transaction pool, and is reported as
 425  		// available.
 426  		testPoolMembership(tc, txD.Tx, false, true)
 427  	}
 428  }
 429  
 430  // TestOrphanReject ensures that orphans are properly rejected when the allow orphans flag is not set on
 431  // ProcessTransaction.
 432  func TestOrphanReject(t *testing.T) {
 433  	t.Parallel()
 434  	harness, outputs, e := newPoolHarness(&chaincfg.MainNetParams)
 435  	if e != nil {
 436  		t.Fatalf("unable to create test pool: %v", e)
 437  	}
 438  	tc := &testContext{t, harness}
 439  	// Create a chain of transactions rooted with the first spendable output provided by the harness.
 440  	maxOrphans := uint32(harness.txPool.cfg.Policy.MaxOrphanTxs)
 441  	chainedTxns, e := harness.CreateTxChain(outputs[0], maxOrphans+1)
 442  	if e != nil {
 443  		t.Fatalf("unable to create transaction chain: %v", e)
 444  	}
 445  	// Ensure orphans are rejected when the allow orphans flag is not set.
 446  	for _, tx := range chainedTxns[1:] {
 447  		acceptedTxns, e := harness.txPool.ProcessTransaction(
 448  			nil, tx, false,
 449  			false, 0,
 450  		)
 451  		if e == nil {
 452  			t.Fatalf(
 453  				"ProcessTransaction: did not fail on orphan "+
 454  					"%v when allow orphans flag is false", tx.Hash(),
 455  			)
 456  		}
 457  		expectedErr := RuleError{}
 458  		if reflect.TypeOf(e) != reflect.TypeOf(expectedErr) {
 459  			t.Fatalf(
 460  				"ProcessTransaction: wrong error got: <%T> %v, "+
 461  					"want: <%T>", e, e, expectedErr,
 462  			)
 463  		}
 464  		code, extracted := extractRejectCode(e)
 465  		if !extracted {
 466  			t.Fatalf(
 467  				"ProcessTransaction: failed to extract reject "+
 468  					"code from error %q", e,
 469  			)
 470  		}
 471  		if code != wire.RejectDuplicate {
 472  			t.Fatalf(
 473  				"ProcessTransaction: unexpected reject code "+
 474  					"-- got %v, want %v", code, wire.RejectDuplicate,
 475  			)
 476  		}
 477  		// Ensure no transactions were reported as accepted.
 478  		if len(acceptedTxns) != 0 {
 479  			t.Fatalf(
 480  				"ProcessTransaction: reported %d accepted "+
 481  					"transactions from failed orphan attempt",
 482  				len(acceptedTxns),
 483  			)
 484  		}
 485  		// Ensure the transaction is not in the orphan pool, not in the transaction pool, and not reported as available
 486  		testPoolMembership(tc, tx, false, false)
 487  	}
 488  }
 489  
 490  // TestOrphanEviction ensures that exceeding the maximum number of orphans evicts entries to make room for the new ones.
 491  func TestOrphanEviction(t *testing.T) {
 492  	t.Parallel()
 493  	harness, outputs, e := newPoolHarness(&chaincfg.MainNetParams)
 494  	if e != nil {
 495  		t.Fatalf("unable to create test pool: %v", e)
 496  	}
 497  	tc := &testContext{t, harness}
 498  	// Create a chain of transactions rooted with the first spendable output provided by the harness that is long enough
 499  	// to be able to force several orphan evictions.
 500  	maxOrphans := uint32(harness.txPool.cfg.Policy.MaxOrphanTxs)
 501  	chainedTxns, e := harness.CreateTxChain(outputs[0], maxOrphans+5)
 502  	if e != nil {
 503  		t.Fatalf("unable to create transaction chain: %v", e)
 504  	}
 505  	// Add enough orphans to exceed the max allowed while ensuring they are all accepted.  This will cause an eviction.
 506  	for _, tx := range chainedTxns[1:] {
 507  		acceptedTxns, e := harness.txPool.ProcessTransaction(
 508  			nil, tx, true,
 509  			false, 0,
 510  		)
 511  		if e != nil {
 512  			t.Fatalf(
 513  				"ProcessTransaction: failed to accept valid "+
 514  					"orphan %v", e,
 515  			)
 516  		}
 517  		// Ensure no transactions were reported as accepted.
 518  		if len(acceptedTxns) != 0 {
 519  			t.Fatalf(
 520  				"ProcessTransaction: reported %d accepted "+
 521  					"transactions from what should be an orphan",
 522  				len(acceptedTxns),
 523  			)
 524  		}
 525  		// Ensure the transaction is in the orphan pool, is not in the transaction pool, and is reported as available.
 526  		testPoolMembership(tc, tx, true, false)
 527  	}
 528  	// Figure out which transactions were evicted and make sure the number evicted matches the expected number.
 529  	var evictedTxns []*util.Tx
 530  	for _, tx := range chainedTxns[1:] {
 531  		if !harness.txPool.IsOrphanInPool(tx.Hash()) {
 532  			evictedTxns = append(evictedTxns, tx)
 533  		}
 534  	}
 535  	expectedEvictions := len(chainedTxns) - 1 - int(maxOrphans)
 536  	if len(evictedTxns) != expectedEvictions {
 537  		t.Fatalf(
 538  			"unexpected number of evictions -- got %d, want %d",
 539  			len(evictedTxns), expectedEvictions,
 540  		)
 541  	}
 542  	// Ensure none of the evicted transactions ended up in the transaction pool.
 543  	for _, tx := range evictedTxns {
 544  		testPoolMembership(tc, tx, false, false)
 545  	}
 546  }
 547  
 548  // TestBasicOrphanRemoval ensure that orphan removal works as expected when an orphan that doesn't exist is removed both
 549  // when there is another orphan that redeems it and when there is not.
 550  func TestBasicOrphanRemoval(t *testing.T) {
 551  	t.Parallel()
 552  	const maxOrphans = 4
 553  	harness, spendableOuts, e := newPoolHarness(&chaincfg.MainNetParams)
 554  	if e != nil {
 555  		t.Fatalf("unable to create test pool: %v", e)
 556  	}
 557  	harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
 558  	tc := &testContext{t, harness}
 559  	// Create a chain of transactions rooted with the first spendable output provided by the harness.
 560  	chainedTxns, e := harness.CreateTxChain(spendableOuts[0], maxOrphans+1)
 561  	if e != nil {
 562  		t.Fatalf("unable to create transaction chain: %v", e)
 563  	}
 564  	// Ensure the orphans are accepted (only up to the maximum allowed so none are evicted).
 565  	for _, tx := range chainedTxns[1 : maxOrphans+1] {
 566  		var acceptedTxns []*TxDesc
 567  		acceptedTxns, e = harness.txPool.ProcessTransaction(
 568  			nil, tx, true,
 569  			false, 0,
 570  		)
 571  		if e != nil {
 572  			t.Fatalf(
 573  				"ProcessTransaction: failed to accept valid "+
 574  					"orphan %v", e,
 575  			)
 576  		}
 577  		// Ensure no transactions were reported as accepted.
 578  		if len(acceptedTxns) != 0 {
 579  			t.Fatalf(
 580  				"ProcessTransaction: reported %d accepted "+
 581  					"transactions from what should be an orphan",
 582  				len(acceptedTxns),
 583  			)
 584  		}
 585  		// Ensure the transaction is in the orphan pool, not in the transaction pool, and reported as available.
 586  		testPoolMembership(tc, tx, true, false)
 587  	}
 588  	// Attempt to remove an orphan that has no redeemers and is not present, and ensure the state of all other orphans
 589  	// are unaffected.
 590  	nonChainedOrphanTx, e := harness.CreateSignedTx(
 591  		[]spendableOutput{
 592  			{
 593  				amount:   amt.Amount(5000000000),
 594  				outPoint: wire.OutPoint{Hash: chainhash.Hash{}, Index: 0},
 595  			},
 596  		}, 1,
 597  	)
 598  	if e != nil {
 599  		t.Fatalf("unable to create signed tx: %v", e)
 600  	}
 601  	harness.txPool.RemoveOrphan(nonChainedOrphanTx)
 602  	testPoolMembership(tc, nonChainedOrphanTx, false, false)
 603  	for _, tx := range chainedTxns[1 : maxOrphans+1] {
 604  		testPoolMembership(tc, tx, true, false)
 605  	}
 606  	// Attempt to remove an orphan that has a existing redeemer but itself is not present and ensure the state of all
 607  	// other orphans (including the one that redeems it) are unaffected.
 608  	harness.txPool.RemoveOrphan(chainedTxns[0])
 609  	testPoolMembership(tc, chainedTxns[0], false, false)
 610  	for _, tx := range chainedTxns[1 : maxOrphans+1] {
 611  		testPoolMembership(tc, tx, true, false)
 612  	}
 613  	// Remove each orphan one-by-one and ensure they are removed as expected.
 614  	for _, tx := range chainedTxns[1 : maxOrphans+1] {
 615  		harness.txPool.RemoveOrphan(tx)
 616  		testPoolMembership(tc, tx, false, false)
 617  	}
 618  }
 619  
 620  // TestOrphanChainRemoval ensure that orphan chains (orphans that spend outputs from other orphans) are removed as
 621  // expected.
 622  func TestOrphanChainRemoval(t *testing.T) {
 623  	t.Parallel()
 624  	const maxOrphans = 10
 625  	harness, spendableOuts, e := newPoolHarness(&chaincfg.MainNetParams)
 626  	if e != nil {
 627  		t.Fatalf("unable to create test pool: %v", e)
 628  	}
 629  	harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
 630  	tc := &testContext{t, harness}
 631  	// Create a chain of transactions rooted with the first spendable output provided by the harness.
 632  	chainedTxns, e := harness.CreateTxChain(spendableOuts[0], maxOrphans+1)
 633  	if e != nil {
 634  		t.Fatalf("unable to create transaction chain: %v", e)
 635  	}
 636  	// Ensure the orphans are accepted (only up to the maximum allowed so none are evicted).
 637  	for _, tx := range chainedTxns[1 : maxOrphans+1] {
 638  		acceptedTxns, e := harness.txPool.ProcessTransaction(
 639  			nil, tx, true,
 640  			false, 0,
 641  		)
 642  		if e != nil {
 643  			t.Fatalf(
 644  				"ProcessTransaction: failed to accept valid "+
 645  					"orphan %v", e,
 646  			)
 647  		}
 648  		// Ensure no transactions were reported as accepted.
 649  		if len(acceptedTxns) != 0 {
 650  			t.Fatalf(
 651  				"ProcessTransaction: reported %d accepted "+
 652  					"transactions from what should be an orphan",
 653  				len(acceptedTxns),
 654  			)
 655  		}
 656  		// Ensure the transaction is in the orphan pool, not in the transaction pool, and reported as available.
 657  		testPoolMembership(tc, tx, true, false)
 658  	}
 659  	// Remove the first orphan that starts the orphan chain without the remove redeemer flag set and ensure that only
 660  	// the first orphan was removed.
 661  	harness.txPool.mtx.Lock()
 662  	harness.txPool.removeOrphan(chainedTxns[1], false)
 663  	harness.txPool.mtx.Unlock()
 664  	testPoolMembership(tc, chainedTxns[1], false, false)
 665  	for _, tx := range chainedTxns[2 : maxOrphans+1] {
 666  		testPoolMembership(tc, tx, true, false)
 667  	}
 668  	// Remove the first remaining orphan that starts the orphan chain with the remove redeemer flag set and ensure they
 669  	// are all removed.
 670  	harness.txPool.mtx.Lock()
 671  	harness.txPool.removeOrphan(chainedTxns[2], true)
 672  	harness.txPool.mtx.Unlock()
 673  	for _, tx := range chainedTxns[2 : maxOrphans+1] {
 674  		testPoolMembership(tc, tx, false, false)
 675  	}
 676  }
 677  
 678  // TestMultiInputOrphanDoubleSpend ensures that orphans that spend from an output that is spend by another transaction
 679  // entering the pool are removed.
 680  func TestMultiInputOrphanDoubleSpend(t *testing.T) {
 681  	t.Parallel()
 682  	const maxOrphans = 4
 683  	harness, outputs, e := newPoolHarness(&chaincfg.MainNetParams)
 684  	if e != nil {
 685  		t.Fatalf("unable to create test pool: %v", e)
 686  	}
 687  	harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
 688  	tc := &testContext{t, harness}
 689  	// Create a chain of transactions rooted with the first spendable output provided by the harness.
 690  	chainedTxns, e := harness.CreateTxChain(outputs[0], maxOrphans+1)
 691  	if e != nil {
 692  		t.Fatalf("unable to create transaction chain: %v", e)
 693  	}
 694  	// Start by adding the orphan transactions from the generated chain except the final one.
 695  	for _, tx := range chainedTxns[1:maxOrphans] {
 696  		var acceptedTxns []*TxDesc
 697  		acceptedTxns, e = harness.txPool.ProcessTransaction(
 698  			nil, tx, true,
 699  			false, 0,
 700  		)
 701  		if e != nil {
 702  			t.Fatalf(
 703  				"ProcessTransaction: failed to accept valid "+
 704  					"orphan %v", e,
 705  			)
 706  		}
 707  		if len(acceptedTxns) != 0 {
 708  			t.Fatalf(
 709  				"ProcessTransaction: reported %d accepted transactions "+
 710  					"from what should be an orphan", len(acceptedTxns),
 711  			)
 712  		}
 713  		testPoolMembership(tc, tx, true, false)
 714  	}
 715  	// Ensure a transaction that contains a double spend of the same output as the second orphan that was just added as
 716  	// well as a valid spend from that last orphan in the chain generated above (and is not in the orphan pool) is
 717  	// accepted to the orphan pool. This must be allowed since it would otherwise be possible for a malicious actor to
 718  	// disrupt tx chains.
 719  	doubleSpendTx, e := harness.CreateSignedTx(
 720  		[]spendableOutput{
 721  			txOutToSpendableOut(chainedTxns[1], 0),
 722  			txOutToSpendableOut(chainedTxns[maxOrphans], 0),
 723  		}, 1,
 724  	)
 725  	if e != nil {
 726  		t.Fatalf("unable to create signed tx: %v", e)
 727  	}
 728  	acceptedTxns, e := harness.txPool.ProcessTransaction(
 729  		nil, doubleSpendTx,
 730  		true, false, 0,
 731  	)
 732  	if e != nil {
 733  		t.Fatalf(
 734  			"ProcessTransaction: failed to accept valid orphan %v",
 735  			e,
 736  		)
 737  	}
 738  	if len(acceptedTxns) != 0 {
 739  		t.Fatalf(
 740  			"ProcessTransaction: reported %d accepted transactions "+
 741  				"from what should be an orphan", len(acceptedTxns),
 742  		)
 743  	}
 744  	testPoolMembership(tc, doubleSpendTx, true, false)
 745  	// Add the transaction which completes the orphan chain and ensure the chain gets accepted. Notice the accept
 746  	// orphans flag is also false here to ensure it has no bearing on whether or not already existing orphans in the
 747  	// pool are linked. This will cause the shared output to become a concrete spend which will in turn must cause the
 748  	// double spending orphan to be removed.
 749  	acceptedTxns, e = harness.txPool.ProcessTransaction(
 750  		nil, chainedTxns[0],
 751  		false, false, 0,
 752  	)
 753  	if e != nil {
 754  		t.Fatalf("ProcessTransaction: failed to accept valid tx %v", e)
 755  	}
 756  	if len(acceptedTxns) != maxOrphans {
 757  		t.Fatalf(
 758  			"ProcessTransaction: reported accepted transactions "+
 759  				"length does not match expected -- got %d, want %d",
 760  			len(acceptedTxns), maxOrphans,
 761  		)
 762  	}
 763  	for _, txD := range acceptedTxns {
 764  		// Ensure the transaction is no longer in the orphan pool, is in the transaction pool, and is reported as
 765  		// available.
 766  		testPoolMembership(tc, txD.Tx, false, true)
 767  	}
 768  	// Ensure the double spending orphan is no longer in the orphan pool and was not moved to the transaction pool.
 769  	testPoolMembership(tc, doubleSpendTx, false, false)
 770  }
 771  
 772  // TestCheckSpend tests that CheckSpend returns the expected spends found in the mempool.
 773  func TestCheckSpend(t *testing.T) {
 774  	t.Parallel()
 775  	harness, outputs, e := newPoolHarness(&chaincfg.MainNetParams)
 776  	if e != nil {
 777  		t.Fatalf("unable to create test pool: %v", e)
 778  	}
 779  	// The mempool is empty, so none of the spendable outputs should have a spend there.
 780  	for _, op := range outputs {
 781  		spend := harness.txPool.CheckSpend(op.outPoint)
 782  		if spend != nil {
 783  			t.Fatalf("Unexpeced spend found in pool: %v", spend)
 784  		}
 785  	}
 786  	// Create a chain of transactions rooted with the first spendable output provided by the harness.
 787  	const txChainLength = 5
 788  	chainedTxns, e := harness.CreateTxChain(outputs[0], txChainLength)
 789  	if e != nil {
 790  		t.Fatalf("unable to create transaction chain: %v", e)
 791  	}
 792  	for _, tx := range chainedTxns {
 793  		_, e := harness.txPool.ProcessTransaction(
 794  			nil, tx, true,
 795  			false, 0,
 796  		)
 797  		if e != nil {
 798  			t.Fatalf(
 799  				"ProcessTransaction: failed to accept "+
 800  					"tx: %v", e,
 801  			)
 802  		}
 803  	}
 804  	// The first tx in the chain should be the spend of the spendable output.
 805  	op := outputs[0].outPoint
 806  	spend := harness.txPool.CheckSpend(op)
 807  	if spend != chainedTxns[0] {
 808  		t.Fatalf(
 809  			"expected %v to be spent by %v, instead "+
 810  				"got %v", op, chainedTxns[0], spend,
 811  		)
 812  	}
 813  	// Now all but the last tx should be spent by the next.
 814  	for i := 0; i < len(chainedTxns)-1; i++ {
 815  		op = wire.OutPoint{
 816  			Hash:  *chainedTxns[i].Hash(),
 817  			Index: 0,
 818  		}
 819  		expSpend := chainedTxns[i+1]
 820  		spend = harness.txPool.CheckSpend(op)
 821  		if spend != expSpend {
 822  			t.Fatalf(
 823  				"expected %v to be spent by %v, instead "+
 824  					"got %v", op, expSpend, spend,
 825  			)
 826  		}
 827  	}
 828  	// The last tx should have no spend.
 829  	op = wire.OutPoint{
 830  		Hash:  *chainedTxns[txChainLength-1].Hash(),
 831  		Index: 0,
 832  	}
 833  	spend = harness.txPool.CheckSpend(op)
 834  	if spend != nil {
 835  		t.Fatalf("Unexpeced spend found in pool: %v", spend)
 836  	}
 837  }
 838