github.com/btcsuite/btcd@v0.24.0/mempool/mempool_test.go (about) 1 // Copyright (c) 2016 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package mempool 6 7 import ( 8 "encoding/hex" 9 "reflect" 10 "strings" 11 "sync" 12 "testing" 13 "time" 14 15 "github.com/btcsuite/btcd/blockchain" 16 "github.com/btcsuite/btcd/btcec/v2" 17 "github.com/btcsuite/btcd/btcutil" 18 "github.com/btcsuite/btcd/chaincfg" 19 "github.com/btcsuite/btcd/chaincfg/chainhash" 20 "github.com/btcsuite/btcd/txscript" 21 "github.com/btcsuite/btcd/wire" 22 ) 23 24 // fakeChain is used by the pool harness to provide generated test utxos and 25 // a current faked chain height to the pool callbacks. This, in turn, allows 26 // transactions to appear as though they are spending completely valid utxos. 27 type fakeChain struct { 28 sync.RWMutex 29 utxos *blockchain.UtxoViewpoint 30 currentHeight int32 31 medianTimePast time.Time 32 } 33 34 // FetchUtxoView loads utxo details about the inputs referenced by the passed 35 // transaction from the point of view of the fake chain. It also attempts to 36 // fetch the utxos for the outputs of the transaction itself so the returned 37 // view can be examined for duplicate transactions. 38 // 39 // This function is safe for concurrent access however the returned view is NOT. 40 func (s *fakeChain) FetchUtxoView(tx *btcutil.Tx) (*blockchain.UtxoViewpoint, error) { 41 s.RLock() 42 defer s.RUnlock() 43 44 // All entries are cloned to ensure modifications to the returned view 45 // do not affect the fake chain's view. 46 47 // Add an entry for the tx itself to the new view. 48 viewpoint := blockchain.NewUtxoViewpoint() 49 prevOut := wire.OutPoint{Hash: *tx.Hash()} 50 for txOutIdx := range tx.MsgTx().TxOut { 51 prevOut.Index = uint32(txOutIdx) 52 entry := s.utxos.LookupEntry(prevOut) 53 viewpoint.Entries()[prevOut] = entry.Clone() 54 } 55 56 // Add entries for all of the inputs to the tx to the new view. 57 for _, txIn := range tx.MsgTx().TxIn { 58 entry := s.utxos.LookupEntry(txIn.PreviousOutPoint) 59 viewpoint.Entries()[txIn.PreviousOutPoint] = entry.Clone() 60 } 61 62 return viewpoint, nil 63 } 64 65 // BestHeight returns the current height associated with the fake chain 66 // instance. 67 func (s *fakeChain) BestHeight() int32 { 68 s.RLock() 69 height := s.currentHeight 70 s.RUnlock() 71 return height 72 } 73 74 // SetHeight sets the current height associated with the fake chain instance. 75 func (s *fakeChain) SetHeight(height int32) { 76 s.Lock() 77 s.currentHeight = height 78 s.Unlock() 79 } 80 81 // MedianTimePast returns the current median time past associated with the fake 82 // chain instance. 83 func (s *fakeChain) MedianTimePast() time.Time { 84 s.RLock() 85 mtp := s.medianTimePast 86 s.RUnlock() 87 return mtp 88 } 89 90 // SetMedianTimePast sets the current median time past associated with the fake 91 // chain instance. 92 func (s *fakeChain) SetMedianTimePast(mtp time.Time) { 93 s.Lock() 94 s.medianTimePast = mtp 95 s.Unlock() 96 } 97 98 // CalcSequenceLock returns the current sequence lock for the passed 99 // transaction associated with the fake chain instance. 100 func (s *fakeChain) CalcSequenceLock(tx *btcutil.Tx, 101 view *blockchain.UtxoViewpoint) (*blockchain.SequenceLock, error) { 102 103 return &blockchain.SequenceLock{ 104 Seconds: -1, 105 BlockHeight: -1, 106 }, nil 107 } 108 109 // spendableOutput is a convenience type that houses a particular utxo and the 110 // amount associated with it. 111 type spendableOutput struct { 112 outPoint wire.OutPoint 113 amount btcutil.Amount 114 } 115 116 // txOutToSpendableOut returns a spendable output given a transaction and index 117 // of the output to use. This is useful as a convenience when creating test 118 // transactions. 119 func txOutToSpendableOut(tx *btcutil.Tx, outputNum uint32) spendableOutput { 120 return spendableOutput{ 121 outPoint: wire.OutPoint{Hash: *tx.Hash(), Index: outputNum}, 122 amount: btcutil.Amount(tx.MsgTx().TxOut[outputNum].Value), 123 } 124 } 125 126 // poolHarness provides a harness that includes functionality for creating and 127 // signing transactions as well as a fake chain that provides utxos for use in 128 // generating valid transactions. 129 type poolHarness struct { 130 // signKey is the signing key used for creating transactions throughout 131 // the tests. 132 // 133 // payAddr is the p2sh address for the signing key and is used for the 134 // payment address throughout the tests. 135 signKey *btcec.PrivateKey 136 payAddr btcutil.Address 137 payScript []byte 138 chainParams *chaincfg.Params 139 140 chain *fakeChain 141 txPool *TxPool 142 } 143 144 // CreateCoinbaseTx returns a coinbase transaction with the requested number of 145 // outputs paying an appropriate subsidy based on the passed block height to the 146 // address associated with the harness. It automatically uses a standard 147 // signature script that starts with the block height that is required by 148 // version 2 blocks. 149 func (p *poolHarness) CreateCoinbaseTx(blockHeight int32, numOutputs uint32) (*btcutil.Tx, error) { 150 // Create standard coinbase script. 151 extraNonce := int64(0) 152 coinbaseScript, err := txscript.NewScriptBuilder(). 153 AddInt64(int64(blockHeight)).AddInt64(extraNonce).Script() 154 if err != nil { 155 return nil, err 156 } 157 158 tx := wire.NewMsgTx(wire.TxVersion) 159 tx.AddTxIn(&wire.TxIn{ 160 // Coinbase transactions have no inputs, so previous outpoint is 161 // zero hash and max index. 162 PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{}, 163 wire.MaxPrevOutIndex), 164 SignatureScript: coinbaseScript, 165 Sequence: wire.MaxTxInSequenceNum, 166 }) 167 totalInput := blockchain.CalcBlockSubsidy(blockHeight, p.chainParams) 168 amountPerOutput := totalInput / int64(numOutputs) 169 remainder := totalInput - amountPerOutput*int64(numOutputs) 170 for i := uint32(0); i < numOutputs; i++ { 171 // Ensure the final output accounts for any remainder that might 172 // be left from splitting the input amount. 173 amount := amountPerOutput 174 if i == numOutputs-1 { 175 amount = amountPerOutput + remainder 176 } 177 tx.AddTxOut(&wire.TxOut{ 178 PkScript: p.payScript, 179 Value: amount, 180 }) 181 } 182 183 return btcutil.NewTx(tx), nil 184 } 185 186 // CreateSignedTx creates a new signed transaction that consumes the provided 187 // inputs and generates the provided number of outputs by evenly splitting the 188 // total input amount. All outputs will be to the payment script associated 189 // with the harness and all inputs are assumed to do the same. 190 func (p *poolHarness) CreateSignedTx(inputs []spendableOutput, 191 numOutputs uint32, fee btcutil.Amount, 192 signalsReplacement bool) (*btcutil.Tx, error) { 193 194 // Calculate the total input amount and split it amongst the requested 195 // number of outputs. 196 var totalInput btcutil.Amount 197 for _, input := range inputs { 198 totalInput += input.amount 199 } 200 totalInput -= fee 201 amountPerOutput := int64(totalInput) / int64(numOutputs) 202 remainder := int64(totalInput) - amountPerOutput*int64(numOutputs) 203 204 tx := wire.NewMsgTx(wire.TxVersion) 205 sequence := wire.MaxTxInSequenceNum 206 if signalsReplacement { 207 sequence = MaxRBFSequence 208 } 209 for _, input := range inputs { 210 tx.AddTxIn(&wire.TxIn{ 211 PreviousOutPoint: input.outPoint, 212 SignatureScript: nil, 213 Sequence: sequence, 214 }) 215 } 216 for i := uint32(0); i < numOutputs; i++ { 217 // Ensure the final output accounts for any remainder that might 218 // be left from splitting the input amount. 219 amount := amountPerOutput 220 if i == numOutputs-1 { 221 amount = amountPerOutput + remainder 222 } 223 tx.AddTxOut(&wire.TxOut{ 224 PkScript: p.payScript, 225 Value: amount, 226 }) 227 } 228 229 // Sign the new transaction. 230 for i := range tx.TxIn { 231 sigScript, err := txscript.SignatureScript(tx, i, p.payScript, 232 txscript.SigHashAll, p.signKey, true) 233 if err != nil { 234 return nil, err 235 } 236 tx.TxIn[i].SignatureScript = sigScript 237 } 238 239 return btcutil.NewTx(tx), nil 240 } 241 242 // CreateTxChain creates a chain of zero-fee transactions (each subsequent 243 // transaction spends the entire amount from the previous one) with the first 244 // one spending the provided outpoint. Each transaction spends the entire 245 // amount of the previous one and as such does not include any fees. 246 func (p *poolHarness) CreateTxChain(firstOutput spendableOutput, numTxns uint32) ([]*btcutil.Tx, error) { 247 txChain := make([]*btcutil.Tx, 0, numTxns) 248 prevOutPoint := firstOutput.outPoint 249 spendableAmount := firstOutput.amount 250 for i := uint32(0); i < numTxns; i++ { 251 // Create the transaction using the previous transaction output 252 // and paying the full amount to the payment address associated 253 // with the harness. 254 tx := wire.NewMsgTx(wire.TxVersion) 255 tx.AddTxIn(&wire.TxIn{ 256 PreviousOutPoint: prevOutPoint, 257 SignatureScript: nil, 258 Sequence: wire.MaxTxInSequenceNum, 259 }) 260 tx.AddTxOut(&wire.TxOut{ 261 PkScript: p.payScript, 262 Value: int64(spendableAmount), 263 }) 264 265 // Sign the new transaction. 266 sigScript, err := txscript.SignatureScript(tx, 0, p.payScript, 267 txscript.SigHashAll, p.signKey, true) 268 if err != nil { 269 return nil, err 270 } 271 tx.TxIn[0].SignatureScript = sigScript 272 273 txChain = append(txChain, btcutil.NewTx(tx)) 274 275 // Next transaction uses outputs from this one. 276 prevOutPoint = wire.OutPoint{Hash: tx.TxHash(), Index: 0} 277 } 278 279 return txChain, nil 280 } 281 282 // newPoolHarness returns a new instance of a pool harness initialized with a 283 // fake chain and a TxPool bound to it that is configured with a policy suitable 284 // for testing. Also, the fake chain is populated with the returned spendable 285 // outputs so the caller can easily create new valid transactions which build 286 // off of it. 287 func newPoolHarness(chainParams *chaincfg.Params) (*poolHarness, []spendableOutput, error) { 288 // Use a hard coded key pair for deterministic results. 289 keyBytes, err := hex.DecodeString("700868df1838811ffbdf918fb482c1f7e" + 290 "ad62db4b97bd7012c23e726485e577d") 291 if err != nil { 292 return nil, nil, err 293 } 294 signKey, signPub := btcec.PrivKeyFromBytes(keyBytes) 295 296 // Generate associated pay-to-script-hash address and resulting payment 297 // script. 298 pubKeyBytes := signPub.SerializeCompressed() 299 payPubKeyAddr, err := btcutil.NewAddressPubKey(pubKeyBytes, chainParams) 300 if err != nil { 301 return nil, nil, err 302 } 303 payAddr := payPubKeyAddr.AddressPubKeyHash() 304 pkScript, err := txscript.PayToAddrScript(payAddr) 305 if err != nil { 306 return nil, nil, err 307 } 308 309 // Create a new fake chain and harness bound to it. 310 chain := &fakeChain{utxos: blockchain.NewUtxoViewpoint()} 311 harness := poolHarness{ 312 signKey: signKey, 313 payAddr: payAddr, 314 payScript: pkScript, 315 chainParams: chainParams, 316 317 chain: chain, 318 txPool: New(&Config{ 319 Policy: Policy{ 320 DisableRelayPriority: true, 321 FreeTxRelayLimit: 15.0, 322 MaxOrphanTxs: 5, 323 MaxOrphanTxSize: 1000, 324 MaxSigOpCostPerTx: blockchain.MaxBlockSigOpsCost / 4, 325 MinRelayTxFee: 1000, // 1 Satoshi per byte 326 MaxTxVersion: 1, 327 }, 328 ChainParams: chainParams, 329 FetchUtxoView: chain.FetchUtxoView, 330 BestHeight: chain.BestHeight, 331 MedianTimePast: chain.MedianTimePast, 332 CalcSequenceLock: chain.CalcSequenceLock, 333 SigCache: nil, 334 AddrIndex: nil, 335 }), 336 } 337 338 // Create a single coinbase transaction and add it to the harness 339 // chain's utxo set and set the harness chain height such that the 340 // coinbase will mature in the next block. This ensures the txpool 341 // accepts transactions which spend immature coinbases that will become 342 // mature in the next block. 343 numOutputs := uint32(1) 344 outputs := make([]spendableOutput, 0, numOutputs) 345 curHeight := harness.chain.BestHeight() 346 coinbase, err := harness.CreateCoinbaseTx(curHeight+1, numOutputs) 347 if err != nil { 348 return nil, nil, err 349 } 350 harness.chain.utxos.AddTxOuts(coinbase, curHeight+1) 351 for i := uint32(0); i < numOutputs; i++ { 352 outputs = append(outputs, txOutToSpendableOut(coinbase, i)) 353 } 354 harness.chain.SetHeight(int32(chainParams.CoinbaseMaturity) + curHeight) 355 harness.chain.SetMedianTimePast(time.Now()) 356 357 return &harness, outputs, nil 358 } 359 360 // testContext houses a test-related state that is useful to pass to helper 361 // functions as a single argument. 362 type testContext struct { 363 t *testing.T 364 harness *poolHarness 365 } 366 367 // addCoinbaseTx adds a spendable coinbase transaction to the test context's 368 // mock chain. 369 func (ctx *testContext) addCoinbaseTx(numOutputs uint32) *btcutil.Tx { 370 ctx.t.Helper() 371 372 coinbaseHeight := ctx.harness.chain.BestHeight() + 1 373 coinbase, err := ctx.harness.CreateCoinbaseTx(coinbaseHeight, numOutputs) 374 if err != nil { 375 ctx.t.Fatalf("unable to create coinbase: %v", err) 376 } 377 378 ctx.harness.chain.utxos.AddTxOuts(coinbase, coinbaseHeight) 379 maturity := int32(ctx.harness.chainParams.CoinbaseMaturity) 380 ctx.harness.chain.SetHeight(coinbaseHeight + maturity) 381 ctx.harness.chain.SetMedianTimePast(time.Now()) 382 383 return coinbase 384 } 385 386 // addSignedTx creates a transaction that spends the inputs with the given fee. 387 // It can be added to the test context's mempool or mock chain based on the 388 // confirmed boolean. 389 func (ctx *testContext) addSignedTx(inputs []spendableOutput, 390 numOutputs uint32, fee btcutil.Amount, 391 signalsReplacement, confirmed bool) *btcutil.Tx { 392 393 ctx.t.Helper() 394 395 tx, err := ctx.harness.CreateSignedTx( 396 inputs, numOutputs, fee, signalsReplacement, 397 ) 398 if err != nil { 399 ctx.t.Fatalf("unable to create transaction: %v", err) 400 } 401 402 if confirmed { 403 newHeight := ctx.harness.chain.BestHeight() + 1 404 ctx.harness.chain.utxos.AddTxOuts(tx, newHeight) 405 ctx.harness.chain.SetHeight(newHeight) 406 ctx.harness.chain.SetMedianTimePast(time.Now()) 407 } else { 408 acceptedTxns, err := ctx.harness.txPool.ProcessTransaction( 409 tx, true, false, 0, 410 ) 411 if err != nil { 412 ctx.t.Fatalf("unable to process transaction: %v", err) 413 } 414 if len(acceptedTxns) != 1 { 415 ctx.t.Fatalf("expected one accepted transaction, got %d", 416 len(acceptedTxns)) 417 } 418 testPoolMembership(ctx, tx, false, true) 419 } 420 421 return tx 422 } 423 424 // testPoolMembership tests the transaction pool associated with the provided 425 // test context to determine if the passed transaction matches the provided 426 // orphan pool and transaction pool status. It also further determines if it 427 // should be reported as available by the HaveTransaction function based upon 428 // the two flags and tests that condition as well. 429 func testPoolMembership(tc *testContext, tx *btcutil.Tx, inOrphanPool, inTxPool bool) { 430 tc.t.Helper() 431 432 txHash := tx.Hash() 433 gotOrphanPool := tc.harness.txPool.IsOrphanInPool(txHash) 434 if inOrphanPool != gotOrphanPool { 435 tc.t.Fatalf("IsOrphanInPool: want %v, got %v", inOrphanPool, 436 gotOrphanPool) 437 } 438 439 gotTxPool := tc.harness.txPool.IsTransactionInPool(txHash) 440 if inTxPool != gotTxPool { 441 tc.t.Fatalf("IsTransactionInPool: want %v, got %v", inTxPool, 442 gotTxPool) 443 } 444 445 gotHaveTx := tc.harness.txPool.HaveTransaction(txHash) 446 wantHaveTx := inOrphanPool || inTxPool 447 if wantHaveTx != gotHaveTx { 448 tc.t.Fatalf("HaveTransaction: want %v, got %v", wantHaveTx, 449 gotHaveTx) 450 } 451 } 452 453 // TestSimpleOrphanChain ensures that a simple chain of orphans is handled 454 // properly. In particular, it generates a chain of single input, single output 455 // transactions and inserts them while skipping the first linking transaction so 456 // they are all orphans. Finally, it adds the linking transaction and ensures 457 // the entire orphan chain is moved to the transaction pool. 458 func TestSimpleOrphanChain(t *testing.T) { 459 t.Parallel() 460 461 harness, spendableOuts, err := newPoolHarness(&chaincfg.MainNetParams) 462 if err != nil { 463 t.Fatalf("unable to create test pool: %v", err) 464 } 465 tc := &testContext{t, harness} 466 467 // Create a chain of transactions rooted with the first spendable output 468 // provided by the harness. 469 maxOrphans := uint32(harness.txPool.cfg.Policy.MaxOrphanTxs) 470 chainedTxns, err := harness.CreateTxChain(spendableOuts[0], maxOrphans+1) 471 if err != nil { 472 t.Fatalf("unable to create transaction chain: %v", err) 473 } 474 475 // Ensure the orphans are accepted (only up to the maximum allowed so 476 // none are evicted). 477 for _, tx := range chainedTxns[1 : maxOrphans+1] { 478 acceptedTxns, err := harness.txPool.ProcessTransaction(tx, true, 479 false, 0) 480 if err != nil { 481 t.Fatalf("ProcessTransaction: failed to accept valid "+ 482 "orphan %v", err) 483 } 484 485 // Ensure no transactions were reported as accepted. 486 if len(acceptedTxns) != 0 { 487 t.Fatalf("ProcessTransaction: reported %d accepted "+ 488 "transactions from what should be an orphan", 489 len(acceptedTxns)) 490 } 491 492 // Ensure the transaction is in the orphan pool, is not in the 493 // transaction pool, and is reported as available. 494 testPoolMembership(tc, tx, true, false) 495 } 496 497 // Add the transaction which completes the orphan chain and ensure they 498 // all get accepted. Notice the accept orphans flag is also false here 499 // to ensure it has no bearing on whether or not already existing 500 // orphans in the pool are linked. 501 acceptedTxns, err := harness.txPool.ProcessTransaction(chainedTxns[0], 502 false, false, 0) 503 if err != nil { 504 t.Fatalf("ProcessTransaction: failed to accept valid "+ 505 "orphan %v", err) 506 } 507 if len(acceptedTxns) != len(chainedTxns) { 508 t.Fatalf("ProcessTransaction: reported accepted transactions "+ 509 "length does not match expected -- got %d, want %d", 510 len(acceptedTxns), len(chainedTxns)) 511 } 512 for _, txD := range acceptedTxns { 513 // Ensure the transaction is no longer in the orphan pool, is 514 // now in the transaction pool, and is reported as available. 515 testPoolMembership(tc, txD.Tx, false, true) 516 } 517 } 518 519 // TestOrphanReject ensures that orphans are properly rejected when the allow 520 // orphans flag is not set on ProcessTransaction. 521 func TestOrphanReject(t *testing.T) { 522 t.Parallel() 523 524 harness, outputs, err := newPoolHarness(&chaincfg.MainNetParams) 525 if err != nil { 526 t.Fatalf("unable to create test pool: %v", err) 527 } 528 tc := &testContext{t, harness} 529 530 // Create a chain of transactions rooted with the first spendable output 531 // provided by the harness. 532 maxOrphans := uint32(harness.txPool.cfg.Policy.MaxOrphanTxs) 533 chainedTxns, err := harness.CreateTxChain(outputs[0], maxOrphans+1) 534 if err != nil { 535 t.Fatalf("unable to create transaction chain: %v", err) 536 } 537 538 // Ensure orphans are rejected when the allow orphans flag is not set. 539 for _, tx := range chainedTxns[1:] { 540 acceptedTxns, err := harness.txPool.ProcessTransaction(tx, false, 541 false, 0) 542 if err == nil { 543 t.Fatalf("ProcessTransaction: did not fail on orphan "+ 544 "%v when allow orphans flag is false", tx.Hash()) 545 } 546 expectedErr := RuleError{} 547 if reflect.TypeOf(err) != reflect.TypeOf(expectedErr) { 548 t.Fatalf("ProcessTransaction: wrong error got: <%T> %v, "+ 549 "want: <%T>", err, err, expectedErr) 550 } 551 code, extracted := extractRejectCode(err) 552 if !extracted { 553 t.Fatalf("ProcessTransaction: failed to extract reject "+ 554 "code from error %q", err) 555 } 556 if code != wire.RejectDuplicate { 557 t.Fatalf("ProcessTransaction: unexpected reject code "+ 558 "-- got %v, want %v", code, wire.RejectDuplicate) 559 } 560 561 // Ensure no transactions were reported as accepted. 562 if len(acceptedTxns) != 0 { 563 t.Fatalf("ProcessTransaction: reported %d accepted "+ 564 "transactions from failed orphan attempt", 565 len(acceptedTxns)) 566 } 567 568 // Ensure the transaction is not in the orphan pool, not in the 569 // transaction pool, and not reported as available 570 testPoolMembership(tc, tx, false, false) 571 } 572 } 573 574 // TestOrphanEviction ensures that exceeding the maximum number of orphans 575 // evicts entries to make room for the new ones. 576 func TestOrphanEviction(t *testing.T) { 577 t.Parallel() 578 579 harness, outputs, err := newPoolHarness(&chaincfg.MainNetParams) 580 if err != nil { 581 t.Fatalf("unable to create test pool: %v", err) 582 } 583 tc := &testContext{t, harness} 584 585 // Create a chain of transactions rooted with the first spendable output 586 // provided by the harness that is long enough to be able to force 587 // several orphan evictions. 588 maxOrphans := uint32(harness.txPool.cfg.Policy.MaxOrphanTxs) 589 chainedTxns, err := harness.CreateTxChain(outputs[0], maxOrphans+5) 590 if err != nil { 591 t.Fatalf("unable to create transaction chain: %v", err) 592 } 593 594 // Add enough orphans to exceed the max allowed while ensuring they are 595 // all accepted. This will cause an eviction. 596 for _, tx := range chainedTxns[1:] { 597 acceptedTxns, err := harness.txPool.ProcessTransaction(tx, true, 598 false, 0) 599 if err != nil { 600 t.Fatalf("ProcessTransaction: failed to accept valid "+ 601 "orphan %v", err) 602 } 603 604 // Ensure no transactions were reported as accepted. 605 if len(acceptedTxns) != 0 { 606 t.Fatalf("ProcessTransaction: reported %d accepted "+ 607 "transactions from what should be an orphan", 608 len(acceptedTxns)) 609 } 610 611 // Ensure the transaction is in the orphan pool, is not in the 612 // transaction pool, and is reported as available. 613 testPoolMembership(tc, tx, true, false) 614 } 615 616 // Figure out which transactions were evicted and make sure the number 617 // evicted matches the expected number. 618 var evictedTxns []*btcutil.Tx 619 for _, tx := range chainedTxns[1:] { 620 if !harness.txPool.IsOrphanInPool(tx.Hash()) { 621 evictedTxns = append(evictedTxns, tx) 622 } 623 } 624 expectedEvictions := len(chainedTxns) - 1 - int(maxOrphans) 625 if len(evictedTxns) != expectedEvictions { 626 t.Fatalf("unexpected number of evictions -- got %d, want %d", 627 len(evictedTxns), expectedEvictions) 628 } 629 630 // Ensure none of the evicted transactions ended up in the transaction 631 // pool. 632 for _, tx := range evictedTxns { 633 testPoolMembership(tc, tx, false, false) 634 } 635 } 636 637 // TestBasicOrphanRemoval ensure that orphan removal works as expected when an 638 // orphan that doesn't exist is removed both when there is another orphan that 639 // redeems it and when there is not. 640 func TestBasicOrphanRemoval(t *testing.T) { 641 t.Parallel() 642 643 const maxOrphans = 4 644 harness, spendableOuts, err := newPoolHarness(&chaincfg.MainNetParams) 645 if err != nil { 646 t.Fatalf("unable to create test pool: %v", err) 647 } 648 harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans 649 tc := &testContext{t, harness} 650 651 // Create a chain of transactions rooted with the first spendable output 652 // provided by the harness. 653 chainedTxns, err := harness.CreateTxChain(spendableOuts[0], maxOrphans+1) 654 if err != nil { 655 t.Fatalf("unable to create transaction chain: %v", err) 656 } 657 658 // Ensure the orphans are accepted (only up to the maximum allowed so 659 // none are evicted). 660 for _, tx := range chainedTxns[1 : maxOrphans+1] { 661 acceptedTxns, err := harness.txPool.ProcessTransaction(tx, true, 662 false, 0) 663 if err != nil { 664 t.Fatalf("ProcessTransaction: failed to accept valid "+ 665 "orphan %v", err) 666 } 667 668 // Ensure no transactions were reported as accepted. 669 if len(acceptedTxns) != 0 { 670 t.Fatalf("ProcessTransaction: reported %d accepted "+ 671 "transactions from what should be an orphan", 672 len(acceptedTxns)) 673 } 674 675 // Ensure the transaction is in the orphan pool, not in the 676 // transaction pool, and reported as available. 677 testPoolMembership(tc, tx, true, false) 678 } 679 680 // Attempt to remove an orphan that has no redeemers and is not present, 681 // and ensure the state of all other orphans are unaffected. 682 nonChainedOrphanTx, err := harness.CreateSignedTx([]spendableOutput{{ 683 amount: btcutil.Amount(5000000000), 684 outPoint: wire.OutPoint{Hash: chainhash.Hash{}, Index: 0}, 685 }}, 1, 0, false) 686 if err != nil { 687 t.Fatalf("unable to create signed tx: %v", err) 688 } 689 690 harness.txPool.RemoveOrphan(nonChainedOrphanTx) 691 testPoolMembership(tc, nonChainedOrphanTx, false, false) 692 for _, tx := range chainedTxns[1 : maxOrphans+1] { 693 testPoolMembership(tc, tx, true, false) 694 } 695 696 // Attempt to remove an orphan that has a existing redeemer but itself 697 // is not present and ensure the state of all other orphans (including 698 // the one that redeems it) are unaffected. 699 harness.txPool.RemoveOrphan(chainedTxns[0]) 700 testPoolMembership(tc, chainedTxns[0], false, false) 701 for _, tx := range chainedTxns[1 : maxOrphans+1] { 702 testPoolMembership(tc, tx, true, false) 703 } 704 705 // Remove each orphan one-by-one and ensure they are removed as 706 // expected. 707 for _, tx := range chainedTxns[1 : maxOrphans+1] { 708 harness.txPool.RemoveOrphan(tx) 709 testPoolMembership(tc, tx, false, false) 710 } 711 } 712 713 // TestOrphanChainRemoval ensure that orphan chains (orphans that spend outputs 714 // from other orphans) are removed as expected. 715 func TestOrphanChainRemoval(t *testing.T) { 716 t.Parallel() 717 718 const maxOrphans = 10 719 harness, spendableOuts, err := newPoolHarness(&chaincfg.MainNetParams) 720 if err != nil { 721 t.Fatalf("unable to create test pool: %v", err) 722 } 723 harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans 724 tc := &testContext{t, harness} 725 726 // Create a chain of transactions rooted with the first spendable output 727 // provided by the harness. 728 chainedTxns, err := harness.CreateTxChain(spendableOuts[0], maxOrphans+1) 729 if err != nil { 730 t.Fatalf("unable to create transaction chain: %v", err) 731 } 732 733 // Ensure the orphans are accepted (only up to the maximum allowed so 734 // none are evicted). 735 for _, tx := range chainedTxns[1 : maxOrphans+1] { 736 acceptedTxns, err := harness.txPool.ProcessTransaction(tx, true, 737 false, 0) 738 if err != nil { 739 t.Fatalf("ProcessTransaction: failed to accept valid "+ 740 "orphan %v", err) 741 } 742 743 // Ensure no transactions were reported as accepted. 744 if len(acceptedTxns) != 0 { 745 t.Fatalf("ProcessTransaction: reported %d accepted "+ 746 "transactions from what should be an orphan", 747 len(acceptedTxns)) 748 } 749 750 // Ensure the transaction is in the orphan pool, not in the 751 // transaction pool, and reported as available. 752 testPoolMembership(tc, tx, true, false) 753 } 754 755 // Remove the first orphan that starts the orphan chain without the 756 // remove redeemer flag set and ensure that only the first orphan was 757 // removed. 758 harness.txPool.mtx.Lock() 759 harness.txPool.removeOrphan(chainedTxns[1], false) 760 harness.txPool.mtx.Unlock() 761 testPoolMembership(tc, chainedTxns[1], false, false) 762 for _, tx := range chainedTxns[2 : maxOrphans+1] { 763 testPoolMembership(tc, tx, true, false) 764 } 765 766 // Remove the first remaining orphan that starts the orphan chain with 767 // the remove redeemer flag set and ensure they are all removed. 768 harness.txPool.mtx.Lock() 769 harness.txPool.removeOrphan(chainedTxns[2], true) 770 harness.txPool.mtx.Unlock() 771 for _, tx := range chainedTxns[2 : maxOrphans+1] { 772 testPoolMembership(tc, tx, false, false) 773 } 774 } 775 776 // TestMultiInputOrphanDoubleSpend ensures that orphans that spend from an 777 // output that is spend by another transaction entering the pool are removed. 778 func TestMultiInputOrphanDoubleSpend(t *testing.T) { 779 t.Parallel() 780 781 const maxOrphans = 4 782 harness, outputs, err := newPoolHarness(&chaincfg.MainNetParams) 783 if err != nil { 784 t.Fatalf("unable to create test pool: %v", err) 785 } 786 harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans 787 tc := &testContext{t, harness} 788 789 // Create a chain of transactions rooted with the first spendable output 790 // provided by the harness. 791 chainedTxns, err := harness.CreateTxChain(outputs[0], maxOrphans+1) 792 if err != nil { 793 t.Fatalf("unable to create transaction chain: %v", err) 794 } 795 796 // Start by adding the orphan transactions from the generated chain 797 // except the final one. 798 for _, tx := range chainedTxns[1:maxOrphans] { 799 acceptedTxns, err := harness.txPool.ProcessTransaction(tx, true, 800 false, 0) 801 if err != nil { 802 t.Fatalf("ProcessTransaction: failed to accept valid "+ 803 "orphan %v", err) 804 } 805 if len(acceptedTxns) != 0 { 806 t.Fatalf("ProcessTransaction: reported %d accepted transactions "+ 807 "from what should be an orphan", len(acceptedTxns)) 808 } 809 testPoolMembership(tc, tx, true, false) 810 } 811 812 // Ensure a transaction that contains a double spend of the same output 813 // as the second orphan that was just added as well as a valid spend 814 // from that last orphan in the chain generated above (and is not in the 815 // orphan pool) is accepted to the orphan pool. This must be allowed 816 // since it would otherwise be possible for a malicious actor to disrupt 817 // tx chains. 818 doubleSpendTx, err := harness.CreateSignedTx([]spendableOutput{ 819 txOutToSpendableOut(chainedTxns[1], 0), 820 txOutToSpendableOut(chainedTxns[maxOrphans], 0), 821 }, 1, 0, false) 822 if err != nil { 823 t.Fatalf("unable to create signed tx: %v", err) 824 } 825 acceptedTxns, err := harness.txPool.ProcessTransaction(doubleSpendTx, 826 true, false, 0) 827 if err != nil { 828 t.Fatalf("ProcessTransaction: failed to accept valid orphan %v", 829 err) 830 } 831 if len(acceptedTxns) != 0 { 832 t.Fatalf("ProcessTransaction: reported %d accepted transactions "+ 833 "from what should be an orphan", len(acceptedTxns)) 834 } 835 testPoolMembership(tc, doubleSpendTx, true, false) 836 837 // Add the transaction which completes the orphan chain and ensure the 838 // chain gets accepted. Notice the accept orphans flag is also false 839 // here to ensure it has no bearing on whether or not already existing 840 // orphans in the pool are linked. 841 // 842 // This will cause the shared output to become a concrete spend which 843 // will in turn must cause the double spending orphan to be removed. 844 acceptedTxns, err = harness.txPool.ProcessTransaction(chainedTxns[0], 845 false, false, 0) 846 if err != nil { 847 t.Fatalf("ProcessTransaction: failed to accept valid tx %v", err) 848 } 849 if len(acceptedTxns) != maxOrphans { 850 t.Fatalf("ProcessTransaction: reported accepted transactions "+ 851 "length does not match expected -- got %d, want %d", 852 len(acceptedTxns), maxOrphans) 853 } 854 for _, txD := range acceptedTxns { 855 // Ensure the transaction is no longer in the orphan pool, is 856 // in the transaction pool, and is reported as available. 857 testPoolMembership(tc, txD.Tx, false, true) 858 } 859 860 // Ensure the double spending orphan is no longer in the orphan pool and 861 // was not moved to the transaction pool. 862 testPoolMembership(tc, doubleSpendTx, false, false) 863 } 864 865 // TestCheckSpend tests that CheckSpend returns the expected spends found in 866 // the mempool. 867 func TestCheckSpend(t *testing.T) { 868 t.Parallel() 869 870 harness, outputs, err := newPoolHarness(&chaincfg.MainNetParams) 871 if err != nil { 872 t.Fatalf("unable to create test pool: %v", err) 873 } 874 875 // The mempool is empty, so none of the spendable outputs should have a 876 // spend there. 877 for _, op := range outputs { 878 spend := harness.txPool.CheckSpend(op.outPoint) 879 if spend != nil { 880 t.Fatalf("Unexpeced spend found in pool: %v", spend) 881 } 882 } 883 884 // Create a chain of transactions rooted with the first spendable 885 // output provided by the harness. 886 const txChainLength = 5 887 chainedTxns, err := harness.CreateTxChain(outputs[0], txChainLength) 888 if err != nil { 889 t.Fatalf("unable to create transaction chain: %v", err) 890 } 891 for _, tx := range chainedTxns { 892 _, err := harness.txPool.ProcessTransaction(tx, true, 893 false, 0) 894 if err != nil { 895 t.Fatalf("ProcessTransaction: failed to accept "+ 896 "tx: %v", err) 897 } 898 } 899 900 // The first tx in the chain should be the spend of the spendable 901 // output. 902 op := outputs[0].outPoint 903 spend := harness.txPool.CheckSpend(op) 904 if spend != chainedTxns[0] { 905 t.Fatalf("expected %v to be spent by %v, instead "+ 906 "got %v", op, chainedTxns[0], spend) 907 } 908 909 // Now all but the last tx should be spent by the next. 910 for i := 0; i < len(chainedTxns)-1; i++ { 911 op = wire.OutPoint{ 912 Hash: *chainedTxns[i].Hash(), 913 Index: 0, 914 } 915 expSpend := chainedTxns[i+1] 916 spend = harness.txPool.CheckSpend(op) 917 if spend != expSpend { 918 t.Fatalf("expected %v to be spent by %v, instead "+ 919 "got %v", op, expSpend, spend) 920 } 921 } 922 923 // The last tx should have no spend. 924 op = wire.OutPoint{ 925 Hash: *chainedTxns[txChainLength-1].Hash(), 926 Index: 0, 927 } 928 spend = harness.txPool.CheckSpend(op) 929 if spend != nil { 930 t.Fatalf("Unexpeced spend found in pool: %v", spend) 931 } 932 } 933 934 // TestSignalsReplacement tests that transactions properly signal they can be 935 // replaced using RBF. 936 func TestSignalsReplacement(t *testing.T) { 937 t.Parallel() 938 939 testCases := []struct { 940 name string 941 setup func(ctx *testContext) *btcutil.Tx 942 signalsReplacement bool 943 }{ 944 { 945 // Transactions can signal replacement through 946 // inheritance if any of its ancestors does. 947 name: "non-signaling with unconfirmed non-signaling parent", 948 setup: func(ctx *testContext) *btcutil.Tx { 949 coinbase := ctx.addCoinbaseTx(1) 950 951 coinbaseOut := txOutToSpendableOut(coinbase, 0) 952 outs := []spendableOutput{coinbaseOut} 953 parent := ctx.addSignedTx(outs, 1, 0, false, false) 954 955 parentOut := txOutToSpendableOut(parent, 0) 956 outs = []spendableOutput{parentOut} 957 return ctx.addSignedTx(outs, 1, 0, false, false) 958 }, 959 signalsReplacement: false, 960 }, 961 { 962 // Transactions can signal replacement through 963 // inheritance if any of its ancestors does, but they 964 // must be unconfirmed. 965 name: "non-signaling with confirmed signaling parent", 966 setup: func(ctx *testContext) *btcutil.Tx { 967 coinbase := ctx.addCoinbaseTx(1) 968 969 coinbaseOut := txOutToSpendableOut(coinbase, 0) 970 outs := []spendableOutput{coinbaseOut} 971 parent := ctx.addSignedTx(outs, 1, 0, true, true) 972 973 parentOut := txOutToSpendableOut(parent, 0) 974 outs = []spendableOutput{parentOut} 975 return ctx.addSignedTx(outs, 1, 0, false, false) 976 }, 977 signalsReplacement: false, 978 }, 979 { 980 name: "inherited signaling", 981 setup: func(ctx *testContext) *btcutil.Tx { 982 coinbase := ctx.addCoinbaseTx(1) 983 984 // We'll create a chain of transactions 985 // A -> B -> C where C is the transaction we'll 986 // be checking for replacement signaling. The 987 // transaction can signal replacement through 988 // any of its ancestors as long as they also 989 // signal replacement. 990 coinbaseOut := txOutToSpendableOut(coinbase, 0) 991 outs := []spendableOutput{coinbaseOut} 992 a := ctx.addSignedTx(outs, 1, 0, true, false) 993 994 aOut := txOutToSpendableOut(a, 0) 995 outs = []spendableOutput{aOut} 996 b := ctx.addSignedTx(outs, 1, 0, false, false) 997 998 bOut := txOutToSpendableOut(b, 0) 999 outs = []spendableOutput{bOut} 1000 return ctx.addSignedTx(outs, 1, 0, false, false) 1001 }, 1002 signalsReplacement: true, 1003 }, 1004 { 1005 name: "explicit signaling", 1006 setup: func(ctx *testContext) *btcutil.Tx { 1007 coinbase := ctx.addCoinbaseTx(1) 1008 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1009 outs := []spendableOutput{coinbaseOut} 1010 return ctx.addSignedTx(outs, 1, 0, true, false) 1011 }, 1012 signalsReplacement: true, 1013 }, 1014 } 1015 1016 for _, testCase := range testCases { 1017 success := t.Run(testCase.name, func(t *testing.T) { 1018 // We'll start each test by creating our mempool 1019 // harness. 1020 harness, _, err := newPoolHarness(&chaincfg.MainNetParams) 1021 if err != nil { 1022 t.Fatalf("unable to create test pool: %v", err) 1023 } 1024 ctx := &testContext{t, harness} 1025 1026 // Each test includes a setup method, which will set up 1027 // its required dependencies. The transaction returned 1028 // is the one we'll be using to determine if it signals 1029 // replacement support. 1030 tx := testCase.setup(ctx) 1031 1032 // Each test should match the expected response. 1033 signalsReplacement := ctx.harness.txPool.signalsReplacement( 1034 tx, nil, 1035 ) 1036 if signalsReplacement && !testCase.signalsReplacement { 1037 ctx.t.Fatalf("expected transaction %v to not "+ 1038 "signal replacement", tx.Hash()) 1039 } 1040 if !signalsReplacement && testCase.signalsReplacement { 1041 ctx.t.Fatalf("expected transaction %v to "+ 1042 "signal replacement", tx.Hash()) 1043 } 1044 }) 1045 if !success { 1046 break 1047 } 1048 } 1049 } 1050 1051 // TestCheckPoolDoubleSpend ensures that the mempool can properly detect 1052 // unconfirmed double spends in the case of replacement and non-replacement 1053 // transactions. 1054 func TestCheckPoolDoubleSpend(t *testing.T) { 1055 t.Parallel() 1056 1057 testCases := []struct { 1058 name string 1059 setup func(ctx *testContext) *btcutil.Tx 1060 isReplacement bool 1061 }{ 1062 { 1063 // Transactions that don't double spend any inputs, 1064 // regardless of whether they signal replacement or not, 1065 // are valid. 1066 name: "no double spend", 1067 setup: func(ctx *testContext) *btcutil.Tx { 1068 coinbase := ctx.addCoinbaseTx(1) 1069 1070 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1071 outs := []spendableOutput{coinbaseOut} 1072 parent := ctx.addSignedTx(outs, 1, 0, false, false) 1073 1074 parentOut := txOutToSpendableOut(parent, 0) 1075 outs = []spendableOutput{parentOut} 1076 return ctx.addSignedTx(outs, 2, 0, false, false) 1077 }, 1078 isReplacement: false, 1079 }, 1080 { 1081 // Transactions that don't signal replacement and double 1082 // spend inputs are invalid. 1083 name: "non-replacement double spend", 1084 setup: func(ctx *testContext) *btcutil.Tx { 1085 coinbase1 := ctx.addCoinbaseTx(1) 1086 coinbaseOut1 := txOutToSpendableOut(coinbase1, 0) 1087 outs := []spendableOutput{coinbaseOut1} 1088 ctx.addSignedTx(outs, 1, 0, true, false) 1089 1090 coinbase2 := ctx.addCoinbaseTx(1) 1091 coinbaseOut2 := txOutToSpendableOut(coinbase2, 0) 1092 outs = []spendableOutput{coinbaseOut2} 1093 ctx.addSignedTx(outs, 1, 0, false, false) 1094 1095 // Create a transaction that spends both 1096 // coinbase outputs that were spent above. This 1097 // should be detected as a double spend as one 1098 // of the transactions doesn't signal 1099 // replacement. 1100 outs = []spendableOutput{coinbaseOut1, coinbaseOut2} 1101 tx, err := ctx.harness.CreateSignedTx( 1102 outs, 1, 0, false, 1103 ) 1104 if err != nil { 1105 ctx.t.Fatalf("unable to create "+ 1106 "transaction: %v", err) 1107 } 1108 1109 return tx 1110 }, 1111 isReplacement: false, 1112 }, 1113 { 1114 // Transactions that double spend inputs and signal 1115 // replacement are invalid if the mempool's policy 1116 // rejects replacements. 1117 name: "reject replacement policy", 1118 setup: func(ctx *testContext) *btcutil.Tx { 1119 // Set the mempool's policy to reject 1120 // replacements. Even if we have a transaction 1121 // that spends inputs that signal replacement, 1122 // it should still be rejected. 1123 ctx.harness.txPool.cfg.Policy.RejectReplacement = true 1124 1125 coinbase := ctx.addCoinbaseTx(1) 1126 1127 // Create a replaceable parent that spends the 1128 // coinbase output. 1129 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1130 outs := []spendableOutput{coinbaseOut} 1131 parent := ctx.addSignedTx(outs, 1, 0, true, false) 1132 1133 parentOut := txOutToSpendableOut(parent, 0) 1134 outs = []spendableOutput{parentOut} 1135 ctx.addSignedTx(outs, 1, 0, false, false) 1136 1137 // Create another transaction that spends the 1138 // same coinbase output. Since the original 1139 // spender of this output, all of its spends 1140 // should also be conflicts. 1141 outs = []spendableOutput{coinbaseOut} 1142 tx, err := ctx.harness.CreateSignedTx( 1143 outs, 2, 0, false, 1144 ) 1145 if err != nil { 1146 ctx.t.Fatalf("unable to create "+ 1147 "transaction: %v", err) 1148 } 1149 1150 return tx 1151 }, 1152 isReplacement: false, 1153 }, 1154 { 1155 // Transactions that double spend inputs and signal 1156 // replacement are valid as long as the mempool's policy 1157 // accepts them. 1158 name: "replacement double spend", 1159 setup: func(ctx *testContext) *btcutil.Tx { 1160 coinbase := ctx.addCoinbaseTx(1) 1161 1162 // Create a replaceable parent that spends the 1163 // coinbase output. 1164 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1165 outs := []spendableOutput{coinbaseOut} 1166 parent := ctx.addSignedTx(outs, 1, 0, true, false) 1167 1168 parentOut := txOutToSpendableOut(parent, 0) 1169 outs = []spendableOutput{parentOut} 1170 ctx.addSignedTx(outs, 1, 0, false, false) 1171 1172 // Create another transaction that spends the 1173 // same coinbase output. Since the original 1174 // spender of this output, all of its spends 1175 // should also be conflicts. 1176 outs = []spendableOutput{coinbaseOut} 1177 tx, err := ctx.harness.CreateSignedTx( 1178 outs, 2, 0, false, 1179 ) 1180 if err != nil { 1181 ctx.t.Fatalf("unable to create "+ 1182 "transaction: %v", err) 1183 } 1184 1185 return tx 1186 }, 1187 isReplacement: true, 1188 }, 1189 } 1190 1191 for _, testCase := range testCases { 1192 success := t.Run(testCase.name, func(t *testing.T) { 1193 // We'll start each test by creating our mempool 1194 // harness. 1195 harness, _, err := newPoolHarness(&chaincfg.MainNetParams) 1196 if err != nil { 1197 t.Fatalf("unable to create test pool: %v", err) 1198 } 1199 ctx := &testContext{t, harness} 1200 1201 // Each test includes a setup method, which will set up 1202 // its required dependencies. The transaction returned 1203 // is the one we'll be querying for the expected 1204 // conflicts. 1205 tx := testCase.setup(ctx) 1206 1207 // Ensure that the mempool properly detected the double 1208 // spend unless this is a replacement transaction. 1209 isReplacement, err := 1210 ctx.harness.txPool.checkPoolDoubleSpend(tx) 1211 if testCase.isReplacement && err != nil { 1212 t.Fatalf("expected no error for replacement "+ 1213 "transaction, got: %v", err) 1214 } 1215 if isReplacement && !testCase.isReplacement { 1216 t.Fatalf("expected replacement transaction") 1217 } 1218 if !isReplacement && testCase.isReplacement { 1219 t.Fatalf("expected non-replacement transaction") 1220 } 1221 }) 1222 if !success { 1223 break 1224 } 1225 } 1226 } 1227 1228 // TestConflicts ensures that the mempool can properly detect conflicts when 1229 // processing new incoming transactions. 1230 func TestConflicts(t *testing.T) { 1231 t.Parallel() 1232 1233 testCases := []struct { 1234 name string 1235 1236 // setup sets up the required dependencies for each test. It 1237 // returns the transaction we'll check for conflicts and its 1238 // expected unique conflicts. 1239 setup func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) 1240 }{ 1241 { 1242 // Create a transaction that would introduce no 1243 // conflicts in the mempool. This is done by not 1244 // spending any outputs that are currently being spent 1245 // within the mempool. 1246 name: "no conflicts", 1247 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1248 coinbase := ctx.addCoinbaseTx(1) 1249 1250 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1251 outs := []spendableOutput{coinbaseOut} 1252 parent := ctx.addSignedTx(outs, 1, 0, false, false) 1253 1254 parentOut := txOutToSpendableOut(parent, 0) 1255 outs = []spendableOutput{parentOut} 1256 tx, err := ctx.harness.CreateSignedTx( 1257 outs, 2, 0, false, 1258 ) 1259 if err != nil { 1260 ctx.t.Fatalf("unable to create "+ 1261 "transaction: %v", err) 1262 } 1263 1264 return tx, nil 1265 }, 1266 }, 1267 { 1268 // Create a transaction that would introduce two 1269 // conflicts in the mempool by spending two outputs 1270 // which are each already being spent by a different 1271 // transaction within the mempool. 1272 name: "conflicts", 1273 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1274 coinbase1 := ctx.addCoinbaseTx(1) 1275 coinbaseOut1 := txOutToSpendableOut(coinbase1, 0) 1276 outs := []spendableOutput{coinbaseOut1} 1277 conflict1 := ctx.addSignedTx( 1278 outs, 1, 0, false, false, 1279 ) 1280 1281 coinbase2 := ctx.addCoinbaseTx(1) 1282 coinbaseOut2 := txOutToSpendableOut(coinbase2, 0) 1283 outs = []spendableOutput{coinbaseOut2} 1284 conflict2 := ctx.addSignedTx( 1285 outs, 1, 0, false, false, 1286 ) 1287 1288 // Create a transaction that spends both 1289 // coinbase outputs that were spent above. 1290 outs = []spendableOutput{coinbaseOut1, coinbaseOut2} 1291 tx, err := ctx.harness.CreateSignedTx( 1292 outs, 1, 0, false, 1293 ) 1294 if err != nil { 1295 ctx.t.Fatalf("unable to create "+ 1296 "transaction: %v", err) 1297 } 1298 1299 return tx, []*btcutil.Tx{conflict1, conflict2} 1300 }, 1301 }, 1302 { 1303 // Create a transaction that would introduce two 1304 // conflicts in the mempool by spending an output 1305 // already being spent in the mempool by a different 1306 // transaction. The second conflict stems from spending 1307 // the transaction that spends the original spender of 1308 // the output, i.e., a descendant of the original 1309 // spender. 1310 name: "descendant conflicts", 1311 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1312 coinbase := ctx.addCoinbaseTx(1) 1313 1314 // Create a replaceable parent that spends the 1315 // coinbase output. 1316 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1317 outs := []spendableOutput{coinbaseOut} 1318 parent := ctx.addSignedTx(outs, 1, 0, false, false) 1319 1320 parentOut := txOutToSpendableOut(parent, 0) 1321 outs = []spendableOutput{parentOut} 1322 child := ctx.addSignedTx(outs, 1, 0, false, false) 1323 1324 // Create another transaction that spends the 1325 // same coinbase output. Since the original 1326 // spender of this output has descendants, they 1327 // should also be conflicts. 1328 outs = []spendableOutput{coinbaseOut} 1329 tx, err := ctx.harness.CreateSignedTx( 1330 outs, 2, 0, false, 1331 ) 1332 if err != nil { 1333 ctx.t.Fatalf("unable to create "+ 1334 "transaction: %v", err) 1335 } 1336 1337 return tx, []*btcutil.Tx{parent, child} 1338 }, 1339 }, 1340 } 1341 1342 for _, testCase := range testCases { 1343 success := t.Run(testCase.name, func(t *testing.T) { 1344 // We'll start each test by creating our mempool 1345 // harness. 1346 harness, _, err := newPoolHarness(&chaincfg.MainNetParams) 1347 if err != nil { 1348 t.Fatalf("unable to create test pool: %v", err) 1349 } 1350 ctx := &testContext{t, harness} 1351 1352 // Each test includes a setup method, which will set up 1353 // its required dependencies. The transaction returned 1354 // is the one we'll be querying for the expected 1355 // conflicts. 1356 tx, conflicts := testCase.setup(ctx) 1357 1358 // Assert the expected conflicts are returned. 1359 txConflicts := ctx.harness.txPool.txConflicts(tx) 1360 if len(txConflicts) != len(conflicts) { 1361 ctx.t.Fatalf("expected %d conflicts, got %d", 1362 len(conflicts), len(txConflicts)) 1363 } 1364 for _, conflict := range conflicts { 1365 conflictHash := *conflict.Hash() 1366 if _, ok := txConflicts[conflictHash]; !ok { 1367 ctx.t.Fatalf("expected %v to be found "+ 1368 "as a conflict", conflictHash) 1369 } 1370 } 1371 }) 1372 if !success { 1373 break 1374 } 1375 } 1376 } 1377 1378 // TestAncestorsDescendants ensures that we can properly retrieve the 1379 // unconfirmed ancestors and descendants of a transaction. 1380 func TestAncestorsDescendants(t *testing.T) { 1381 t.Parallel() 1382 1383 // We'll start the test by initializing our mempool harness. 1384 harness, outputs, err := newPoolHarness(&chaincfg.MainNetParams) 1385 if err != nil { 1386 t.Fatalf("unable to create test pool: %v", err) 1387 } 1388 ctx := &testContext{t, harness} 1389 1390 // We'll be creating the following chain of unconfirmed transactions: 1391 // 1392 // B ---- 1393 // / \ 1394 // A E 1395 // \ / 1396 // C -- D 1397 // 1398 // where B and C spend A, D spends C, and E spends B and D. We set up a 1399 // chain like so to properly detect ancestors and descendants past a 1400 // single parent/child. 1401 aInputs := outputs[:1] 1402 a := ctx.addSignedTx(aInputs, 2, 0, false, false) 1403 1404 bInputs := []spendableOutput{txOutToSpendableOut(a, 0)} 1405 b := ctx.addSignedTx(bInputs, 1, 0, false, false) 1406 1407 cInputs := []spendableOutput{txOutToSpendableOut(a, 1)} 1408 c := ctx.addSignedTx(cInputs, 1, 0, false, false) 1409 1410 dInputs := []spendableOutput{txOutToSpendableOut(c, 0)} 1411 d := ctx.addSignedTx(dInputs, 1, 0, false, false) 1412 1413 eInputs := []spendableOutput{ 1414 txOutToSpendableOut(b, 0), txOutToSpendableOut(d, 0), 1415 } 1416 e := ctx.addSignedTx(eInputs, 1, 0, false, false) 1417 1418 // We'll be querying for the ancestors of E. We should expect to see all 1419 // of the transactions that it depends on. 1420 expectedAncestors := map[chainhash.Hash]struct{}{ 1421 *a.Hash(): {}, *b.Hash(): {}, 1422 *c.Hash(): {}, *d.Hash(): {}, 1423 } 1424 ancestors := ctx.harness.txPool.txAncestors(e, nil) 1425 if len(ancestors) != len(expectedAncestors) { 1426 ctx.t.Fatalf("expected %d ancestors, got %d", 1427 len(expectedAncestors), len(ancestors)) 1428 } 1429 for ancestorHash := range ancestors { 1430 if _, ok := expectedAncestors[ancestorHash]; !ok { 1431 ctx.t.Fatalf("found unexpected ancestor %v", 1432 ancestorHash) 1433 } 1434 } 1435 1436 // Then, we'll query for the descendants of A. We should expect to see 1437 // all of the transactions that depend on it. 1438 expectedDescendants := map[chainhash.Hash]struct{}{ 1439 *b.Hash(): {}, *c.Hash(): {}, 1440 *d.Hash(): {}, *e.Hash(): {}, 1441 } 1442 descendants := ctx.harness.txPool.txDescendants(a, nil) 1443 if len(descendants) != len(expectedDescendants) { 1444 ctx.t.Fatalf("expected %d descendants, got %d", 1445 len(expectedDescendants), len(descendants)) 1446 } 1447 for descendantHash := range descendants { 1448 if _, ok := expectedDescendants[descendantHash]; !ok { 1449 ctx.t.Fatalf("found unexpected descendant %v", 1450 descendantHash) 1451 } 1452 } 1453 } 1454 1455 // TestRBF tests the different cases required for a transaction to properly 1456 // replace its conflicts given that they all signal replacement. 1457 func TestRBF(t *testing.T) { 1458 t.Parallel() 1459 1460 const defaultFee = btcutil.SatoshiPerBitcoin 1461 1462 testCases := []struct { 1463 name string 1464 setup func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) 1465 err string 1466 }{ 1467 { 1468 // A transaction cannot replace another if it doesn't 1469 // signal replacement. 1470 name: "non-replaceable parent", 1471 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1472 coinbase := ctx.addCoinbaseTx(1) 1473 1474 // Create a transaction that spends the coinbase 1475 // output and doesn't signal for replacement. 1476 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1477 outs := []spendableOutput{coinbaseOut} 1478 ctx.addSignedTx(outs, 1, defaultFee, false, false) 1479 1480 // Attempting to create another transaction that 1481 // spends the same output should fail since the 1482 // original transaction spending it doesn't 1483 // signal replacement. 1484 tx, err := ctx.harness.CreateSignedTx( 1485 outs, 2, defaultFee, false, 1486 ) 1487 if err != nil { 1488 ctx.t.Fatalf("unable to create "+ 1489 "transaction: %v", err) 1490 } 1491 1492 return tx, nil 1493 }, 1494 err: "already spent by transaction", 1495 }, 1496 { 1497 // A transaction cannot replace another if we don't 1498 // allow accepting replacement transactions. 1499 name: "reject replacement policy", 1500 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1501 ctx.harness.txPool.cfg.Policy.RejectReplacement = true 1502 1503 coinbase := ctx.addCoinbaseTx(1) 1504 1505 // Create a transaction that spends the coinbase 1506 // output and doesn't signal for replacement. 1507 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1508 outs := []spendableOutput{coinbaseOut} 1509 ctx.addSignedTx(outs, 1, defaultFee, true, false) 1510 1511 // Attempting to create another transaction that 1512 // spends the same output should fail since the 1513 // original transaction spending it doesn't 1514 // signal replacement. 1515 tx, err := ctx.harness.CreateSignedTx( 1516 outs, 2, defaultFee, false, 1517 ) 1518 if err != nil { 1519 ctx.t.Fatalf("unable to create "+ 1520 "transaction: %v", err) 1521 } 1522 1523 return tx, nil 1524 }, 1525 err: "already spent by transaction", 1526 }, 1527 { 1528 // A transaction cannot replace another if doing so 1529 // would cause more than 100 transactions being 1530 // replaced. 1531 name: "exceeds maximum conflicts", 1532 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1533 const numDescendants = 100 1534 coinbaseOuts := make( 1535 []spendableOutput, numDescendants, 1536 ) 1537 for i := 0; i < numDescendants; i++ { 1538 tx := ctx.addCoinbaseTx(1) 1539 coinbaseOuts[i] = txOutToSpendableOut(tx, 0) 1540 } 1541 parent := ctx.addSignedTx( 1542 coinbaseOuts, numDescendants, 1543 defaultFee, true, false, 1544 ) 1545 1546 // We'll then spend each output of the parent 1547 // transaction with a distinct transaction. 1548 for i := uint32(0); i < numDescendants; i++ { 1549 out := txOutToSpendableOut(parent, i) 1550 outs := []spendableOutput{out} 1551 ctx.addSignedTx( 1552 outs, 1, defaultFee, false, false, 1553 ) 1554 } 1555 1556 // We'll then create a replacement transaction 1557 // by spending one of the coinbase outputs. 1558 // Replacing the original spender of the 1559 // coinbase output would evict the maximum 1560 // number of transactions from the mempool, 1561 // however, so we should reject it. 1562 tx, err := ctx.harness.CreateSignedTx( 1563 coinbaseOuts[:1], 1, defaultFee, false, 1564 ) 1565 if err != nil { 1566 ctx.t.Fatalf("unable to create "+ 1567 "transaction: %v", err) 1568 } 1569 1570 return tx, nil 1571 }, 1572 err: "evicts more transactions than permitted", 1573 }, 1574 { 1575 // A transaction cannot replace another if the 1576 // replacement ends up spending an output that belongs 1577 // to one of the transactions it replaces. 1578 name: "replacement spends parent transaction", 1579 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1580 coinbase := ctx.addCoinbaseTx(1) 1581 1582 // Create a transaction that spends the coinbase 1583 // output and signals replacement. 1584 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1585 outs := []spendableOutput{coinbaseOut} 1586 parent := ctx.addSignedTx( 1587 outs, 1, defaultFee, true, false, 1588 ) 1589 1590 // Attempting to create another transaction that 1591 // spends it, but also replaces it, should be 1592 // invalid. 1593 parentOut := txOutToSpendableOut(parent, 0) 1594 outs = []spendableOutput{coinbaseOut, parentOut} 1595 tx, err := ctx.harness.CreateSignedTx( 1596 outs, 2, defaultFee, false, 1597 ) 1598 if err != nil { 1599 ctx.t.Fatalf("unable to create "+ 1600 "transaction: %v", err) 1601 } 1602 1603 return tx, nil 1604 }, 1605 err: "spends parent transaction", 1606 }, 1607 { 1608 // A transaction cannot replace another if it has a 1609 // lower fee rate than any of the transactions it 1610 // intends to replace. 1611 name: "insufficient fee rate", 1612 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1613 coinbase1 := ctx.addCoinbaseTx(1) 1614 coinbase2 := ctx.addCoinbaseTx(1) 1615 1616 // We'll create two transactions that each spend 1617 // one of the coinbase outputs. The first will 1618 // have a higher fee rate than the second. 1619 coinbaseOut1 := txOutToSpendableOut(coinbase1, 0) 1620 outs := []spendableOutput{coinbaseOut1} 1621 ctx.addSignedTx(outs, 1, defaultFee*2, true, false) 1622 1623 coinbaseOut2 := txOutToSpendableOut(coinbase2, 0) 1624 outs = []spendableOutput{coinbaseOut2} 1625 ctx.addSignedTx(outs, 1, defaultFee, true, false) 1626 1627 // We'll then create the replacement transaction 1628 // by spending the coinbase outputs. It will be 1629 // an invalid one however, since it won't have a 1630 // higher fee rate than the first transaction. 1631 outs = []spendableOutput{coinbaseOut1, coinbaseOut2} 1632 tx, err := ctx.harness.CreateSignedTx( 1633 outs, 1, defaultFee*2, false, 1634 ) 1635 if err != nil { 1636 ctx.t.Fatalf("unable to create "+ 1637 "transaction: %v", err) 1638 } 1639 1640 return tx, nil 1641 }, 1642 err: "insufficient fee rate", 1643 }, 1644 { 1645 // A transaction cannot replace another if it doesn't 1646 // have an absolute greater than the transactions its 1647 // replacing _plus_ the replacement transaction's 1648 // minimum relay fee. 1649 name: "insufficient absolute fee", 1650 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1651 coinbase := ctx.addCoinbaseTx(1) 1652 1653 // We'll create a transaction with two outputs 1654 // and the default fee. 1655 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1656 outs := []spendableOutput{coinbaseOut} 1657 ctx.addSignedTx(outs, 2, defaultFee, true, false) 1658 1659 // We'll create a replacement transaction with 1660 // one output, which should cause the 1661 // transaction's absolute fee to be lower than 1662 // the above's, so it'll be invalid. 1663 tx, err := ctx.harness.CreateSignedTx( 1664 outs, 1, defaultFee, false, 1665 ) 1666 if err != nil { 1667 ctx.t.Fatalf("unable to create "+ 1668 "transaction: %v", err) 1669 } 1670 1671 return tx, nil 1672 }, 1673 err: "insufficient absolute fee", 1674 }, 1675 { 1676 // A transaction cannot replace another if it introduces 1677 // a new unconfirmed input that was not already in any 1678 // of the transactions it's directly replacing. 1679 name: "spends new unconfirmed input", 1680 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1681 coinbase1 := ctx.addCoinbaseTx(1) 1682 coinbase2 := ctx.addCoinbaseTx(1) 1683 1684 // We'll create two unconfirmed transactions 1685 // from our coinbase transactions. 1686 coinbaseOut1 := txOutToSpendableOut(coinbase1, 0) 1687 outs := []spendableOutput{coinbaseOut1} 1688 ctx.addSignedTx(outs, 1, defaultFee, true, false) 1689 1690 coinbaseOut2 := txOutToSpendableOut(coinbase2, 0) 1691 outs = []spendableOutput{coinbaseOut2} 1692 newTx := ctx.addSignedTx( 1693 outs, 1, defaultFee, false, false, 1694 ) 1695 1696 // We should not be able to accept a replacement 1697 // transaction that spends an unconfirmed input 1698 // that was not previously included. 1699 newTxOut := txOutToSpendableOut(newTx, 0) 1700 outs = []spendableOutput{coinbaseOut1, newTxOut} 1701 tx, err := ctx.harness.CreateSignedTx( 1702 outs, 1, defaultFee*2, false, 1703 ) 1704 if err != nil { 1705 ctx.t.Fatalf("unable to create "+ 1706 "transaction: %v", err) 1707 } 1708 1709 return tx, nil 1710 }, 1711 err: "spends new unconfirmed input", 1712 }, 1713 { 1714 // A transaction can replace another with a higher fee. 1715 name: "higher fee", 1716 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1717 coinbase := ctx.addCoinbaseTx(1) 1718 1719 // Create a transaction that we'll directly 1720 // replace. 1721 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1722 outs := []spendableOutput{coinbaseOut} 1723 parent := ctx.addSignedTx( 1724 outs, 1, defaultFee, true, false, 1725 ) 1726 1727 // Spend the parent transaction to create a 1728 // descendant that will be indirectly replaced. 1729 parentOut := txOutToSpendableOut(parent, 0) 1730 outs = []spendableOutput{parentOut} 1731 child := ctx.addSignedTx( 1732 outs, 1, defaultFee, false, false, 1733 ) 1734 1735 // The replacement transaction should replace 1736 // both transactions above since it has a higher 1737 // fee and doesn't violate any other conditions 1738 // within the RBF policy. 1739 outs = []spendableOutput{coinbaseOut} 1740 tx, err := ctx.harness.CreateSignedTx( 1741 outs, 1, defaultFee*3, false, 1742 ) 1743 if err != nil { 1744 ctx.t.Fatalf("unable to create "+ 1745 "transaction: %v", err) 1746 } 1747 1748 return tx, []*btcutil.Tx{parent, child} 1749 }, 1750 err: "", 1751 }, 1752 { 1753 // A transaction that doesn't signal replacement, can 1754 // be replaced if the parent signals replacement. 1755 name: "inherited replacement", 1756 setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { 1757 coinbase := ctx.addCoinbaseTx(1) 1758 1759 // Create an initial parent transaction that 1760 // marks replacement, we won't be replacing 1761 // this directly however. 1762 coinbaseOut := txOutToSpendableOut(coinbase, 0) 1763 outs := []spendableOutput{coinbaseOut} 1764 parent := ctx.addSignedTx( 1765 outs, 1, defaultFee, true, false, 1766 ) 1767 1768 // Now create a transaction that spends that 1769 // parent transaction, which is marked as NOT 1770 // being RBF-able. 1771 parentOut := txOutToSpendableOut(parent, 0) 1772 parentOuts := []spendableOutput{parentOut} 1773 childNoReplace := ctx.addSignedTx( 1774 parentOuts, 1, defaultFee, false, false, 1775 ) 1776 1777 // Now we'll create another transaction that 1778 // replaces the *child* only. This should work 1779 // as the parent has been marked for RBF, even 1780 // though the child hasn't. 1781 respendOuts := []spendableOutput{parentOut} 1782 childReplace, err := ctx.harness.CreateSignedTx( 1783 respendOuts, 1, defaultFee*3, false, 1784 ) 1785 if err != nil { 1786 ctx.t.Fatalf("unable to create child tx: %v", err) 1787 } 1788 1789 return childReplace, []*btcutil.Tx{childNoReplace} 1790 }, 1791 err: "", 1792 }, 1793 } 1794 1795 for _, testCase := range testCases { 1796 success := t.Run(testCase.name, func(t *testing.T) { 1797 // We'll start each test by creating our mempool 1798 // harness. 1799 harness, _, err := newPoolHarness(&chaincfg.MainNetParams) 1800 if err != nil { 1801 t.Fatalf("unable to create test pool: %v", err) 1802 } 1803 1804 // We'll enable relay priority to ensure we can properly 1805 // test fees between replacement transactions and the 1806 // transactions it replaces. 1807 harness.txPool.cfg.Policy.DisableRelayPriority = false 1808 1809 // Each test includes a setup method, which will set up 1810 // its required dependencies. The transaction returned 1811 // is the intended replacement, which should replace the 1812 // expected list of transactions. 1813 ctx := &testContext{t, harness} 1814 replacementTx, replacedTxs := testCase.setup(ctx) 1815 1816 // Attempt to process the replacement transaction. If 1817 // it's not a valid one, we should see the error 1818 // expected by the test. 1819 _, err = ctx.harness.txPool.ProcessTransaction( 1820 replacementTx, false, false, 0, 1821 ) 1822 if testCase.err == "" && err != nil { 1823 ctx.t.Fatalf("expected no error when "+ 1824 "processing replacement transaction, "+ 1825 "got: %v", err) 1826 } 1827 if testCase.err != "" && err == nil { 1828 ctx.t.Fatalf("expected error when processing "+ 1829 "replacement transaction: %v", 1830 testCase.err) 1831 } 1832 if testCase.err != "" && err != nil { 1833 if !strings.Contains(err.Error(), testCase.err) { 1834 ctx.t.Fatalf("expected error: %v\n"+ 1835 "got: %v", testCase.err, err) 1836 } 1837 } 1838 1839 // If the replacement transaction is valid, we'll check 1840 // that it has been included in the mempool and its 1841 // conflicts have been removed. Otherwise, the conflicts 1842 // should remain in the mempool. 1843 valid := testCase.err == "" 1844 for _, tx := range replacedTxs { 1845 testPoolMembership(ctx, tx, false, !valid) 1846 } 1847 testPoolMembership(ctx, replacementTx, false, valid) 1848 }) 1849 if !success { 1850 break 1851 } 1852 } 1853 }