From 7661d00d5ad47f5317436957381b826cf8b6fca1 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Aug 2018 19:15:37 -0700 Subject: [PATCH] chainntnfs/txconfnotifier_test: update height hint cache test --- chainntnfs/txconfnotifier_test.go | 129 ++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 35 deletions(-) diff --git a/chainntnfs/txconfnotifier_test.go b/chainntnfs/txconfnotifier_test.go index 823891309..afb6474a4 100644 --- a/chainntnfs/txconfnotifier_test.go +++ b/chainntnfs/txconfnotifier_test.go @@ -128,6 +128,7 @@ func TestTxConfFutureDispatch(t *testing.T) { t.Fatalf("unable to register ntfn: %v", err) } + err := tcn.UpdateConfDetails(*ntfn1.TxID, 0, nil) tx2Hash := tx2.TxHash() ntfn2 := chainntnfs.ConfNtfn{ TxID: &tx2Hash, @@ -675,14 +676,18 @@ func TestTxConfChainReorg(t *testing.T) { } // TestTxConfHeightHintCache ensures that the height hints for transactions are -// kept track of correctly with each new block connected/disconnected. +// kept track of correctly with each new block connected/disconnected. This test +// also asserts that the height hints are not updated until the simulated +// historical dispatches have returned, and we know the transactions aren't +// already in the chain. func TestTxConfHeightHintCache(t *testing.T) { t.Parallel() const ( - startingHeight = 10 - tx1Height = 11 - tx2Height = 12 + startingHeight = 200 + txDummyHeight = 201 + tx1Height = 202 + tx2Height = 203 ) // Initialize our TxConfNotifier instance backed by a height hint cache. @@ -715,65 +720,105 @@ func TestTxConfHeightHintCache(t *testing.T) { t.Fatalf("unable to register tx2: %v", err) } - // Both transactions should have a height hint of the starting height - // due to registering notifications for them. - hint, err := hintCache.QueryConfirmHint(tx1Hash) - if err != nil { - t.Fatalf("unable to query for hint: %v", err) - } - if hint != startingHeight { - t.Fatalf("expected hint %d, got %d", startingHeight, hint) + // Both transactions should not have a height hint set, as Register + // should not alter the cache state. + _, err := hintCache.QueryConfirmHint(tx1Hash) + 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) - if err != nil { - t.Fatalf("unable to query for hint: %v", err) - } - if hint != startingHeight { - t.Fatalf("expected hint %d, got %d", startingHeight, hint) + _, err = hintCache.QueryConfirmHint(tx2Hash) + if err != chainntnfs.ErrConfirmHintNotFound { + t.Fatalf("unexpected error when querying for height hint "+ + "want: %v, got %v", + chainntnfs.ErrConfirmHintNotFound, err) } - // Create a new block that will include the first transaction and extend + // Create a new block that will include the dummy transaction and extend // the chain. + txDummy := wire.MsgTx{Version: 3} block1 := btcutil.NewBlock(&wire.MsgBlock{ - Transactions: []*wire.MsgTx{&tx1}, + Transactions: []*wire.MsgTx{&txDummy}, }) err = tcn.ConnectTip( - block1.Hash(), tx1Height, block1.Transactions(), + block1.Hash(), txDummyHeight, block1.Transactions(), ) if err != nil { t.Fatalf("Failed to connect block: %v", err) } - // The height hint for the first transaction should now be updated to - // reflect its confirmation. + // Since UpdateConfDetails has not been called for either transaction, + // the height hints should remain unchanged. This simulates blocks + // confirming while the historical dispatch is processing the + // registration. + hint, err := hintCache.QueryConfirmHint(tx1Hash) + 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) + if err != chainntnfs.ErrConfirmHintNotFound { + t.Fatalf("unexpected error when querying for height hint "+ + "want: %v, got %v", + chainntnfs.ErrConfirmHintNotFound, err) + } + + // Now, update the conf details reporting that the neither txn was found + // in the historical dispatch. + if err := tcn.UpdateConfDetails(tx1Hash, 0, nil); err != nil { + t.Fatalf("unable to update conf details: %v", err) + } + if err := tcn.UpdateConfDetails(tx2Hash, 0, nil); err != nil { + t.Fatalf("unable to update conf details: %v", err) + } + + // We'll create another block that will include the first transaction + // and extend the chain. + block2 := btcutil.NewBlock(&wire.MsgBlock{ + Transactions: []*wire.MsgTx{&tx1}, + }) + + err = tcn.ConnectTip( + block2.Hash(), tx1Height, block2.Transactions(), + ) + if err != nil { + t.Fatalf("Failed to connect block: %v", err) + } + + // 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) if err != nil { t.Fatalf("unable to query for hint: %v", err) } if hint != tx1Height { - t.Fatalf("expected hint %d, got %d", tx1Height, hint) + t.Fatalf("expected hint %d, got %d", + tx1Height, hint) } - // The height hint for the second transaction should also be updated due - // to it still being unconfirmed. hint, err = hintCache.QueryConfirmHint(tx2Hash) if err != nil { t.Fatalf("unable to query for hint: %v", err) } if hint != tx1Height { - t.Fatalf("expected hint %d, got %d", tx1Height, hint) + t.Fatalf("expected hint %d, got %d", + tx2Height, hint) } - // Now, we'll create another block that will include the second + // Next, we'll create another block that will include the second // transaction and extend the chain. - block2 := btcutil.NewBlock(&wire.MsgBlock{ + block3 := btcutil.NewBlock(&wire.MsgBlock{ Transactions: []*wire.MsgTx{&tx2}, }) err = tcn.ConnectTip( - block2.Hash(), tx2Height, block2.Transactions(), + block3.Hash(), tx2Height, block3.Transactions(), ) if err != nil { t.Fatalf("Failed to connect block: %v", err) @@ -785,7 +830,8 @@ func TestTxConfHeightHintCache(t *testing.T) { t.Fatalf("unable to query for hint: %v", err) } if hint != tx1Height { - t.Fatalf("expected hint %d, got %d", tx1Height, hint) + t.Fatalf("expected hint %d, got %d", + tx1Height, hint) } // The height hint for the second transaction should now be updated to @@ -795,11 +841,12 @@ func TestTxConfHeightHintCache(t *testing.T) { t.Fatalf("unable to query for hint: %v", err) } if hint != tx2Height { - t.Fatalf("expected hint %d, got %d", tx2Height, hint) + t.Fatalf("expected hint %d, got %d", + tx2Height, hint) } - // Now, we'll attempt do disconnect the last block in order to simulate - // a chain reorg. + // Finally, we'll attempt do disconnect the last block in order to + // simulate a chain reorg. if err := tcn.DisconnectTip(tx2Height); err != nil { t.Fatalf("Failed to disconnect block: %v", err) } @@ -811,7 +858,19 @@ func TestTxConfHeightHintCache(t *testing.T) { t.Fatalf("unable to query for hint: %v", err) } if hint != tx1Height { - t.Fatalf("expected hint %d, got %d", tx1Height, hint) + t.Fatalf("expected hint %d, got %d", + tx1Height, hint) + } + + // The first transaction's height hint should remain at the original + // confirmation height. + hint, err = hintCache.QueryConfirmHint(tx2Hash) + if err != nil { + t.Fatalf("unable to query for hint: %v", err) + } + if hint != tx1Height { + t.Fatalf("expected hint %d, got %d", + tx1Height, hint) } }