From 7f644019b80e573caaaf37f44f70754792b76b49 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 6 Dec 2018 21:13:59 -0800 Subject: [PATCH] chainntnfs/txnotifier_test: update tests with new registration changes --- chainntnfs/txnotifier_test.go | 465 +++++++++++++++++++++------------- 1 file changed, 285 insertions(+), 180 deletions(-) diff --git a/chainntnfs/txnotifier_test.go b/chainntnfs/txnotifier_test.go index d426ebdf..bc28f8f3 100644 --- a/chainntnfs/txnotifier_test.go +++ b/chainntnfs/txnotifier_test.go @@ -1,18 +1,39 @@ package chainntnfs_test import ( + "bytes" "sync" "testing" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/chainntnfs" ) var ( - zeroHash chainhash.Hash - zeroOutPoint wire.OutPoint + testRawScript = []byte{ + // OP_HASH160 + 0xa9, + // OP_DATA_20 + 0x14, + // <20-byte script hash> + 0x90, 0x1c, 0x86, 0x94, 0xc0, 0x3f, 0xaf, 0xd5, + 0x52, 0x28, 0x10, 0xe0, 0x33, 0x0f, 0x26, 0xe6, + 0x7a, 0x85, 0x33, 0xcd, + // OP_EQUAL + 0x87, + } + testSigScript = []byte{ + // OP_DATA_16 + 0x16, + // <22-byte redeem script> + 0x00, 0x14, 0x1d, 0x7c, 0xd6, 0xc7, 0x5c, 0x2e, + 0x86, 0xf4, 0xcb, 0xf9, 0x8e, 0xae, 0xd2, 0x21, + 0xb3, 0x0b, 0xd9, 0xa0, 0xb9, 0x28, + } + testScript, _ = txscript.ParsePkScript(testRawScript) ) type mockHintCache struct { @@ -116,19 +137,21 @@ func TestTxNotifierMaxConfs(t *testing.T) { // Registering one confirmation above the maximum should fail with // ErrTxMaxConfs. ntfn := &chainntnfs.ConfNtfn{ - ConfID: 1, - TxID: &zeroHash, + ConfRequest: chainntnfs.ConfRequest{ + TxID: chainntnfs.ZeroHash, + PkScript: testScript, + }, NumConfirmations: chainntnfs.MaxNumConfs + 1, Event: chainntnfs.NewConfirmationEvent( chainntnfs.MaxNumConfs, ), } - if _, err := n.RegisterConf(ntfn); err != chainntnfs.ErrTxMaxConfs { + if _, _, err := n.RegisterConf(ntfn); err != chainntnfs.ErrTxMaxConfs { t.Fatalf("expected chainntnfs.ErrTxMaxConfs, got %v", err) } ntfn.NumConfirmations-- - if _, err := n.RegisterConf(ntfn); err != nil { + if _, _, err := n.RegisterConf(ntfn); err != nil { t.Fatalf("unable to register conf ntfn: %v", err) } } @@ -143,12 +166,6 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) { tx2NumConfs uint32 = 2 ) - var ( - tx1 = wire.MsgTx{Version: 1} - tx2 = wire.MsgTx{Version: 2} - tx3 = wire.MsgTx{Version: 3} - ) - hintCache := newMockHintCache() n := chainntnfs.NewTxNotifier( 10, chainntnfs.ReorgSafetyLimit, hintCache, hintCache, @@ -157,23 +174,31 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) { // Create the test transactions and register them with the TxNotifier // before including them in a block to receive future // notifications. - tx1Hash := tx1.TxHash() + tx1 := wire.MsgTx{Version: 1} + tx1.AddTxOut(&wire.TxOut{PkScript: testRawScript}) ntfn1 := chainntnfs.ConfNtfn{ - TxID: &tx1Hash, + ConfRequest: chainntnfs.ConfRequest{ + TxID: tx1.TxHash(), + PkScript: testScript, + }, NumConfirmations: tx1NumConfs, Event: chainntnfs.NewConfirmationEvent(tx1NumConfs), } - if _, err := n.RegisterConf(&ntfn1); err != nil { + if _, _, err := n.RegisterConf(&ntfn1); err != nil { t.Fatalf("unable to register ntfn: %v", err) } - tx2Hash := tx2.TxHash() + tx2 := wire.MsgTx{Version: 2} + tx2.AddTxOut(&wire.TxOut{PkScript: testRawScript}) ntfn2 := chainntnfs.ConfNtfn{ - TxID: &tx2Hash, + ConfRequest: chainntnfs.ConfRequest{ + TxID: tx2.TxHash(), + PkScript: testScript, + }, NumConfirmations: tx2NumConfs, Event: chainntnfs.NewConfirmationEvent(tx2NumConfs), } - if _, err := n.RegisterConf(&ntfn2); err != nil { + if _, _, err := n.RegisterConf(&ntfn2); err != nil { t.Fatalf("unable to register ntfn: %v", err) } @@ -198,7 +223,7 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) { // Include the transactions in a block and add it to the TxNotifier. // This should confirm tx1, but not tx2. block1 := btcutil.NewBlock(&wire.MsgBlock{ - Transactions: []*wire.MsgTx{&tx1, &tx2, &tx3}, + Transactions: []*wire.MsgTx{&tx1, &tx2}, }) err := n.ConnectTip(block1.Hash(), 11, block1.Transactions()) @@ -261,10 +286,7 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) { // Create a new block and add it to the TxNotifier at the next height. // This should confirm tx2. - block2 := btcutil.NewBlock(&wire.MsgBlock{ - Transactions: []*wire.MsgTx{&tx3}, - }) - + block2 := btcutil.NewBlock(&wire.MsgBlock{}) err = n.ConnectTip(block2.Hash(), 12, block2.Transactions()) if err != nil { t.Fatalf("Failed to connect block: %v", err) @@ -339,33 +361,33 @@ func TestTxNotifierHistoricalConfDispatch(t *testing.T) { tx1Hash := tx1.TxHash() ntfn1 := chainntnfs.ConfNtfn{ ConfID: 0, - TxID: &tx1Hash, + ConfRequest: chainntnfs.ConfRequest{TxID: tx1Hash}, NumConfirmations: tx1NumConfs, Event: chainntnfs.NewConfirmationEvent(tx1NumConfs), } - if _, err := n.RegisterConf(&ntfn1); err != nil { + if _, _, err := n.RegisterConf(&ntfn1); err != nil { t.Fatalf("unable to register ntfn: %v", err) } tx2Hash := tx2.TxHash() ntfn2 := chainntnfs.ConfNtfn{ ConfID: 1, - TxID: &tx2Hash, + ConfRequest: chainntnfs.ConfRequest{TxID: tx2Hash}, NumConfirmations: tx2NumConfs, Event: chainntnfs.NewConfirmationEvent(tx2NumConfs), } - if _, err := n.RegisterConf(&ntfn2); err != nil { + if _, _, err := n.RegisterConf(&ntfn2); err != nil { t.Fatalf("unable to register ntfn: %v", err) } // Update tx1 with its confirmation details. We should only receive one // update since it only requires one confirmation and it already met it. txConf1 := chainntnfs.TxConfirmation{ - BlockHash: &zeroHash, + BlockHash: &chainntnfs.ZeroHash, BlockHeight: 9, TxIndex: 1, } - err := n.UpdateConfDetails(tx1Hash, &txConf1) + err := n.UpdateConfDetails(ntfn1.ConfRequest, &txConf1) if err != nil { t.Fatalf("unable to update conf details: %v", err) } @@ -394,11 +416,11 @@ func TestTxNotifierHistoricalConfDispatch(t *testing.T) { // of confirmations, but we should receive a confirmation update // indicating how many confirmation are left. txConf2 := chainntnfs.TxConfirmation{ - BlockHash: &zeroHash, + BlockHash: &chainntnfs.ZeroHash, BlockHeight: 9, TxIndex: 2, } - err = n.UpdateConfDetails(tx2Hash, &txConf2) + err = n.UpdateConfDetails(ntfn2.ConfRequest, &txConf2) if err != nil { t.Fatalf("unable to update conf details: %v", err) } @@ -481,10 +503,13 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) { // We'll start off by registering for a spend notification of an // outpoint. ntfn := &chainntnfs.SpendNtfn{ - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendRequest: chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 1}, + PkScript: testScript, + }, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(ntfn); err != nil { + if _, _, err := n.RegisterSpend(ntfn); err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -500,7 +525,10 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) { // above. We'll include it in the next block, which should trigger a // spend notification. spendTx := wire.NewMsgTx(2) - spendTx.AddTxIn(&wire.TxIn{PreviousOutPoint: zeroOutPoint}) + spendTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: ntfn.OutPoint, + SignatureScript: testSigScript, + }) spendTxHash := spendTx.TxHash() block := btcutil.NewBlock(&wire.MsgBlock{ Transactions: []*wire.MsgTx{spendTx}, @@ -533,7 +561,10 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) { // spent, then we don't receive another spend notification. prevOut := wire.OutPoint{Hash: spendTxHash, Index: 0} spendOfSpend := wire.NewMsgTx(2) - spendOfSpend.AddTxIn(&wire.TxIn{PreviousOutPoint: prevOut}) + spendOfSpend.AddTxIn(&wire.TxIn{ + PreviousOutPoint: prevOut, + SignatureScript: testSigScript, + }) block = btcutil.NewBlock(&wire.MsgBlock{ Transactions: []*wire.MsgTx{spendOfSpend}, }) @@ -567,9 +598,12 @@ func TestTxNotifierHistoricalSpendDispatch(t *testing.T) { // We'll start by constructing the spending details of the outpoint // below. - spentOutpoint := zeroOutPoint + spentOutpoint := wire.OutPoint{Index: 1} spendTx := wire.NewMsgTx(2) - spendTx.AddTxIn(&wire.TxIn{PreviousOutPoint: zeroOutPoint}) + spendTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: spentOutpoint, + SignatureScript: testSigScript, + }) spendTxHash := spendTx.TxHash() expectedSpendDetails := &chainntnfs.SpendDetail{ @@ -583,10 +617,10 @@ func TestTxNotifierHistoricalSpendDispatch(t *testing.T) { // We'll register for a spend notification of the outpoint and ensure // that a notification isn't dispatched. ntfn := &chainntnfs.SpendNtfn{ - OutPoint: spentOutpoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendRequest: chainntnfs.SpendRequest{OutPoint: spentOutpoint}, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(ntfn); err != nil { + if _, _, err := n.RegisterSpend(ntfn); err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -600,7 +634,7 @@ func TestTxNotifierHistoricalSpendDispatch(t *testing.T) { // we'll hand off the spending details of the outpoint to the notifier // as it is not possible for it to view historical events in the chain. // By doing this, we replicate the functionality of the ChainNotifier. - err := n.UpdateSpendDetails(ntfn.OutPoint, expectedSpendDetails) + err := n.UpdateSpendDetails(ntfn.SpendRequest, expectedSpendDetails) if err != nil { t.Fatalf("unable to update spend details: %v", err) } @@ -618,7 +652,10 @@ func TestTxNotifierHistoricalSpendDispatch(t *testing.T) { // spent, then we don't receive another spend notification. prevOut := wire.OutPoint{Hash: spendTxHash, Index: 0} spendOfSpend := wire.NewMsgTx(2) - spendOfSpend.AddTxIn(&wire.TxIn{PreviousOutPoint: prevOut}) + spendOfSpend.AddTxIn(&wire.TxIn{ + PreviousOutPoint: prevOut, + SignatureScript: testSigScript, + }) block := btcutil.NewBlock(&wire.MsgBlock{ Transactions: []*wire.MsgTx{spendOfSpend}, }) @@ -654,10 +691,11 @@ func TestTxNotifierMultipleHistoricalConfRescans(t *testing.T) { // historical view of the chain. confNtfn1 := &chainntnfs.ConfNtfn{ ConfID: 0, - TxID: &zeroHash, - Event: chainntnfs.NewConfirmationEvent(1), + // TODO(wilmer): set pkScript. + ConfRequest: chainntnfs.ConfRequest{TxID: chainntnfs.ZeroHash}, + Event: chainntnfs.NewConfirmationEvent(1), } - historicalConfDispatch1, err := n.RegisterConf(confNtfn1) + historicalConfDispatch1, _, err := n.RegisterConf(confNtfn1) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -670,10 +708,11 @@ func TestTxNotifierMultipleHistoricalConfRescans(t *testing.T) { // since the first one is still pending. confNtfn2 := &chainntnfs.ConfNtfn{ ConfID: 1, - TxID: &zeroHash, - Event: chainntnfs.NewConfirmationEvent(1), + // TODO(wilmer): set pkScript. + ConfRequest: chainntnfs.ConfRequest{TxID: chainntnfs.ZeroHash}, + Event: chainntnfs.NewConfirmationEvent(1), } - historicalConfDispatch2, err := n.RegisterConf(confNtfn2) + historicalConfDispatch2, _, err := n.RegisterConf(confNtfn2) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -688,16 +727,17 @@ func TestTxNotifierMultipleHistoricalConfRescans(t *testing.T) { confDetails := &chainntnfs.TxConfirmation{ BlockHeight: startingHeight - 1, } - if err := n.UpdateConfDetails(*confNtfn2.TxID, confDetails); err != nil { + err = n.UpdateConfDetails(confNtfn2.ConfRequest, confDetails) + if err != nil { t.Fatalf("unable to update conf details: %v", err) } confNtfn3 := &chainntnfs.ConfNtfn{ - ConfID: 2, - TxID: &zeroHash, - Event: chainntnfs.NewConfirmationEvent(1), + ConfID: 2, + ConfRequest: chainntnfs.ConfRequest{TxID: chainntnfs.ZeroHash}, + Event: chainntnfs.NewConfirmationEvent(1), } - historicalConfDispatch3, err := n.RegisterConf(confNtfn3) + historicalConfDispatch3, _, err := n.RegisterConf(confNtfn3) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -721,12 +761,15 @@ func TestTxNotifierMultipleHistoricalSpendRescans(t *testing.T) { // The first registration for an outpoint in the notifier should request // a historical spend rescan as it does not have a historical view of // the chain. - ntfn1 := &chainntnfs.SpendNtfn{ - SpendID: 0, - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + spendRequest := chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 1}, } - historicalDispatch1, err := n.RegisterSpend(ntfn1) + ntfn1 := &chainntnfs.SpendNtfn{ + SpendID: 0, + SpendRequest: spendRequest, + Event: chainntnfs.NewSpendEvent(nil), + } + historicalDispatch1, _, err := n.RegisterSpend(ntfn1) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -738,11 +781,11 @@ func TestTxNotifierMultipleHistoricalSpendRescans(t *testing.T) { // should not request a historical spend rescan since the first one is // still pending. ntfn2 := &chainntnfs.SpendNtfn{ - SpendID: 1, - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 1, + SpendRequest: spendRequest, + Event: chainntnfs.NewSpendEvent(nil), } - historicalDispatch2, err := n.RegisterSpend(ntfn2) + historicalDispatch2, _, err := n.RegisterSpend(ntfn2) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -756,22 +799,22 @@ func TestTxNotifierMultipleHistoricalSpendRescans(t *testing.T) { // cached. spendDetails := &chainntnfs.SpendDetail{ SpentOutPoint: &ntfn2.OutPoint, - SpenderTxHash: &zeroHash, + SpenderTxHash: &chainntnfs.ZeroHash, SpendingTx: wire.NewMsgTx(2), SpenderInputIndex: 0, SpendingHeight: startingHeight - 1, } - err = n.UpdateSpendDetails(ntfn2.OutPoint, spendDetails) + err = n.UpdateSpendDetails(ntfn2.SpendRequest, spendDetails) if err != nil { t.Fatalf("unable to update spend details: %v", err) } ntfn3 := &chainntnfs.SpendNtfn{ - SpendID: 2, - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 2, + SpendRequest: spendRequest, + Event: chainntnfs.NewSpendEvent(nil), } - historicalDispatch3, err := n.RegisterSpend(ntfn3) + historicalDispatch3, _, err := n.RegisterSpend(ntfn3) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -799,16 +842,23 @@ func TestTxNotifierMultipleHistoricalNtfns(t *testing.T) { hintCache, ) + var txid chainhash.Hash + copy(txid[:], bytes.Repeat([]byte{0x01}, 32)) + confRequest := chainntnfs.ConfRequest{ + // TODO(wilmer): set pkScript. + TxID: txid, + } + // We'll start off by registered 5 clients for a confirmation // notification on the same transaction. confNtfns := make([]*chainntnfs.ConfNtfn, numNtfns) for i := uint64(0); i < numNtfns; i++ { confNtfns[i] = &chainntnfs.ConfNtfn{ - ConfID: i, - TxID: &zeroHash, - Event: chainntnfs.NewConfirmationEvent(1), + ConfID: i, + ConfRequest: confRequest, + Event: chainntnfs.NewConfirmationEvent(1), } - if _, err := n.RegisterConf(confNtfns[i]); err != nil { + if _, _, err := n.RegisterConf(confNtfns[i]); err != nil { t.Fatalf("unable to register conf ntfn #%d: %v", i, err) } } @@ -829,7 +879,7 @@ func TestTxNotifierMultipleHistoricalNtfns(t *testing.T) { expectedConfDetails := &chainntnfs.TxConfirmation{ BlockHeight: startingHeight - 1, } - err := n.UpdateConfDetails(*confNtfns[0].TxID, expectedConfDetails) + err := n.UpdateConfDetails(confNtfns[0].ConfRequest, expectedConfDetails) if err != nil { t.Fatalf("unable to update conf details: %v", err) } @@ -851,11 +901,11 @@ func TestTxNotifierMultipleHistoricalNtfns(t *testing.T) { // see a historical rescan request and the confirmation notification // should come through immediately. extraConfNtfn := &chainntnfs.ConfNtfn{ - ConfID: numNtfns + 1, - TxID: &zeroHash, - Event: chainntnfs.NewConfirmationEvent(1), + ConfID: numNtfns + 1, + ConfRequest: confRequest, + Event: chainntnfs.NewConfirmationEvent(1), } - historicalConfRescan, err := n.RegisterConf(extraConfNtfn) + historicalConfRescan, _, err := n.RegisterConf(extraConfNtfn) if err != nil { t.Fatalf("unable to register conf ntfn: %v", err) } @@ -871,14 +921,17 @@ func TestTxNotifierMultipleHistoricalNtfns(t *testing.T) { } // Similarly, we'll do the same thing but for spend notifications. + spendRequest := chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 1}, + } spendNtfns := make([]*chainntnfs.SpendNtfn, numNtfns) for i := uint64(0); i < numNtfns; i++ { spendNtfns[i] = &chainntnfs.SpendNtfn{ - SpendID: i, - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: i, + SpendRequest: spendRequest, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(spendNtfns[i]); err != nil { + if _, _, err := n.RegisterSpend(spendNtfns[i]); err != nil { t.Fatalf("unable to register spend ntfn #%d: %v", i, err) } } @@ -898,12 +951,12 @@ func TestTxNotifierMultipleHistoricalNtfns(t *testing.T) { // stop watching at tip. expectedSpendDetails := &chainntnfs.SpendDetail{ SpentOutPoint: &spendNtfns[0].OutPoint, - SpenderTxHash: &zeroHash, + SpenderTxHash: &chainntnfs.ZeroHash, SpendingTx: wire.NewMsgTx(2), SpenderInputIndex: 0, SpendingHeight: startingHeight - 1, } - err = n.UpdateSpendDetails(spendNtfns[0].OutPoint, expectedSpendDetails) + err = n.UpdateSpendDetails(spendNtfns[0].SpendRequest, expectedSpendDetails) if err != nil { t.Fatalf("unable to update spend details: %v", err) } @@ -925,11 +978,11 @@ func TestTxNotifierMultipleHistoricalNtfns(t *testing.T) { // should not see a historical rescan request and the spend notification // should come through immediately. extraSpendNtfn := &chainntnfs.SpendNtfn{ - SpendID: numNtfns + 1, - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: numNtfns + 1, + SpendRequest: spendRequest, + Event: chainntnfs.NewSpendEvent(nil), } - historicalSpendRescan, err := n.RegisterSpend(extraSpendNtfn) + historicalSpendRescan, _, err := n.RegisterSpend(extraSpendNtfn) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -960,27 +1013,35 @@ func TestTxNotifierCancelSpend(t *testing.T) { // We'll register two notification requests. Only the second one will be // canceled. ntfn1 := &chainntnfs.SpendNtfn{ - SpendID: 0, - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 0, + SpendRequest: chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 1}, + PkScript: testScript, + }, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(ntfn1); err != nil { + if _, _, err := n.RegisterSpend(ntfn1); err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } ntfn2 := &chainntnfs.SpendNtfn{ - SpendID: 1, - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 1, + SpendRequest: chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 2}, + }, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(ntfn2); err != nil { + if _, _, err := n.RegisterSpend(ntfn2); err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } // Construct the spending details of the outpoint and create a dummy // block containing it. spendTx := wire.NewMsgTx(2) - spendTx.AddTxIn(&wire.TxIn{PreviousOutPoint: ntfn1.OutPoint}) + spendTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: ntfn1.OutPoint, + SignatureScript: testSigScript, + }) spendTxHash := spendTx.TxHash() expectedSpendDetails := &chainntnfs.SpendDetail{ SpentOutPoint: &ntfn1.OutPoint, @@ -996,7 +1057,7 @@ func TestTxNotifierCancelSpend(t *testing.T) { // Before extending the notifier's tip with the dummy block above, we'll // cancel the second request. - n.CancelSpend(ntfn2.OutPoint, ntfn2.SpendID) + n.CancelSpend(ntfn2.SpendRequest, ntfn2.SpendID) err := n.ConnectTip(block.Hash(), startingHeight+1, block.Transactions()) if err != nil { @@ -1040,59 +1101,68 @@ func TestTxNotifierConfReorg(t *testing.T) { tx3NumConfs uint32 = 2 ) - var ( - tx1 = wire.MsgTx{Version: 1} - tx2 = wire.MsgTx{Version: 2} - tx3 = wire.MsgTx{Version: 3} - ) - hintCache := newMockHintCache() n := chainntnfs.NewTxNotifier( 7, chainntnfs.ReorgSafetyLimit, hintCache, hintCache, ) // Tx 1 will be confirmed in block 9 and requires 2 confs. - tx1Hash := tx1.TxHash() + tx1 := wire.MsgTx{Version: 1} + tx1.AddTxOut(&wire.TxOut{PkScript: testRawScript}) ntfn1 := chainntnfs.ConfNtfn{ - TxID: &tx1Hash, + ConfID: 1, + ConfRequest: chainntnfs.ConfRequest{ + TxID: tx1.TxHash(), + PkScript: testScript, + }, NumConfirmations: tx1NumConfs, Event: chainntnfs.NewConfirmationEvent(tx1NumConfs), } - if _, err := n.RegisterConf(&ntfn1); err != nil { + if _, _, err := n.RegisterConf(&ntfn1); err != nil { t.Fatalf("unable to register ntfn: %v", err) } - if err := n.UpdateConfDetails(*ntfn1.TxID, nil); err != nil { + if err := n.UpdateConfDetails(ntfn1.ConfRequest, nil); err != nil { t.Fatalf("unable to deliver conf details: %v", err) } // Tx 2 will be confirmed in block 10 and requires 1 conf. - tx2Hash := tx2.TxHash() + tx2 := wire.MsgTx{Version: 2} + tx2.AddTxOut(&wire.TxOut{PkScript: testRawScript}) ntfn2 := chainntnfs.ConfNtfn{ - TxID: &tx2Hash, + ConfID: 2, + ConfRequest: chainntnfs.ConfRequest{ + TxID: tx2.TxHash(), + PkScript: testScript, + }, NumConfirmations: tx2NumConfs, Event: chainntnfs.NewConfirmationEvent(tx2NumConfs), } - if _, err := n.RegisterConf(&ntfn2); err != nil { + if _, _, err := n.RegisterConf(&ntfn2); err != nil { t.Fatalf("unable to register ntfn: %v", err) } - if err := n.UpdateConfDetails(*ntfn2.TxID, nil); err != nil { + if err := n.UpdateConfDetails(ntfn2.ConfRequest, nil); err != nil { t.Fatalf("unable to deliver conf details: %v", err) } // Tx 3 will be confirmed in block 10 and requires 2 confs. - tx3Hash := tx3.TxHash() + tx3 := wire.MsgTx{Version: 3} + tx3.AddTxOut(&wire.TxOut{PkScript: testRawScript}) ntfn3 := chainntnfs.ConfNtfn{ - TxID: &tx3Hash, + ConfID: 3, + ConfRequest: chainntnfs.ConfRequest{ + TxID: tx3.TxHash(), + PkScript: testScript, + }, NumConfirmations: tx3NumConfs, Event: chainntnfs.NewConfirmationEvent(tx3NumConfs), } - if _, err := n.RegisterConf(&ntfn3); err != nil { + if _, _, err := n.RegisterConf(&ntfn3); err != nil { t.Fatalf("unable to register ntfn: %v", err) } - if err := n.UpdateConfDetails(*ntfn3.TxID, nil); err != nil { + if err := n.UpdateConfDetails(ntfn3.ConfRequest, nil); err != nil { t.Fatalf("unable to deliver conf details: %v", err) } @@ -1327,31 +1397,44 @@ func TestTxNotifierSpendReorg(t *testing.T) { // We'll have two outpoints that will be spent throughout the test. The // first will be spent and will not experience a reorg, while the second // one will. - op1 := zeroOutPoint - op1.Index = 1 + spendRequest1 := chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 1}, + PkScript: testScript, + } spendTx1 := wire.NewMsgTx(2) - spendTx1.AddTxIn(&wire.TxIn{PreviousOutPoint: op1}) + spendTx1.AddTxIn(&wire.TxIn{ + PreviousOutPoint: spendRequest1.OutPoint, + SignatureScript: testSigScript, + }) spendTxHash1 := spendTx1.TxHash() expectedSpendDetails1 := &chainntnfs.SpendDetail{ - SpentOutPoint: &op1, + SpentOutPoint: &spendRequest1.OutPoint, SpenderTxHash: &spendTxHash1, SpendingTx: spendTx1, SpenderInputIndex: 0, SpendingHeight: startingHeight + 1, } - op2 := zeroOutPoint - op2.Index = 2 + spendRequest2 := chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 2}, + PkScript: testScript, + } spendTx2 := wire.NewMsgTx(2) - spendTx2.AddTxIn(&wire.TxIn{PreviousOutPoint: zeroOutPoint}) - spendTx2.AddTxIn(&wire.TxIn{PreviousOutPoint: op2}) + spendTx2.AddTxIn(&wire.TxIn{ + PreviousOutPoint: chainntnfs.ZeroOutPoint, + SignatureScript: testSigScript, + }) + spendTx2.AddTxIn(&wire.TxIn{ + PreviousOutPoint: spendRequest2.OutPoint, + SignatureScript: testSigScript, + }) spendTxHash2 := spendTx2.TxHash() // The second outpoint will experience a reorg and get re-spent at a // different height, so we'll need to construct the spend details for // before and after the reorg. expectedSpendDetails2BeforeReorg := chainntnfs.SpendDetail{ - SpentOutPoint: &op2, + SpentOutPoint: &spendRequest2.OutPoint, SpenderTxHash: &spendTxHash2, SpendingTx: spendTx2, SpenderInputIndex: 1, @@ -1365,20 +1448,20 @@ func TestTxNotifierSpendReorg(t *testing.T) { // We'll register for a spend notification for each outpoint above. ntfn1 := &chainntnfs.SpendNtfn{ - SpendID: 78, - OutPoint: op1, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 78, + SpendRequest: spendRequest1, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(ntfn1); err != nil { + if _, _, err := n.RegisterSpend(ntfn1); err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } ntfn2 := &chainntnfs.SpendNtfn{ - SpendID: 21, - OutPoint: op2, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 21, + SpendRequest: spendRequest2, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(ntfn2); err != nil { + if _, _, err := n.RegisterSpend(ntfn2); err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -1549,38 +1632,46 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { // Create two test transactions and register them for notifications. tx1 := wire.MsgTx{Version: 1} - tx1Hash := tx1.TxHash() + tx1.AddTxOut(&wire.TxOut{PkScript: testRawScript}) ntfn1 := &chainntnfs.ConfNtfn{ - TxID: &tx1Hash, + ConfID: 1, + ConfRequest: chainntnfs.ConfRequest{ + TxID: tx1.TxHash(), + PkScript: testScript, + }, NumConfirmations: 1, Event: chainntnfs.NewConfirmationEvent(1), } tx2 := wire.MsgTx{Version: 2} - tx2Hash := tx2.TxHash() + tx2.AddTxOut(&wire.TxOut{PkScript: testRawScript}) ntfn2 := &chainntnfs.ConfNtfn{ - TxID: &tx2Hash, + ConfID: 2, + ConfRequest: chainntnfs.ConfRequest{ + TxID: tx2.TxHash(), + PkScript: testScript, + }, NumConfirmations: 2, Event: chainntnfs.NewConfirmationEvent(2), } - if _, err := n.RegisterConf(ntfn1); err != nil { + if _, _, err := n.RegisterConf(ntfn1); err != nil { t.Fatalf("unable to register tx1: %v", err) } - if _, err := n.RegisterConf(ntfn2); err != nil { + if _, _, err := n.RegisterConf(ntfn2); err != nil { t.Fatalf("unable to register tx2: %v", err) } // Both transactions should not have a height hint set, as RegisterConf // should not alter the cache state. - _, err := hintCache.QueryConfirmHint(tx1Hash) + _, err := hintCache.QueryConfirmHint(ntfn1.ConfRequest) if err != chainntnfs.ErrConfirmHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "want: %v, got %v", chainntnfs.ErrConfirmHintNotFound, err) } - _, err = hintCache.QueryConfirmHint(tx2Hash) + _, err = hintCache.QueryConfirmHint(ntfn2.ConfRequest) if err != chainntnfs.ErrConfirmHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "want: %v, got %v", @@ -1606,14 +1697,14 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { // the height hints should remain unchanged. This simulates blocks // confirming while the historical dispatch is processing the // registration. - hint, err := hintCache.QueryConfirmHint(tx1Hash) + hint, err := hintCache.QueryConfirmHint(ntfn1.ConfRequest) if err != chainntnfs.ErrConfirmHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "want: %v, got %v", chainntnfs.ErrConfirmHintNotFound, err) } - hint, err = hintCache.QueryConfirmHint(tx2Hash) + hint, err = hintCache.QueryConfirmHint(ntfn2.ConfRequest) if err != chainntnfs.ErrConfirmHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "want: %v, got %v", @@ -1622,10 +1713,10 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { // Now, update the conf details reporting that the neither txn was found // in the historical dispatch. - if err := n.UpdateConfDetails(tx1Hash, nil); err != nil { + if err := n.UpdateConfDetails(ntfn1.ConfRequest, nil); err != nil { t.Fatalf("unable to update conf details: %v", err) } - if err := n.UpdateConfDetails(tx2Hash, nil); err != nil { + if err := n.UpdateConfDetails(ntfn2.ConfRequest, nil); err != nil { t.Fatalf("unable to update conf details: %v", err) } @@ -1646,7 +1737,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { // Now that both notifications are waiting at tip for confirmations, // they should have their height hints updated to the latest block // height. - hint, err = hintCache.QueryConfirmHint(tx1Hash) + hint, err = hintCache.QueryConfirmHint(ntfn1.ConfRequest) if err != nil { t.Fatalf("unable to query for hint: %v", err) } @@ -1655,7 +1746,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { tx1Height, hint) } - hint, err = hintCache.QueryConfirmHint(tx2Hash) + hint, err = hintCache.QueryConfirmHint(ntfn2.ConfRequest) if err != nil { t.Fatalf("unable to query for hint: %v", err) } @@ -1679,7 +1770,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { } // The height hint for the first transaction should remain the same. - hint, err = hintCache.QueryConfirmHint(tx1Hash) + hint, err = hintCache.QueryConfirmHint(ntfn1.ConfRequest) if err != nil { t.Fatalf("unable to query for hint: %v", err) } @@ -1690,7 +1781,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { // The height hint for the second transaction should now be updated to // reflect its confirmation. - hint, err = hintCache.QueryConfirmHint(tx2Hash) + hint, err = hintCache.QueryConfirmHint(ntfn2.ConfRequest) if err != nil { t.Fatalf("unable to query for hint: %v", err) } @@ -1707,7 +1798,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { // This should update the second transaction's height hint within the // cache to the previous height. - hint, err = hintCache.QueryConfirmHint(tx2Hash) + hint, err = hintCache.QueryConfirmHint(ntfn2.ConfRequest) if err != nil { t.Fatalf("unable to query for hint: %v", err) } @@ -1718,7 +1809,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) { // The first transaction's height hint should remain at the original // confirmation height. - hint, err = hintCache.QueryConfirmHint(tx2Hash) + hint, err = hintCache.QueryConfirmHint(ntfn2.ConfRequest) if err != nil { t.Fatalf("unable to query for hint: %v", err) } @@ -1751,34 +1842,40 @@ func TestTxNotifierSpendHintCache(t *testing.T) { ) // Create two test outpoints and register them for spend notifications. - op1 := wire.OutPoint{Hash: zeroHash, Index: 1} ntfn1 := &chainntnfs.SpendNtfn{ - OutPoint: op1, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 1, + SpendRequest: chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 1}, + PkScript: testScript, + }, + Event: chainntnfs.NewSpendEvent(nil), } - op2 := wire.OutPoint{Hash: zeroHash, Index: 2} ntfn2 := &chainntnfs.SpendNtfn{ - OutPoint: op2, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 2, + SpendRequest: chainntnfs.SpendRequest{ + OutPoint: wire.OutPoint{Index: 2}, + PkScript: testScript, + }, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(ntfn1); err != nil { + if _, _, err := n.RegisterSpend(ntfn1); err != nil { t.Fatalf("unable to register spend for op1: %v", err) } - if _, err := n.RegisterSpend(ntfn2); err != nil { + if _, _, err := n.RegisterSpend(ntfn2); err != nil { t.Fatalf("unable to register spend for op2: %v", err) } // Both outpoints should not have a spend hint set upon registration, as // we must first determine whether they have already been spent in the // chain. - _, err := hintCache.QuerySpendHint(op1) + _, err := hintCache.QuerySpendHint(ntfn1.SpendRequest) if err != chainntnfs.ErrSpendHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "expected: %v, got %v", chainntnfs.ErrSpendHintNotFound, err) } - _, err = hintCache.QuerySpendHint(op2) + _, err = hintCache.QuerySpendHint(ntfn2.SpendRequest) if err != chainntnfs.ErrSpendHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "expected: %v, got %v", chainntnfs.ErrSpendHintNotFound, @@ -1800,13 +1897,13 @@ func TestTxNotifierSpendHintCache(t *testing.T) { // Since we haven't called UpdateSpendDetails on any of the test // outpoints, this implies that there is a still a pending historical // rescan for them, so their spend hints should not be created/updated. - _, err = hintCache.QuerySpendHint(op1) + _, err = hintCache.QuerySpendHint(ntfn1.SpendRequest) if err != chainntnfs.ErrSpendHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "expected: %v, got %v", chainntnfs.ErrSpendHintNotFound, err) } - _, err = hintCache.QuerySpendHint(op2) + _, err = hintCache.QuerySpendHint(ntfn2.SpendRequest) if err != chainntnfs.ErrSpendHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "expected: %v, got %v", chainntnfs.ErrSpendHintNotFound, @@ -1816,17 +1913,20 @@ func TestTxNotifierSpendHintCache(t *testing.T) { // Now, we'll simulate that their historical rescans have finished by // calling UpdateSpendDetails. This should allow their spend hints to be // updated upon every block connected/disconnected. - if err := n.UpdateSpendDetails(ntfn1.OutPoint, nil); err != nil { + if err := n.UpdateSpendDetails(ntfn1.SpendRequest, nil); err != nil { t.Fatalf("unable to update spend details: %v", err) } - if err := n.UpdateSpendDetails(ntfn2.OutPoint, nil); err != nil { + if err := n.UpdateSpendDetails(ntfn2.SpendRequest, nil); err != nil { t.Fatalf("unable to update spend details: %v", err) } // We'll create a new block that only contains the spending transaction // of the first outpoint. spendTx1 := wire.NewMsgTx(2) - spendTx1.AddTxIn(&wire.TxIn{PreviousOutPoint: ntfn1.OutPoint}) + spendTx1.AddTxIn(&wire.TxIn{ + PreviousOutPoint: ntfn1.OutPoint, + SignatureScript: testSigScript, + }) block1 := btcutil.NewBlock(&wire.MsgBlock{ Transactions: []*wire.MsgTx{spendTx1}, }) @@ -1841,14 +1941,14 @@ func TestTxNotifierSpendHintCache(t *testing.T) { // Both outpoints should have their spend hints reflect the height of // the new block being connected due to the first outpoint being spent // at this height, and the second outpoint still being unspent. - op1Hint, err := hintCache.QuerySpendHint(ntfn1.OutPoint) + op1Hint, err := hintCache.QuerySpendHint(ntfn1.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op1: %v", err) } if op1Hint != op1Height { t.Fatalf("expected hint %d, got %d", op1Height, op1Hint) } - op2Hint, err := hintCache.QuerySpendHint(ntfn2.OutPoint) + op2Hint, err := hintCache.QuerySpendHint(ntfn2.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op2: %v", err) } @@ -1858,7 +1958,10 @@ func TestTxNotifierSpendHintCache(t *testing.T) { // Then, we'll create another block that spends the second outpoint. spendTx2 := wire.NewMsgTx(2) - spendTx2.AddTxIn(&wire.TxIn{PreviousOutPoint: ntfn2.OutPoint}) + spendTx2.AddTxIn(&wire.TxIn{ + PreviousOutPoint: ntfn2.OutPoint, + SignatureScript: testSigScript, + }) block2 := btcutil.NewBlock(&wire.MsgBlock{ Transactions: []*wire.MsgTx{spendTx2}, }) @@ -1873,14 +1976,14 @@ func TestTxNotifierSpendHintCache(t *testing.T) { // Only the second outpoint should have its spend hint updated due to // being spent within the new block. The first outpoint's spend hint // should remain the same as it's already been spent before. - op1Hint, err = hintCache.QuerySpendHint(ntfn1.OutPoint) + op1Hint, err = hintCache.QuerySpendHint(ntfn1.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op1: %v", err) } if op1Hint != op1Height { t.Fatalf("expected hint %d, got %d", op1Height, op1Hint) } - op2Hint, err = hintCache.QuerySpendHint(ntfn2.OutPoint) + op2Hint, err = hintCache.QuerySpendHint(ntfn2.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op2: %v", err) } @@ -1898,14 +2001,14 @@ func TestTxNotifierSpendHintCache(t *testing.T) { // to the previous height, as that's where its spending transaction was // included in within the chain. The first outpoint's spend hint should // remain the same. - op1Hint, err = hintCache.QuerySpendHint(ntfn1.OutPoint) + op1Hint, err = hintCache.QuerySpendHint(ntfn1.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op1: %v", err) } if op1Hint != op1Height { t.Fatalf("expected hint %d, got %d", op1Height, op1Hint) } - op2Hint, err = hintCache.QuerySpendHint(ntfn2.OutPoint) + op2Hint, err = hintCache.QuerySpendHint(ntfn2.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op2: %v", err) } @@ -1927,19 +2030,21 @@ func TestTxNotifierTearDown(t *testing.T) { // To begin the test, we'll register for a confirmation and spend // notification. confNtfn := &chainntnfs.ConfNtfn{ - TxID: &zeroHash, + ConfID: 1, + ConfRequest: chainntnfs.ConfRequest{TxID: chainntnfs.ZeroHash}, NumConfirmations: 1, Event: chainntnfs.NewConfirmationEvent(1), } - if _, err := n.RegisterConf(confNtfn); err != nil { + if _, _, err := n.RegisterConf(confNtfn); err != nil { t.Fatalf("unable to register conf ntfn: %v", err) } spendNtfn := &chainntnfs.SpendNtfn{ - OutPoint: zeroOutPoint, - Event: chainntnfs.NewSpendEvent(nil), + SpendID: 1, + SpendRequest: chainntnfs.SpendRequest{OutPoint: chainntnfs.ZeroOutPoint}, + Event: chainntnfs.NewSpendEvent(nil), } - if _, err := n.RegisterSpend(spendNtfn); err != nil { + if _, _, err := n.RegisterSpend(spendNtfn); err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -1976,10 +2081,10 @@ func TestTxNotifierTearDown(t *testing.T) { // Now that the notifier is torn down, we should no longer be able to // register notification requests. - if _, err := n.RegisterConf(confNtfn); err == nil { + if _, _, err := n.RegisterConf(confNtfn); err == nil { t.Fatal("expected confirmation registration to fail") } - if _, err := n.RegisterSpend(spendNtfn); err == nil { + if _, _, err := n.RegisterSpend(spendNtfn); err == nil { t.Fatal("expected spend registration to fail") } }