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