github.com/decred/dcrlnd@v0.7.6/chainntnfs/test/test_interface.go (about)

     1  //go:build dev
     2  // +build dev
     3  
     4  package chainntnfstest
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"log"
    12  	"sync"
    13  	"testing"
    14  	"time"
    15  
    16  	"decred.org/dcrwallet/v4/wallet"
    17  	"github.com/decred/dcrd/chaincfg/chainhash"
    18  	"github.com/decred/dcrd/chaincfg/v3"
    19  	"github.com/decred/dcrd/dcrutil/v4"
    20  	rpctest "github.com/decred/dcrtest/dcrdtest"
    21  	"google.golang.org/grpc"
    22  	"matheusd.com/testctx"
    23  
    24  	"github.com/decred/dcrd/wire"
    25  	"github.com/decred/dcrlnd/chainntnfs"
    26  	"github.com/decred/dcrlnd/chainntnfs/dcrdnotify"
    27  	"github.com/decred/dcrlnd/chainntnfs/dcrwnotify"
    28  	"github.com/decred/dcrlnd/chainntnfs/remotedcrwnotify"
    29  	"github.com/decred/dcrlnd/channeldb"
    30  	"github.com/decred/dcrlnd/internal/testutils"
    31  )
    32  
    33  var ctxb = context.Background()
    34  var netParams = chaincfg.SimNetParams()
    35  
    36  func testSingleConfirmationNotification(miner *rpctest.Harness, vw *rpctest.VotingWallet,
    37  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
    38  
    39  	// We'd like to test the case of being notified once a txid reaches a
    40  	// *single* confirmation.
    41  	//
    42  	// So first, let's send some coins to "ourself", obtaining a txid.
    43  	// We're spending from a coinbase output here, so we use the dedicated
    44  	// function.
    45  	txid, pkScript, err := chainntnfs.GetTestTxidAndScript(miner)
    46  	if err != nil {
    47  		t.Fatalf("unable to create test tx: %v", err)
    48  	}
    49  	if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
    50  		t.Fatalf("tx not relayed to miner: %v", err)
    51  	}
    52  
    53  	_, currentHeight, err := miner.Node.GetBestBlock(ctxb)
    54  	if err != nil {
    55  		t.Fatalf("unable to get current height: %v", err)
    56  	}
    57  
    58  	// Now that we have a txid, register a confirmation notification with
    59  	// the chainntfn source.
    60  	numConfs := uint32(1)
    61  	var confIntent *chainntnfs.ConfirmationEvent
    62  	if scriptDispatch {
    63  		confIntent, err = notifier.RegisterConfirmationsNtfn(
    64  			nil, pkScript, numConfs, uint32(currentHeight),
    65  		)
    66  	} else {
    67  		confIntent, err = notifier.RegisterConfirmationsNtfn(
    68  			txid, pkScript, numConfs, uint32(currentHeight),
    69  		)
    70  	}
    71  	if err != nil {
    72  		t.Fatalf("unable to register ntfn: %v", err)
    73  	}
    74  
    75  	// Now generate a single block, the transaction should be included which
    76  	// should trigger a notification event.
    77  	blockHash, err := vw.GenerateBlocks(ctxb, 1)
    78  	if err != nil {
    79  		t.Fatalf("unable to generate single block: %v", err)
    80  	}
    81  
    82  	select {
    83  	case confInfo := <-confIntent.Confirmed:
    84  		if !confInfo.BlockHash.IsEqual(blockHash[0]) {
    85  			t.Fatalf("mismatched block hashes: expected %v, got %v",
    86  				blockHash[0], confInfo.BlockHash)
    87  		}
    88  
    89  		// Finally, we'll verify that the tx index returned is the exact same
    90  		// as the tx index of the transaction within the block itself.
    91  		msgBlock, err := miner.Node.GetBlock(ctxb, blockHash[0])
    92  		if err != nil {
    93  			t.Fatalf("unable to fetch block: %v", err)
    94  		}
    95  
    96  		block := dcrutil.NewBlock(msgBlock)
    97  		specifiedTxHash, err := block.TxHash(int(confInfo.TxIndex))
    98  		if err != nil {
    99  			t.Fatalf("unable to index into block: %v", err)
   100  		}
   101  
   102  		if !specifiedTxHash.IsEqual(txid) {
   103  			t.Fatalf("mismatched tx indexes: expected %v, got %v",
   104  				txid, specifiedTxHash)
   105  		}
   106  	case <-time.After(20 * time.Second):
   107  		t.Fatalf("confirmation notification never received")
   108  	}
   109  }
   110  
   111  func testMultiConfirmationNotification(miner *rpctest.Harness, vw *rpctest.VotingWallet,
   112  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
   113  
   114  	// We'd like to test the case of being notified once a txid reaches N
   115  	// confirmations, where N > 1.
   116  	//
   117  	// Again, we'll begin by creating a fresh transaction, so we can obtain
   118  	// a fresh txid.
   119  	txid, pkScript, err := chainntnfs.GetTestTxidAndScript(miner)
   120  	if err != nil {
   121  		t.Fatalf("unable to create test addr: %v", err)
   122  	}
   123  	if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
   124  		t.Fatalf("tx not relayed to miner: %v", err)
   125  	}
   126  
   127  	_, currentHeight, err := miner.Node.GetBestBlock(ctxb)
   128  	if err != nil {
   129  		t.Fatalf("unable to get current height: %v", err)
   130  	}
   131  
   132  	numConfs := uint32(6)
   133  	var confIntent *chainntnfs.ConfirmationEvent
   134  	if scriptDispatch {
   135  		confIntent, err = notifier.RegisterConfirmationsNtfn(
   136  			nil, pkScript, numConfs, uint32(currentHeight),
   137  		)
   138  	} else {
   139  		confIntent, err = notifier.RegisterConfirmationsNtfn(
   140  			txid, pkScript, numConfs, uint32(currentHeight),
   141  		)
   142  	}
   143  	if err != nil {
   144  		t.Fatalf("unable to register ntfn: %v", err)
   145  	}
   146  
   147  	// Now generate a six blocks. The transaction should be included in the
   148  	// first block, which will be built upon by the other 5 blocks.
   149  	if _, err := vw.GenerateBlocks(ctxb, 6); err != nil {
   150  		t.Fatalf("unable to generate single block: %v", err)
   151  	}
   152  
   153  	// TODO(roasbeef): reduce all timeouts after neutrino sync tightended
   154  	// up
   155  
   156  	select {
   157  	case <-confIntent.Confirmed:
   158  		break
   159  	case <-time.After(20 * time.Second):
   160  		t.Fatalf("confirmation notification never received")
   161  	}
   162  }
   163  
   164  func testBatchConfirmationNotification(miner *rpctest.Harness, vw *rpctest.VotingWallet,
   165  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
   166  
   167  	// We'd like to test a case of serving notifications to multiple
   168  	// clients, each requesting to be notified once a txid receives various
   169  	// numbers of confirmations.
   170  	confSpread := [6]uint32{1, 2, 3, 6, 20, 22}
   171  	confIntents := make([]*chainntnfs.ConfirmationEvent, len(confSpread))
   172  
   173  	_, currentHeight, err := miner.Node.GetBestBlock(ctxb)
   174  	if err != nil {
   175  		t.Fatalf("unable to get current height: %v", err)
   176  	}
   177  
   178  	// Create a new txid spending miner coins for each confirmation entry
   179  	// in confSpread, we collect each conf intent into a slice so we can
   180  	// verify they're each notified at the proper number of confirmations
   181  	// below.
   182  	for i, numConfs := range confSpread {
   183  		txid, pkScript, err := chainntnfs.GetTestTxidAndScript(miner)
   184  		if err != nil {
   185  			t.Fatalf("unable to create test addr: %v", err)
   186  		}
   187  		var confIntent *chainntnfs.ConfirmationEvent
   188  		if scriptDispatch {
   189  			confIntent, err = notifier.RegisterConfirmationsNtfn(
   190  				nil, pkScript, numConfs, uint32(currentHeight),
   191  			)
   192  		} else {
   193  			confIntent, err = notifier.RegisterConfirmationsNtfn(
   194  				txid, pkScript, numConfs, uint32(currentHeight),
   195  			)
   196  		}
   197  		if err != nil {
   198  			t.Fatalf("unable to register ntfn: %v", err)
   199  		}
   200  		confIntents[i] = confIntent
   201  		if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
   202  			t.Fatalf("tx not relayed to miner: %v", err)
   203  		}
   204  
   205  	}
   206  
   207  	initialConfHeight := uint32(currentHeight + 1)
   208  
   209  	// Now, for each confirmation intent, generate the delta number of blocks
   210  	// needed to trigger the confirmation notification. A goroutine is
   211  	// spawned in order to verify the proper notification is triggered.
   212  	for i, numConfs := range confSpread {
   213  		var blocksToGen uint32
   214  
   215  		// If this is the last instance, manually index to generate the
   216  		// proper block delta in order to avoid a panic.
   217  		if i == len(confSpread)-1 {
   218  			blocksToGen = confSpread[len(confSpread)-1] - confSpread[len(confSpread)-2]
   219  		} else {
   220  			blocksToGen = confSpread[i+1] - confSpread[i]
   221  		}
   222  
   223  		// Generate the number of blocks necessary to trigger this
   224  		// current confirmation notification.
   225  		if _, err := vw.GenerateBlocks(ctxb, blocksToGen); err != nil {
   226  			t.Fatalf("unable to generate single block: %v", err)
   227  		}
   228  
   229  		select {
   230  		case conf := <-confIntents[i].Confirmed:
   231  			// All of the notifications above were originally
   232  			// confirmed in the same block. The returned
   233  			// notification should list the initial confirmation
   234  			// height rather than the height they were _fully_
   235  			// confirmed.
   236  			if conf.BlockHeight != initialConfHeight {
   237  				t.Fatalf("notification has incorrect initial "+
   238  					"conf height: expected %v, got %v",
   239  					initialConfHeight, conf.BlockHeight)
   240  			}
   241  			continue
   242  		case <-time.After(20 * time.Second):
   243  			t.Fatalf("confirmation notification never received: %v", numConfs)
   244  		}
   245  	}
   246  }
   247  
   248  func checkNotificationFields(ntfn *chainntnfs.SpendDetail,
   249  	outpoint *wire.OutPoint, spenderHash *chainhash.Hash,
   250  	height int64, t *testing.T) {
   251  
   252  	t.Helper()
   253  
   254  	if *ntfn.SpentOutPoint != *outpoint {
   255  		t.Fatalf("ntfn includes wrong output, reports "+
   256  			"%v instead of %v",
   257  			ntfn.SpentOutPoint, outpoint)
   258  	}
   259  	if !bytes.Equal(ntfn.SpenderTxHash[:], spenderHash[:]) {
   260  		t.Fatalf("ntfn includes wrong spender tx hash, "+
   261  			"reports %v instead of %v",
   262  			ntfn.SpenderTxHash[:], spenderHash[:])
   263  	}
   264  	if ntfn.SpenderInputIndex != 0 {
   265  		t.Fatalf("ntfn includes wrong spending input "+
   266  			"index, reports %v, should be %v",
   267  			ntfn.SpenderInputIndex, 0)
   268  	}
   269  	if int64(ntfn.SpendingHeight) != height {
   270  		t.Fatalf("ntfn has wrong spending height: "+
   271  			"expected %v, got %v", height,
   272  			ntfn.SpendingHeight)
   273  	}
   274  }
   275  
   276  func testSpendNotification(miner *rpctest.Harness, vw *rpctest.VotingWallet,
   277  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
   278  
   279  	// We'd like to test the spend notifications for all ChainNotifier
   280  	// concrete implementations.
   281  	//
   282  	// To do so, we first create a new output to our test target address.
   283  	outpoint, output, privKey := chainntnfs.CreateSpendableOutput(t, miner, vw)
   284  
   285  	_, currentHeight, err := miner.Node.GetBestBlock(ctxb)
   286  	if err != nil {
   287  		t.Fatalf("unable to get current height: %v", err)
   288  	}
   289  
   290  	// Now that we have an output index and the pkScript, register for a
   291  	// spentness notification for the newly created output with multiple
   292  	// clients in order to ensure the implementation can support
   293  	// multi-client spend notifications.
   294  	const numClients = 5
   295  	spendClients := make([]*chainntnfs.SpendEvent, numClients)
   296  	for i := 0; i < numClients; i++ {
   297  		var spentIntent *chainntnfs.SpendEvent
   298  		if scriptDispatch {
   299  			spentIntent, err = notifier.RegisterSpendNtfn(
   300  				nil, output.PkScript, uint32(currentHeight),
   301  			)
   302  		} else {
   303  			spentIntent, err = notifier.RegisterSpendNtfn(
   304  				outpoint, output.PkScript, uint32(currentHeight),
   305  			)
   306  		}
   307  		if err != nil {
   308  			t.Fatalf("unable to register for spend ntfn: %v", err)
   309  		}
   310  
   311  		spendClients[i] = spentIntent
   312  	}
   313  
   314  	// Next, create a new transaction spending that output.
   315  	spendingTx := chainntnfs.CreateSpendTx(t, outpoint, output, privKey)
   316  
   317  	// Broadcast our spending transaction.
   318  	spenderHash, err := miner.Node.SendRawTransaction(ctxb, spendingTx, true)
   319  	if err != nil {
   320  		t.Fatalf("unable to broadcast tx: %v", err)
   321  	}
   322  
   323  	if err := chainntnfs.WaitForMempoolTx(miner, spenderHash); err != nil {
   324  		t.Fatalf("tx not relayed to miner: %v", err)
   325  	}
   326  
   327  	// Make sure notifications are not yet sent. We launch a go routine for
   328  	// all the spend clients, such that we can wait for them all in
   329  	// parallel.
   330  	//
   331  	// Since dcrd is at times very slow at notifying about txs in the
   332  	// mempool, we use a quite large timeout of 10 seconds.
   333  	// TODO(halseth): change this when mempool spends are removed.
   334  	mempoolSpendTimeout := 10 * time.Second
   335  	mempoolSpends := make(chan *chainntnfs.SpendDetail, numClients)
   336  	for _, c := range spendClients {
   337  		go func(client *chainntnfs.SpendEvent) {
   338  			select {
   339  			case s := <-client.Spend:
   340  				mempoolSpends <- s
   341  			case <-time.After(mempoolSpendTimeout):
   342  			}
   343  		}(c)
   344  	}
   345  
   346  	select {
   347  	case <-mempoolSpends:
   348  		t.Fatalf("did not expect to get notification before " +
   349  			"block was mined")
   350  	case <-time.After(mempoolSpendTimeout):
   351  	}
   352  
   353  	// Make sure registering a client after the tx is in the mempool still
   354  	// doesn't trigger a notification.
   355  	var spentIntent *chainntnfs.SpendEvent
   356  	if scriptDispatch {
   357  		spentIntent, err = notifier.RegisterSpendNtfn(
   358  			nil, output.PkScript, uint32(currentHeight),
   359  		)
   360  	} else {
   361  		spentIntent, err = notifier.RegisterSpendNtfn(
   362  			outpoint, output.PkScript, uint32(currentHeight),
   363  		)
   364  	}
   365  	if err != nil {
   366  		t.Fatalf("unable to register for spend ntfn: %v", err)
   367  	}
   368  
   369  	select {
   370  	case <-spentIntent.Spend:
   371  		t.Fatalf("did not expect to get notification before " +
   372  			"block was mined")
   373  	case <-time.After(mempoolSpendTimeout):
   374  	}
   375  	spendClients = append(spendClients, spentIntent)
   376  
   377  	// Now we mine a single block, which should include our spend. The
   378  	// notification should also be sent off.
   379  	if _, err := vw.GenerateBlocks(ctxb, 1); err != nil {
   380  		t.Fatalf("unable to generate single block: %v", err)
   381  	}
   382  
   383  	_, currentHeight, err = miner.Node.GetBestBlock(ctxb)
   384  	if err != nil {
   385  		t.Fatalf("unable to get current height: %v", err)
   386  	}
   387  
   388  	for _, c := range spendClients {
   389  		select {
   390  		case ntfn := <-c.Spend:
   391  			// We've received the spend nftn. So now verify all the
   392  			// fields have been set properly.
   393  			checkNotificationFields(ntfn, outpoint, spenderHash,
   394  				currentHeight, t)
   395  		case <-time.After(30 * time.Second):
   396  			t.Fatalf("spend ntfn never received")
   397  		}
   398  	}
   399  }
   400  
   401  func testBlockEpochNotification(miner *rpctest.Harness, vw *rpctest.VotingWallet,
   402  	notifier chainntnfs.TestChainNotifier, t *testing.T) {
   403  
   404  	// We'd like to test the case of multiple registered clients receiving
   405  	// block epoch notifications.
   406  	const numBlocks = 10
   407  	const numNtfns = numBlocks + 1
   408  	const numClients = 5
   409  	var wg sync.WaitGroup
   410  
   411  	// Create numClients clients which will listen for block notifications. We
   412  	// expect each client to receive 11 notifications, one for the current
   413  	// tip of the chain, and one for each of the ten blocks we generate
   414  	// below. So we'll use a WaitGroup to synchronize the test.
   415  	clientErrors := make(chan error, numClients)
   416  	for i := 0; i < numClients; i++ {
   417  		epochClient, err := notifier.RegisterBlockEpochNtfn(nil)
   418  		if err != nil {
   419  			t.Fatalf("unable to register for epoch notification")
   420  		}
   421  
   422  		wg.Add(numNtfns)
   423  		go func() {
   424  			for i := 0; i < numNtfns; i++ {
   425  				// Ensure that each block epoch has a header,
   426  				// and that header matches the contained header
   427  				// hash.
   428  				blockEpoch := <-epochClient.Epochs
   429  				if blockEpoch.BlockHeader == nil {
   430  					fmt.Println(i)
   431  					clientErrors <- fmt.Errorf("block " +
   432  						"header is nil")
   433  					return
   434  				}
   435  				if blockEpoch.BlockHeader.BlockHash() !=
   436  					*blockEpoch.Hash {
   437  
   438  					clientErrors <- fmt.Errorf("block " +
   439  						"header hash mismatch")
   440  					return
   441  				}
   442  
   443  				wg.Done()
   444  			}
   445  		}()
   446  	}
   447  
   448  	epochsSent := make(chan struct{})
   449  	go func() {
   450  		wg.Wait()
   451  		close(epochsSent)
   452  	}()
   453  
   454  	// Now generate 10 blocks, the clients above should each receive 10
   455  	// notifications, thereby unblocking the goroutine above.
   456  	if _, err := vw.GenerateBlocks(ctxb, numBlocks); err != nil {
   457  		t.Fatalf("unable to generate blocks: %v", err)
   458  	}
   459  
   460  	select {
   461  	case err := <-clientErrors:
   462  		t.Fatalf("block epoch case failed: %v", err)
   463  	case <-epochsSent:
   464  	case <-time.After(30 * time.Second):
   465  		t.Fatalf("all notifications not sent")
   466  	}
   467  }
   468  
   469  func testMultiClientConfirmationNotification(miner *rpctest.Harness, vw *rpctest.VotingWallet,
   470  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
   471  
   472  	// We'd like to test the case of a multiple clients registered to
   473  	// receive a confirmation notification for the same transaction.
   474  	txid, pkScript, err := chainntnfs.GetTestTxidAndScript(miner)
   475  	if err != nil {
   476  		t.Fatalf("unable to create test tx: %v", err)
   477  	}
   478  	if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
   479  		t.Fatalf("tx not relayed to miner: %v", err)
   480  	}
   481  
   482  	var wg sync.WaitGroup
   483  	const (
   484  		numConfsClients = 5
   485  		numConfs        = 1
   486  	)
   487  
   488  	_, currentHeight, err := miner.Node.GetBestBlock(ctxb)
   489  	if err != nil {
   490  		t.Fatalf("unable to get current height: %v", err)
   491  	}
   492  
   493  	// Register for a conf notification for the above generated txid with
   494  	// numConfsClients distinct clients.
   495  	for i := 0; i < numConfsClients; i++ {
   496  		var confClient *chainntnfs.ConfirmationEvent
   497  		if scriptDispatch {
   498  			confClient, err = notifier.RegisterConfirmationsNtfn(
   499  				nil, pkScript, numConfs, uint32(currentHeight),
   500  			)
   501  		} else {
   502  			confClient, err = notifier.RegisterConfirmationsNtfn(
   503  				txid, pkScript, numConfs, uint32(currentHeight),
   504  			)
   505  		}
   506  		if err != nil {
   507  			t.Fatalf("unable to register for confirmation: %v", err)
   508  		}
   509  
   510  		wg.Add(1)
   511  		go func() {
   512  			<-confClient.Confirmed
   513  			wg.Done()
   514  		}()
   515  	}
   516  
   517  	confsSent := make(chan struct{})
   518  	go func() {
   519  		wg.Wait()
   520  		close(confsSent)
   521  	}()
   522  
   523  	// Finally, generate a single block which should trigger the unblocking
   524  	// of all numConfsClients blocked on the channel read above.
   525  	if _, err := vw.GenerateBlocks(ctxb, 1); err != nil {
   526  		t.Fatalf("unable to generate block: %v", err)
   527  	}
   528  
   529  	select {
   530  	case <-confsSent:
   531  	case <-time.After(30 * time.Second):
   532  		t.Fatalf("all confirmation notifications not sent")
   533  	}
   534  }
   535  
   536  // Tests the case in which a confirmation notification is requested for a
   537  // transaction that has already been included in a block. In this case, the
   538  // confirmation notification should be dispatched immediately.
   539  func testTxConfirmedBeforeNtfnRegistration(miner *rpctest.Harness, vw *rpctest.VotingWallet,
   540  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
   541  
   542  	// First, let's send some coins to "ourself", obtaining a txid.  We're
   543  	// spending from a coinbase output here, so we use the dedicated
   544  	// function.
   545  	txid3, pkScript3, err := chainntnfs.GetTestTxidAndScript(miner)
   546  	if err != nil {
   547  		t.Fatalf("unable to create test tx: %v", err)
   548  	}
   549  	if err := chainntnfs.WaitForMempoolTx(miner, txid3); err != nil {
   550  		t.Fatalf("tx not relayed to miner: %v", err)
   551  	}
   552  
   553  	// Generate another block containing tx 3, but we won't register conf
   554  	// notifications for this tx until much later. The notifier must check
   555  	// older blocks when the confirmation event is registered below to ensure
   556  	// that the TXID hasn't already been included in the chain, otherwise the
   557  	// notification will never be sent.
   558  	_, err = vw.GenerateBlocks(ctxb, 1)
   559  	if err != nil {
   560  		t.Fatalf("unable to generate block: %v", err)
   561  	}
   562  
   563  	txid1, pkScript1, err := chainntnfs.GetTestTxidAndScript(miner)
   564  	if err != nil {
   565  		t.Fatalf("unable to create test tx: %v", err)
   566  	}
   567  	if err := chainntnfs.WaitForMempoolTx(miner, txid1); err != nil {
   568  		t.Fatalf("tx not relayed to miner: %v", err)
   569  	}
   570  
   571  	txid2, pkScript2, err := chainntnfs.GetTestTxidAndScript(miner)
   572  	if err != nil {
   573  		t.Fatalf("unable to create test tx: %v", err)
   574  	}
   575  	if err := chainntnfs.WaitForMempoolTx(miner, txid2); err != nil {
   576  		t.Fatalf("tx not relayed to miner: %v", err)
   577  	}
   578  
   579  	_, currentHeight, err := miner.Node.GetBestBlock(ctxb)
   580  	if err != nil {
   581  		t.Fatalf("unable to get current height: %v", err)
   582  	}
   583  
   584  	// Now generate another block containing txs 1 & 2.
   585  	blockHash, err := vw.GenerateBlocks(ctxb, 1)
   586  	if err != nil {
   587  		t.Fatalf("unable to generate block: %v", err)
   588  	}
   589  
   590  	// Register a confirmation notification with the chainntfn source for tx2,
   591  	// which is included in the last block. The height hint is the height before
   592  	// the block is included. This notification should fire immediately since
   593  	// only 1 confirmation is required.
   594  	var ntfn1 *chainntnfs.ConfirmationEvent
   595  	if scriptDispatch {
   596  		ntfn1, err = notifier.RegisterConfirmationsNtfn(
   597  			nil, pkScript1, 1, uint32(currentHeight),
   598  		)
   599  	} else {
   600  		ntfn1, err = notifier.RegisterConfirmationsNtfn(
   601  			txid1, pkScript1, 1, uint32(currentHeight),
   602  		)
   603  	}
   604  	if err != nil {
   605  		t.Fatalf("unable to register ntfn: %v", err)
   606  	}
   607  
   608  	select {
   609  	case confInfo := <-ntfn1.Confirmed:
   610  		// Finally, we'll verify that the tx index returned is the exact same
   611  		// as the tx index of the transaction within the block itself.
   612  		msgBlock, err := miner.Node.GetBlock(ctxb, blockHash[0])
   613  		if err != nil {
   614  			t.Fatalf("unable to fetch block: %v", err)
   615  		}
   616  		block := dcrutil.NewBlock(msgBlock)
   617  		specifiedTxHash, err := block.TxHash(int(confInfo.TxIndex))
   618  		if err != nil {
   619  			t.Fatalf("unable to index into block: %v", err)
   620  		}
   621  		if !specifiedTxHash.IsEqual(txid1) {
   622  			t.Fatalf("mismatched tx indexes: expected %v, got %v",
   623  				txid1, specifiedTxHash)
   624  		}
   625  
   626  		// We'll also ensure that the block height has been set
   627  		// properly.
   628  		if confInfo.BlockHeight != uint32(currentHeight+1) {
   629  			t.Fatalf("incorrect block height: expected %v, got %v",
   630  				confInfo.BlockHeight, currentHeight)
   631  		}
   632  		break
   633  	case <-time.After(20 * time.Second):
   634  		t.Fatalf("confirmation notification never received")
   635  	}
   636  
   637  	// Register a confirmation notification for tx2, requiring 3 confirmations.
   638  	// This transaction is only partially confirmed, so the notification should
   639  	// not fire yet.
   640  	var ntfn2 *chainntnfs.ConfirmationEvent
   641  	if scriptDispatch {
   642  		ntfn2, err = notifier.RegisterConfirmationsNtfn(
   643  			nil, pkScript2, 3, uint32(currentHeight),
   644  		)
   645  	} else {
   646  		ntfn2, err = notifier.RegisterConfirmationsNtfn(
   647  			txid2, pkScript2, 3, uint32(currentHeight),
   648  		)
   649  	}
   650  	if err != nil {
   651  		t.Fatalf("unable to register ntfn: %v", err)
   652  	}
   653  
   654  	// Fully confirm tx3.
   655  	_, err = vw.GenerateBlocks(ctxb, 2)
   656  	if err != nil {
   657  		t.Fatalf("unable to generate block: %v", err)
   658  	}
   659  
   660  	select {
   661  	case <-ntfn2.Confirmed:
   662  	case <-time.After(10 * time.Second):
   663  		t.Fatalf("confirmation notification never received")
   664  	}
   665  
   666  	select {
   667  	case <-ntfn1.Confirmed:
   668  		t.Fatalf("received multiple confirmations for tx")
   669  	case <-time.After(1 * time.Second):
   670  	}
   671  
   672  	// Finally register a confirmation notification for tx3, requiring 1
   673  	// confirmation. Ensure that conf notifications do not refire on txs
   674  	// 1 or 2.
   675  	var ntfn3 *chainntnfs.ConfirmationEvent
   676  	if scriptDispatch {
   677  		ntfn3, err = notifier.RegisterConfirmationsNtfn(
   678  			nil, pkScript3, 1, uint32(currentHeight-1),
   679  		)
   680  	} else {
   681  		ntfn3, err = notifier.RegisterConfirmationsNtfn(
   682  			txid3, pkScript3, 1, uint32(currentHeight-1),
   683  		)
   684  	}
   685  	if err != nil {
   686  		t.Fatalf("unable to register ntfn: %v", err)
   687  	}
   688  
   689  	// We'll also register for a confirmation notification with the pkscript
   690  	// of a different transaction. This notification shouldn't fire since we
   691  	// match on both txid and pkscript.
   692  	var ntfn4 *chainntnfs.ConfirmationEvent
   693  	ntfn4, err = notifier.RegisterConfirmationsNtfn(
   694  		txid3, pkScript2, 1, uint32(currentHeight-1),
   695  	)
   696  	if err != nil {
   697  		t.Fatalf("unable to register ntfn: %v", err)
   698  	}
   699  
   700  	select {
   701  	case <-ntfn3.Confirmed:
   702  	case <-time.After(10 * time.Second):
   703  		t.Fatalf("confirmation notification never received")
   704  	}
   705  
   706  	select {
   707  	case <-ntfn4.Confirmed:
   708  		t.Fatalf("confirmation notification received")
   709  	case <-time.After(5 * time.Second):
   710  	}
   711  
   712  	time.Sleep(1 * time.Second)
   713  
   714  	select {
   715  	case <-ntfn1.Confirmed:
   716  		t.Fatalf("received multiple confirmations for tx")
   717  	default:
   718  	}
   719  
   720  	select {
   721  	case <-ntfn2.Confirmed:
   722  		t.Fatalf("received multiple confirmations for tx")
   723  	default:
   724  	}
   725  }
   726  
   727  // Test the case of a notification consumer having forget or being delayed in
   728  // checking for a confirmation. This should not cause the notifier to stop
   729  // working
   730  func testLazyNtfnConsumer(miner *rpctest.Harness, vw *rpctest.VotingWallet,
   731  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
   732  
   733  	// Create a transaction to be notified about. We'll register for
   734  	// notifications on this transaction but won't be prompt in checking them
   735  	txid, pkScript, err := chainntnfs.GetTestTxidAndScript(miner)
   736  	if err != nil {
   737  		t.Fatalf("unable to create test tx: %v", err)
   738  	}
   739  	if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
   740  		t.Fatalf("tx not relayed to miner: %v", err)
   741  	}
   742  
   743  	_, currentHeight, err := miner.Node.GetBestBlock(ctxb)
   744  	if err != nil {
   745  		t.Fatalf("unable to get current height: %v", err)
   746  	}
   747  
   748  	numConfs := uint32(3)
   749  
   750  	// Add a block right before registering, this makes race conditions
   751  	// between the historical dispatcher and the normal dispatcher more obvious
   752  	if _, err := vw.GenerateBlocks(ctxb, 1); err != nil {
   753  		t.Fatalf("unable to generate blocks: %v", err)
   754  	}
   755  
   756  	var firstConfIntent *chainntnfs.ConfirmationEvent
   757  	if scriptDispatch {
   758  		firstConfIntent, err = notifier.RegisterConfirmationsNtfn(
   759  			nil, pkScript, numConfs, uint32(currentHeight),
   760  		)
   761  	} else {
   762  		firstConfIntent, err = notifier.RegisterConfirmationsNtfn(
   763  			txid, pkScript, numConfs, uint32(currentHeight),
   764  		)
   765  	}
   766  	if err != nil {
   767  		t.Fatalf("unable to register ntfn: %v", err)
   768  	}
   769  
   770  	// Generate another 2 blocks, this should dispatch the confirm notification
   771  	if _, err := vw.GenerateBlocks(ctxb, 2); err != nil {
   772  		t.Fatalf("unable to generate blocks: %v", err)
   773  	}
   774  
   775  	// Now make another transaction, just because we haven't checked to see
   776  	// if the first transaction has confirmed doesn't mean that we shouldn't
   777  	// be able to see if this transaction confirms first
   778  	txid, pkScript, err = chainntnfs.GetTestTxidAndScript(miner)
   779  	if err != nil {
   780  		t.Fatalf("unable to create test tx: %v", err)
   781  	}
   782  	if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
   783  		t.Fatalf("tx not relayed to miner: %v", err)
   784  	}
   785  
   786  	_, currentHeight, err = miner.Node.GetBestBlock(ctxb)
   787  	if err != nil {
   788  		t.Fatalf("unable to get current height: %v", err)
   789  	}
   790  
   791  	numConfs = 1
   792  	var secondConfIntent *chainntnfs.ConfirmationEvent
   793  	if scriptDispatch {
   794  		secondConfIntent, err = notifier.RegisterConfirmationsNtfn(
   795  			nil, pkScript, numConfs, uint32(currentHeight),
   796  		)
   797  	} else {
   798  		secondConfIntent, err = notifier.RegisterConfirmationsNtfn(
   799  			txid, pkScript, numConfs, uint32(currentHeight),
   800  		)
   801  	}
   802  	if err != nil {
   803  		t.Fatalf("unable to register ntfn: %v", err)
   804  	}
   805  
   806  	if _, err := vw.GenerateBlocks(ctxb, 1); err != nil {
   807  		t.Fatalf("unable to generate blocks: %v", err)
   808  	}
   809  
   810  	select {
   811  	case <-secondConfIntent.Confirmed:
   812  		// Successfully receive the second notification
   813  		break
   814  	case <-time.After(30 * time.Second):
   815  		t.Fatalf("Second confirmation notification never received")
   816  	}
   817  
   818  	// Make sure the first tx confirmed successfully
   819  	select {
   820  	case <-firstConfIntent.Confirmed:
   821  		break
   822  	case <-time.After(30 * time.Second):
   823  		t.Fatalf("First confirmation notification never received")
   824  	}
   825  }
   826  
   827  // Tests the case in which a spend notification is requested for a spend that
   828  // has already been included in a block. In this case, the spend notification
   829  // should be dispatched immediately.
   830  func testSpendBeforeNtfnRegistration(miner *rpctest.Harness, vw *rpctest.VotingWallet,
   831  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
   832  
   833  	// We'd like to test the spend notifications for all ChainNotifier
   834  	// concrete implementations.
   835  	//
   836  	// To do so, we first create a new output to our test target address.
   837  	outpoint, output, privKey := chainntnfs.CreateSpendableOutput(t, miner, vw)
   838  
   839  	_, heightHint, err := miner.Node.GetBestBlock(ctxb)
   840  	if err != nil {
   841  		t.Fatalf("unable to get current height: %v", err)
   842  	}
   843  
   844  	// We'll then spend this output and broadcast the spend transaction.
   845  	spendingTx := chainntnfs.CreateSpendTx(t, outpoint, output, privKey)
   846  	spenderHash, err := miner.Node.SendRawTransaction(ctxb, spendingTx, true)
   847  	if err != nil {
   848  		t.Fatalf("unable to broadcast tx: %v", err)
   849  	}
   850  	if err := chainntnfs.WaitForMempoolTx(miner, spenderHash); err != nil {
   851  		t.Fatalf("tx not relayed to miner: %v", err)
   852  	}
   853  
   854  	// We create an epoch client we can use to make sure the notifier is
   855  	// caught up to the mining node's chain.
   856  	epochClient, err := notifier.RegisterBlockEpochNtfn(nil)
   857  	if err != nil {
   858  		t.Fatalf("unable to register for block epoch: %v", err)
   859  	}
   860  
   861  	// Now we mine an additional block, which should include our spend.
   862  	if _, err := vw.GenerateBlocks(ctxb, 1); err != nil {
   863  		t.Fatalf("unable to generate single block: %v", err)
   864  	}
   865  	_, spendHeight, err := miner.Node.GetBestBlock(ctxb)
   866  	if err != nil {
   867  		t.Fatalf("unable to get current height: %v", err)
   868  	}
   869  
   870  	// When testing via scriptDispatch we ignore the outpoint.
   871  	if scriptDispatch {
   872  		outpoint = &chainntnfs.ZeroOutPoint
   873  	}
   874  
   875  	// checkSpends registers two clients to be notified of a spend that has
   876  	// already happened. The notifier should dispatch a spend notification
   877  	// immediately.
   878  	checkSpends := func() {
   879  		t.Helper()
   880  
   881  		const numClients = 2
   882  		spendClients := make([]*chainntnfs.SpendEvent, numClients)
   883  		for i := 0; i < numClients; i++ {
   884  			var spentIntent *chainntnfs.SpendEvent
   885  			if scriptDispatch {
   886  				spentIntent, err = notifier.RegisterSpendNtfn(
   887  					nil, output.PkScript,
   888  					uint32(heightHint),
   889  				)
   890  			} else {
   891  				spentIntent, err = notifier.RegisterSpendNtfn(
   892  					outpoint, output.PkScript,
   893  					uint32(heightHint),
   894  				)
   895  			}
   896  			if err != nil {
   897  				t.Fatalf("unable to register for spend ntfn: %v",
   898  					err)
   899  			}
   900  
   901  			spendClients[i] = spentIntent
   902  		}
   903  
   904  		for _, client := range spendClients {
   905  			select {
   906  			case ntfn := <-client.Spend:
   907  				// We've received the spend nftn. So now verify
   908  				// all the fields have been set properly.
   909  				checkNotificationFields(
   910  					ntfn, outpoint, spenderHash, spendHeight, t,
   911  				)
   912  			case <-time.After(30 * time.Second):
   913  				t.Fatalf("spend ntfn never received")
   914  			}
   915  		}
   916  	}
   917  
   918  	// Wait for the notifier to have caught up to the mined block.
   919  	var lastBlockEpochHeight int64
   920  	for lastBlockEpochHeight != spendHeight {
   921  		select {
   922  		case be, ok := <-epochClient.Epochs:
   923  			lastBlockEpochHeight = int64(be.Height)
   924  			if !ok {
   925  				t.Fatalf("epoch channel was closed")
   926  			}
   927  		case <-time.After(15 * time.Second):
   928  			t.Fatalf("did not receive block epoch")
   929  		}
   930  	}
   931  
   932  	// Check that the spend clients gets immediately notified for the spend
   933  	// in the previous block.
   934  	checkSpends()
   935  
   936  	// Bury the spend even deeper, and do the same check.
   937  	const numBlocks = 10
   938  	if _, err := vw.GenerateBlocks(ctxb, numBlocks); err != nil {
   939  		t.Fatalf("unable to generate single block: %v", err)
   940  	}
   941  
   942  	// Wait for the notifier to have caught up with the new blocks.
   943  	for i := 0; i < numBlocks; i++ {
   944  		select {
   945  		case _, ok := <-epochClient.Epochs:
   946  			if !ok {
   947  				t.Fatalf("epoch channel was closed")
   948  			}
   949  		case <-time.After(15 * time.Second):
   950  			t.Fatalf("did not receive block epoch")
   951  		}
   952  	}
   953  
   954  	// The clients should still be notified immediately.
   955  	checkSpends()
   956  }
   957  
   958  func testCancelSpendNtfn(node *rpctest.Harness, vw *rpctest.VotingWallet,
   959  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
   960  
   961  	// We'd like to test that once a spend notification is registered, it
   962  	// can be canceled before the notification is dispatched.
   963  
   964  	// First, we'll start by creating a new output that we can spend
   965  	// ourselves.
   966  	outpoint, output, privKey := chainntnfs.CreateSpendableOutput(t, node, vw)
   967  
   968  	_, currentHeight, err := node.Node.GetBestBlock(ctxb)
   969  	if err != nil {
   970  		t.Fatalf("unable to get current height: %v", err)
   971  	}
   972  
   973  	// Create two clients that each registered to the spend notification.
   974  	// We'll cancel the notification for the first client and leave the
   975  	// notification for the second client enabled.
   976  	const numClients = 2
   977  	spendClients := make([]*chainntnfs.SpendEvent, numClients)
   978  	for i := 0; i < numClients; i++ {
   979  		var spentIntent *chainntnfs.SpendEvent
   980  		if scriptDispatch {
   981  			spentIntent, err = notifier.RegisterSpendNtfn(
   982  				nil, output.PkScript, uint32(currentHeight),
   983  			)
   984  		} else {
   985  			spentIntent, err = notifier.RegisterSpendNtfn(
   986  				outpoint, output.PkScript, uint32(currentHeight),
   987  			)
   988  		}
   989  		if err != nil {
   990  			t.Fatalf("unable to register for spend ntfn: %v", err)
   991  		}
   992  
   993  		spendClients[i] = spentIntent
   994  	}
   995  
   996  	// Next, create a new transaction spending that output.
   997  	spendingTx := chainntnfs.CreateSpendTx(t, outpoint, output, privKey)
   998  
   999  	// Before we broadcast the spending transaction, we'll cancel the
  1000  	// notification of the first client.
  1001  	spendClients[1].Cancel()
  1002  
  1003  	// Broadcast our spending transaction.
  1004  	spenderHash, err := node.Node.SendRawTransaction(ctxb, spendingTx, true)
  1005  	if err != nil {
  1006  		t.Fatalf("unable to broadcast tx: %v", err)
  1007  	}
  1008  
  1009  	if err := chainntnfs.WaitForMempoolTx(node, spenderHash); err != nil {
  1010  		t.Fatalf("tx not relayed to miner: %v", err)
  1011  	}
  1012  
  1013  	// Now we mine a single block, which should include our spend. The
  1014  	// notification should also be sent off.
  1015  	if _, err := vw.GenerateBlocks(ctxb, 1); err != nil {
  1016  		t.Fatalf("unable to generate single block: %v", err)
  1017  	}
  1018  
  1019  	// The spend notification for the first client should have been
  1020  	// dispatched.
  1021  	select {
  1022  	case ntfn := <-spendClients[0].Spend:
  1023  		// We've received the spend nftn. So now verify all the
  1024  		// fields have been set properly.
  1025  		if *ntfn.SpentOutPoint != *outpoint {
  1026  			t.Fatalf("ntfn includes wrong output, reports "+
  1027  				"%v instead of %v",
  1028  				ntfn.SpentOutPoint, outpoint)
  1029  		}
  1030  		if !bytes.Equal(ntfn.SpenderTxHash[:], spenderHash[:]) {
  1031  			t.Fatalf("ntfn includes wrong spender tx hash, "+
  1032  				"reports %v instead of %v",
  1033  				ntfn.SpenderTxHash[:], spenderHash[:])
  1034  		}
  1035  		if ntfn.SpenderInputIndex != 0 {
  1036  			t.Fatalf("ntfn includes wrong spending input "+
  1037  				"index, reports %v, should be %v",
  1038  				ntfn.SpenderInputIndex, 0)
  1039  		}
  1040  	case <-time.After(20 * time.Second):
  1041  		t.Fatalf("spend ntfn never received")
  1042  	}
  1043  
  1044  	// However, the spend notification of the second client should NOT have
  1045  	// been dispatched.
  1046  	select {
  1047  	case _, ok := <-spendClients[1].Spend:
  1048  		if ok {
  1049  			t.Fatalf("spend ntfn should have been canceled")
  1050  		}
  1051  	case <-time.After(20 * time.Second):
  1052  		t.Fatalf("spend ntfn never canceled")
  1053  	}
  1054  }
  1055  
  1056  func testCancelEpochNtfn(node *rpctest.Harness, vw *rpctest.VotingWallet,
  1057  	notifier chainntnfs.TestChainNotifier, t *testing.T) {
  1058  
  1059  	// We'd like to ensure that once a client cancels their block epoch
  1060  	// notifications, no further notifications are sent over the channel
  1061  	// if/when new blocks come in.
  1062  	const numClients = 2
  1063  
  1064  	epochClients := make([]*chainntnfs.BlockEpochEvent, numClients)
  1065  	for i := 0; i < numClients; i++ {
  1066  		epochClient, err := notifier.RegisterBlockEpochNtfn(nil)
  1067  		if err != nil {
  1068  			t.Fatalf("unable to register for epoch notification")
  1069  		}
  1070  		epochClients[i] = epochClient
  1071  	}
  1072  
  1073  	// Now before we mine any blocks, cancel the notification for the first
  1074  	// epoch client.
  1075  	epochClients[0].Cancel()
  1076  
  1077  	// Now mine a single block, this should trigger the logic to dispatch
  1078  	// epoch notifications.
  1079  	if _, err := vw.GenerateBlocks(ctxb, 1); err != nil {
  1080  		t.Fatalf("unable to generate blocks: %v", err)
  1081  	}
  1082  
  1083  	// The epoch notification for the first client shouldn't have been
  1084  	// dispatched.
  1085  	select {
  1086  	case _, ok := <-epochClients[0].Epochs:
  1087  		if ok {
  1088  			t.Fatalf("epoch notification should have been canceled")
  1089  		}
  1090  	case <-time.After(2 * time.Second):
  1091  		t.Fatalf("epoch notification not sent")
  1092  	}
  1093  
  1094  	// However, the epoch notification for the second client should have
  1095  	// been dispatched as normal.
  1096  	select {
  1097  	case _, ok := <-epochClients[1].Epochs:
  1098  		if !ok {
  1099  			t.Fatalf("epoch was canceled")
  1100  		}
  1101  	case <-time.After(20 * time.Second):
  1102  		t.Fatalf("epoch notification not sent")
  1103  	}
  1104  }
  1105  
  1106  func testReorgConf(miner *rpctest.Harness, vw *rpctest.VotingWallet,
  1107  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
  1108  
  1109  	// Set up a new miner that we can use to cause a reorg.
  1110  	extraArgs := []string{"--txindex", "--logdir=.miner2"}
  1111  	miner2, err := testutils.NewSetupRPCTest(
  1112  		testctx.New(t), 5, netParams, nil, extraArgs, false, 0,
  1113  	)
  1114  	if err != nil {
  1115  		t.Fatalf("unable to create mining node: %v", err)
  1116  	}
  1117  	defer func() {
  1118  		time.Sleep(time.Millisecond * 50)
  1119  		miner2.TearDown()
  1120  	}()
  1121  
  1122  	// We start by connecting the new miner to our original miner,
  1123  	// such that it will sync to our original chain.
  1124  	if err := rpctest.ConnectNode(ctxb, miner, miner2); err != nil {
  1125  		t.Fatalf("unable to connect harnesses: %v", err)
  1126  	}
  1127  	nodeSlice := []*rpctest.Harness{miner, miner2}
  1128  	if err := rpctest.JoinNodes(ctxb, nodeSlice, rpctest.Blocks); err != nil {
  1129  		t.Fatalf("unable to join node on blocks: %v", err)
  1130  	}
  1131  
  1132  	// The two should be on the same blockheight.
  1133  	_, nodeHeight1, err := miner.Node.GetBestBlock(ctxb)
  1134  	if err != nil {
  1135  		t.Fatalf("unable to get current blockheight %v", err)
  1136  	}
  1137  
  1138  	_, nodeHeight2, err := miner2.Node.GetBestBlock(ctxb)
  1139  	if err != nil {
  1140  		t.Fatalf("unable to get current blockheight %v", err)
  1141  	}
  1142  
  1143  	if nodeHeight1 != nodeHeight2 {
  1144  		t.Fatalf("expected both miners to be on the same height: %v vs %v",
  1145  			nodeHeight1, nodeHeight2)
  1146  	}
  1147  
  1148  	// We disconnect the two nodes, such that we can start mining on them
  1149  	// individually without the other one learning about the new blocks.
  1150  	err = rpctest.RemoveNode(ctxb, miner, miner2)
  1151  	if err != nil {
  1152  		t.Fatalf("unable to remove node: %v", err)
  1153  	}
  1154  
  1155  	txid, pkScript, err := chainntnfs.GetTestTxidAndScript(miner)
  1156  	if err != nil {
  1157  		t.Fatalf("unable to create test tx: %v", err)
  1158  	}
  1159  	if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
  1160  		t.Fatalf("tx not relayed to miner: %v", err)
  1161  	}
  1162  
  1163  	_, currentHeight, err := miner.Node.GetBestBlock(ctxb)
  1164  	if err != nil {
  1165  		t.Fatalf("unable to get current height: %v", err)
  1166  	}
  1167  
  1168  	// Now that we have a txid, register a confirmation notification with
  1169  	// the chainntfn source.
  1170  	numConfs := uint32(2)
  1171  	var confIntent *chainntnfs.ConfirmationEvent
  1172  	if scriptDispatch {
  1173  		confIntent, err = notifier.RegisterConfirmationsNtfn(
  1174  			nil, pkScript, numConfs, uint32(currentHeight),
  1175  		)
  1176  	} else {
  1177  		confIntent, err = notifier.RegisterConfirmationsNtfn(
  1178  			txid, pkScript, numConfs, uint32(currentHeight),
  1179  		)
  1180  	}
  1181  	if err != nil {
  1182  		t.Fatalf("unable to register ntfn: %v", err)
  1183  	}
  1184  
  1185  	// Now generate a single block, the transaction should be included.
  1186  	_, err = vw.GenerateBlocks(ctxb, 1)
  1187  	if err != nil {
  1188  		t.Fatalf("unable to generate single block: %v", err)
  1189  	}
  1190  
  1191  	// Transaction only has one confirmation, and the notification is registered
  1192  	// with 2 confirmations, so we should not be notified yet.
  1193  	select {
  1194  	case <-confIntent.Confirmed:
  1195  		t.Fatal("tx was confirmed unexpectedly")
  1196  	case <-time.After(1 * time.Second):
  1197  	}
  1198  
  1199  	// Reorganize transaction out of the chain by generating a longer fork
  1200  	// from the other miner. The transaction is not included in this fork.
  1201  	if _, err := rpctest.AdjustedSimnetMiner(ctxb, miner2.Node, 2); err != nil {
  1202  		t.Fatalf("unable to generate longer fork: %v", err)
  1203  	}
  1204  
  1205  	// Reconnect nodes to reach consensus on the longest chain. miner2's chain
  1206  	// should win and become active on miner1.
  1207  	if err := rpctest.ConnectNode(ctxb, miner, miner2); err != nil {
  1208  		t.Fatalf("unable to connect harnesses: %v", err)
  1209  	}
  1210  	nodeSlice = []*rpctest.Harness{miner, miner2}
  1211  	if err := rpctest.JoinNodes(ctxb, nodeSlice, rpctest.Blocks); err != nil {
  1212  		t.Fatalf("unable to join node on blocks: %v", err)
  1213  	}
  1214  
  1215  	_, nodeHeight1, err = miner.Node.GetBestBlock(ctxb)
  1216  	if err != nil {
  1217  		t.Fatalf("unable to get current blockheight %v", err)
  1218  	}
  1219  
  1220  	_, nodeHeight2, err = miner2.Node.GetBestBlock(ctxb)
  1221  	if err != nil {
  1222  		t.Fatalf("unable to get current blockheight %v", err)
  1223  	}
  1224  
  1225  	if nodeHeight1 != nodeHeight2 {
  1226  		t.Fatalf("expected both miners to be on the same height: %v vs %v",
  1227  			nodeHeight1, nodeHeight2)
  1228  	}
  1229  
  1230  	// Even though there is one block above the height of the block that the
  1231  	// transaction was included in, it is not the active chain so the
  1232  	// notification should not be sent.
  1233  	select {
  1234  	case <-confIntent.Confirmed:
  1235  		t.Fatal("tx was confirmed unexpectedly")
  1236  	case <-time.After(1 * time.Second):
  1237  	}
  1238  
  1239  	// Now confirm the transaction on the longest chain and verify that we
  1240  	// receive the notification.
  1241  	tx, err := miner.Node.GetRawTransaction(ctxb, txid)
  1242  	if err != nil {
  1243  		t.Fatalf("unable to get raw tx: %v", err)
  1244  	}
  1245  
  1246  	txid, err = miner2.Node.SendRawTransaction(ctxb, tx.MsgTx(), false)
  1247  	if err != nil {
  1248  		t.Fatalf("unable to get send tx: %v", err)
  1249  	}
  1250  	if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
  1251  		t.Fatalf("tx not relayed to miner: %v", err)
  1252  	}
  1253  
  1254  	_, err = vw.GenerateBlocks(ctxb, 3)
  1255  	if err != nil {
  1256  		t.Fatalf("unable to generate single block: %v", err)
  1257  	}
  1258  
  1259  	select {
  1260  	case <-confIntent.Confirmed:
  1261  	case <-time.After(20 * time.Second):
  1262  		t.Fatalf("confirmation notification never received")
  1263  	}
  1264  }
  1265  
  1266  // testReorgSpend ensures that the different ChainNotifier implementations
  1267  // correctly handle outpoints whose spending transaction has been reorged out of
  1268  // the chain.
  1269  func testReorgSpend(miner *rpctest.Harness, vw *rpctest.VotingWallet,
  1270  	notifier chainntnfs.TestChainNotifier, scriptDispatch bool, t *testing.T) {
  1271  
  1272  	// We'll start by creating an output and registering a spend
  1273  	// notification for it.
  1274  	outpoint, output, privKey := chainntnfs.CreateSpendableOutput(t, miner, vw)
  1275  	_, heightHint, err := miner.Node.GetBestBlock(ctxb)
  1276  	if err != nil {
  1277  		t.Fatalf("unable to retrieve current height: %v", err)
  1278  	}
  1279  
  1280  	var spendIntent *chainntnfs.SpendEvent
  1281  	if scriptDispatch {
  1282  		spendIntent, err = notifier.RegisterSpendNtfn(
  1283  			nil, output.PkScript, uint32(heightHint),
  1284  		)
  1285  	} else {
  1286  		spendIntent, err = notifier.RegisterSpendNtfn(
  1287  			outpoint, output.PkScript, uint32(heightHint),
  1288  		)
  1289  	}
  1290  	if err != nil {
  1291  		t.Fatalf("unable to register for spend: %v", err)
  1292  	}
  1293  
  1294  	// Set up a new miner that we can use to cause a reorg.
  1295  	miner2, err := testutils.NewSetupRPCTest(
  1296  		testctx.New(t), 5, netParams, nil, []string{"--txindex"}, false, 0,
  1297  	)
  1298  	if err != nil {
  1299  		t.Fatalf("unable to create mining node: %v", err)
  1300  	}
  1301  	defer func() {
  1302  		time.Sleep(time.Millisecond * 50)
  1303  		miner2.TearDown()
  1304  	}()
  1305  
  1306  	// We start by connecting the new miner to our original miner, in order
  1307  	// to have a consistent view of the chain from both miners. They should
  1308  	// be on the same block height.
  1309  	if err := rpctest.ConnectNode(ctxb, miner, miner2); err != nil {
  1310  		t.Fatalf("unable to connect miners: %v", err)
  1311  	}
  1312  	nodeSlice := []*rpctest.Harness{miner, miner2}
  1313  	if err := rpctest.JoinNodes(ctxb, nodeSlice, rpctest.Blocks); err != nil {
  1314  		t.Fatalf("unable to sync miners: %v", err)
  1315  	}
  1316  	_, minerHeight1, err := miner.Node.GetBestBlock(ctxb)
  1317  	if err != nil {
  1318  		t.Fatalf("unable to get miner1's current height: %v", err)
  1319  	}
  1320  	_, minerHeight2, err := miner2.Node.GetBestBlock(ctxb)
  1321  	if err != nil {
  1322  		t.Fatalf("unable to get miner2's current height: %v", err)
  1323  	}
  1324  	if minerHeight1 != minerHeight2 {
  1325  		t.Fatalf("expected both miners to be on the same height: "+
  1326  			"%v vs %v", minerHeight1, minerHeight2)
  1327  	}
  1328  
  1329  	// We disconnect the two nodes, such that we can start mining on them
  1330  	// individually without the other one learning about the new blocks.
  1331  	err = rpctest.RemoveNode(ctxb, miner, miner2)
  1332  	if err != nil {
  1333  		t.Fatalf("unable to disconnect miners: %v", err)
  1334  	}
  1335  
  1336  	// Craft the spending transaction for the outpoint created above and
  1337  	// confirm it under the chain of the original miner.
  1338  	spendTx := chainntnfs.CreateSpendTx(t, outpoint, output, privKey)
  1339  	spendTxHash, err := miner.Node.SendRawTransaction(ctxb, spendTx, true)
  1340  	if err != nil {
  1341  		t.Fatalf("unable to broadcast spend tx: %v", err)
  1342  	}
  1343  	if err := chainntnfs.WaitForMempoolTx(miner, spendTxHash); err != nil {
  1344  		t.Fatalf("spend tx not relayed to miner: %v", err)
  1345  	}
  1346  	const numBlocks = 1
  1347  	if _, err := vw.GenerateBlocks(ctxb, numBlocks); err != nil {
  1348  		t.Fatalf("unable to generate blocks: %v", err)
  1349  	}
  1350  	_, spendHeight, err := miner.Node.GetBestBlock(ctxb)
  1351  	if err != nil {
  1352  		t.Fatalf("unable to get spend height: %v", err)
  1353  	}
  1354  
  1355  	// We should see a spend notification dispatched with the correct spend
  1356  	// details.
  1357  	select {
  1358  	case spendDetails := <-spendIntent.Spend:
  1359  		checkNotificationFields(
  1360  			spendDetails, outpoint, spendTxHash, spendHeight, t,
  1361  		)
  1362  	case <-time.After(5 * time.Second):
  1363  		t.Fatal("expected spend notification to be dispatched")
  1364  	}
  1365  
  1366  	// Now, with the other miner, we'll generate one more block than the
  1367  	// other miner and connect them to cause a reorg.
  1368  	if _, err := rpctest.AdjustedSimnetMiner(ctxb, miner2.Node, numBlocks+1); err != nil {
  1369  		t.Fatalf("unable to generate blocks: %v", err)
  1370  	}
  1371  	if err := rpctest.ConnectNode(ctxb, miner, miner2); err != nil {
  1372  		t.Fatalf("unable to connect miners: %v", err)
  1373  	}
  1374  	nodeSlice = []*rpctest.Harness{miner2, miner}
  1375  	if err := rpctest.JoinNodes(ctxb, nodeSlice, rpctest.Blocks); err != nil {
  1376  		t.Fatalf("unable to sync miners: %v", err)
  1377  	}
  1378  	_, minerHeight1, err = miner.Node.GetBestBlock(ctxb)
  1379  	if err != nil {
  1380  		t.Fatalf("unable to get miner1's current height: %v", err)
  1381  	}
  1382  	_, minerHeight2, err = miner2.Node.GetBestBlock(ctxb)
  1383  	if err != nil {
  1384  		t.Fatalf("unable to get miner2's current height: %v", err)
  1385  	}
  1386  	if minerHeight1 != minerHeight2 {
  1387  		t.Fatalf("expected both miners to be on the same height: "+
  1388  			"%v vs %v", minerHeight1, minerHeight2)
  1389  	}
  1390  
  1391  	// We should receive a reorg notification.
  1392  	select {
  1393  	case _, ok := <-spendIntent.Reorg:
  1394  		if !ok {
  1395  			t.Fatal("unexpected reorg channel closed")
  1396  		}
  1397  	case <-time.After(5 * time.Second):
  1398  		t.Fatal("expected to receive reorg notification")
  1399  	}
  1400  
  1401  	// Now that both miners are on the same chain, we'll confirm the
  1402  	// spending transaction of the outpoint and receive a notification for
  1403  	// it.
  1404  	if _, err = miner2.Node.SendRawTransaction(ctxb, spendTx, true); err != nil {
  1405  		t.Fatalf("unable to broadcast spend tx: %v", err)
  1406  	}
  1407  	if err := chainntnfs.WaitForMempoolTx(miner, spendTxHash); err != nil {
  1408  		t.Fatalf("tx not relayed to miner: %v", err)
  1409  	}
  1410  	if _, err := vw.GenerateBlocks(ctxb, numBlocks); err != nil {
  1411  		t.Fatalf("unable to generate single block: %v", err)
  1412  	}
  1413  	_, spendHeight, err = miner.Node.GetBestBlock(ctxb)
  1414  	if err != nil {
  1415  		t.Fatalf("unable to retrieve current height: %v", err)
  1416  	}
  1417  
  1418  	select {
  1419  	case spendDetails := <-spendIntent.Spend:
  1420  		checkNotificationFields(
  1421  			spendDetails, outpoint, spendTxHash, spendHeight, t,
  1422  		)
  1423  	case <-time.After(5 * time.Second):
  1424  		t.Fatal("expected spend notification to be dispatched")
  1425  	}
  1426  }
  1427  
  1428  // testCatchUpClientOnMissedBlocks tests the case of multiple registered client
  1429  // receiving historical block epoch notifications due to their best known block
  1430  // being out of date.
  1431  func testCatchUpClientOnMissedBlocks(miner *rpctest.Harness, vw *rpctest.VotingWallet,
  1432  	notifier chainntnfs.TestChainNotifier, t *testing.T) {
  1433  
  1434  	const numBlocks = 10
  1435  	const numClients = 5
  1436  	var wg sync.WaitGroup
  1437  
  1438  	outdatedHash, outdatedHeight, err := miner.Node.GetBestBlock(ctxb)
  1439  	if err != nil {
  1440  		t.Fatalf("unable to retrieve current height: %v", err)
  1441  	}
  1442  
  1443  	// This function is used by UnsafeStart to ensure all notifications
  1444  	// are fully drained before clients register for notifications.
  1445  	generateBlocks := func() error {
  1446  		_, err = vw.GenerateBlocks(ctxb, numBlocks)
  1447  		return err
  1448  	}
  1449  
  1450  	// We want to ensure that when a client registers for block notifications,
  1451  	// the notifier's best block is at the tip of the chain. If it isn't, the
  1452  	// client may not receive all historical notifications.
  1453  	bestHeight := outdatedHeight + numBlocks
  1454  	err = notifier.UnsafeStart(bestHeight, nil, bestHeight, generateBlocks)
  1455  	if err != nil {
  1456  		t.Fatalf("unable to unsafe start the notifier: %v", err)
  1457  	}
  1458  	defer notifier.Stop()
  1459  
  1460  	// Create numClients clients whose best known block is 10 blocks behind
  1461  	// the tip of the chain. We expect each client to receive numBlocks
  1462  	// notifications, 1 for each block  they're behind.
  1463  	clients := make([]*chainntnfs.BlockEpochEvent, 0, numClients)
  1464  	outdatedBlock := &chainntnfs.BlockEpoch{
  1465  		Height: int32(outdatedHeight), Hash: outdatedHash,
  1466  	}
  1467  	for i := 0; i < numClients; i++ {
  1468  		epochClient, err := notifier.RegisterBlockEpochNtfn(outdatedBlock)
  1469  		if err != nil {
  1470  			t.Fatalf("unable to register for epoch notification: %v", err)
  1471  		}
  1472  		clients = append(clients, epochClient)
  1473  	}
  1474  	for expectedHeight := outdatedHeight + 1; expectedHeight <=
  1475  		bestHeight; expectedHeight++ {
  1476  
  1477  		for _, epochClient := range clients {
  1478  			select {
  1479  			case block := <-epochClient.Epochs:
  1480  				if block.Height != int32(expectedHeight) {
  1481  					t.Fatalf("received block of height: %d, "+
  1482  						"expected: %d", block.Height,
  1483  						expectedHeight)
  1484  				}
  1485  			case <-time.After(20 * time.Second):
  1486  				t.Fatalf("did not receive historical notification "+
  1487  					"for height %d", expectedHeight)
  1488  			}
  1489  
  1490  		}
  1491  	}
  1492  
  1493  	// Finally, ensure that an extra block notification wasn't received.
  1494  	anyExtras := make(chan struct{}, len(clients))
  1495  	for _, epochClient := range clients {
  1496  		wg.Add(1)
  1497  		go func(epochClient *chainntnfs.BlockEpochEvent) {
  1498  			defer wg.Done()
  1499  			select {
  1500  			case <-epochClient.Epochs:
  1501  				anyExtras <- struct{}{}
  1502  			case <-time.After(5 * time.Second):
  1503  			}
  1504  		}(epochClient)
  1505  	}
  1506  
  1507  	wg.Wait()
  1508  	close(anyExtras)
  1509  
  1510  	var extraCount int
  1511  	for range anyExtras {
  1512  		extraCount++
  1513  	}
  1514  
  1515  	if extraCount > 0 {
  1516  		t.Fatalf("received %d unexpected block notification", extraCount)
  1517  	}
  1518  }
  1519  
  1520  // testCatchUpOnMissedBlocks the case of multiple registered clients receiving
  1521  // historical block epoch notifications due to the notifier's best known block
  1522  // being out of date.
  1523  func testCatchUpOnMissedBlocks(miner *rpctest.Harness, vw *rpctest.VotingWallet,
  1524  	notifier chainntnfs.TestChainNotifier, t *testing.T) {
  1525  
  1526  	const numBlocks = 10
  1527  	const numClients = 5
  1528  	var wg sync.WaitGroup
  1529  
  1530  	_, bestHeight, err := miner.Node.GetBestBlock(ctxb)
  1531  	if err != nil {
  1532  		t.Fatalf("unable to get current blockheight %v", err)
  1533  	}
  1534  
  1535  	// This function is used by UnsafeStart to ensure all notifications
  1536  	// are fully drained before clients register for notifications.
  1537  	generateBlocks := func() error {
  1538  		_, err = vw.GenerateBlocks(ctxb, numBlocks)
  1539  		return err
  1540  	}
  1541  
  1542  	// Next, start the notifier with outdated best block information.
  1543  	err = notifier.UnsafeStart(
  1544  		bestHeight, nil, bestHeight+numBlocks, generateBlocks,
  1545  	)
  1546  	if err != nil {
  1547  		t.Fatalf("unable to unsafe start the notifier: %v", err)
  1548  	}
  1549  	defer notifier.Stop()
  1550  
  1551  	// Create numClients clients who will listen for block notifications.
  1552  	clients := make([]*chainntnfs.BlockEpochEvent, 0, numClients)
  1553  	for i := 0; i < numClients; i++ {
  1554  		epochClient, err := notifier.RegisterBlockEpochNtfn(nil)
  1555  		if err != nil {
  1556  			t.Fatalf("unable to register for epoch notification: %v", err)
  1557  		}
  1558  
  1559  		// Drain the notification dispatched upon registration as we're
  1560  		// not interested in it.
  1561  		select {
  1562  		case <-epochClient.Epochs:
  1563  		case <-time.After(5 * time.Second):
  1564  			t.Fatal("expected to receive epoch for current block " +
  1565  				"upon registration")
  1566  		}
  1567  
  1568  		clients = append(clients, epochClient)
  1569  	}
  1570  
  1571  	// Generate a single block to trigger the backlog of historical
  1572  	// notifications for the previously mined blocks.
  1573  	if _, err := vw.GenerateBlocks(ctxb, 1); err != nil {
  1574  		t.Fatalf("unable to generate blocks: %v", err)
  1575  	}
  1576  
  1577  	// We expect each client to receive numBlocks + 1 notifications, 1 for
  1578  	// each block that the notifier has missed out on.
  1579  	for expectedHeight := bestHeight + 1; expectedHeight <=
  1580  		bestHeight+numBlocks+1; expectedHeight++ {
  1581  
  1582  		for _, epochClient := range clients {
  1583  			select {
  1584  			case block := <-epochClient.Epochs:
  1585  				if int64(block.Height) != expectedHeight {
  1586  					t.Fatalf("received block of height: %d, "+
  1587  						"expected: %d", block.Height,
  1588  						expectedHeight)
  1589  				}
  1590  			case <-time.After(20 * time.Second):
  1591  				t.Fatalf("did not receive historical notification "+
  1592  					"for height %d", expectedHeight)
  1593  			}
  1594  		}
  1595  	}
  1596  
  1597  	// Finally, ensure that an extra block notification wasn't received.
  1598  	anyExtras := make(chan struct{}, len(clients))
  1599  	for _, epochClient := range clients {
  1600  		wg.Add(1)
  1601  		go func(epochClient *chainntnfs.BlockEpochEvent) {
  1602  			defer wg.Done()
  1603  			select {
  1604  			case <-epochClient.Epochs:
  1605  				anyExtras <- struct{}{}
  1606  			case <-time.After(5 * time.Second):
  1607  			}
  1608  		}(epochClient)
  1609  	}
  1610  
  1611  	wg.Wait()
  1612  	close(anyExtras)
  1613  
  1614  	var extraCount int
  1615  	for range anyExtras {
  1616  		extraCount++
  1617  	}
  1618  
  1619  	if extraCount > 0 {
  1620  		t.Fatalf("received %d unexpected block notification", extraCount)
  1621  	}
  1622  }
  1623  
  1624  // testCatchUpOnMissedBlocks tests that a client will still receive all valid
  1625  // block notifications in the case where a notifier's best block has been reorged
  1626  // out of the chain.
  1627  func testCatchUpOnMissedBlocksWithReorg(miner1 *rpctest.Harness, vw *rpctest.VotingWallet,
  1628  	notifier chainntnfs.TestChainNotifier, t *testing.T) {
  1629  
  1630  	const numBlocks = 10
  1631  	const numClients = 5
  1632  	var wg sync.WaitGroup
  1633  
  1634  	// Set up a new miner that we can use to cause a reorg.
  1635  	miner2, err := testutils.NewSetupRPCTest(
  1636  		testctx.New(t), 5, netParams, nil, []string{"--txindex"}, false, 0,
  1637  	)
  1638  	if err != nil {
  1639  		t.Fatalf("unable to create mining node: %v", err)
  1640  	}
  1641  	defer func() {
  1642  		time.Sleep(time.Millisecond * 50)
  1643  		miner2.TearDown()
  1644  	}()
  1645  
  1646  	// We start by connecting the new miner to our original miner,
  1647  	// such that it will sync to our original chain.
  1648  	if err := rpctest.ConnectNode(ctxb, miner1, miner2); err != nil {
  1649  		t.Fatalf("unable to connect harnesses: %v", err)
  1650  	}
  1651  	nodeSlice := []*rpctest.Harness{miner1, miner2}
  1652  	if err := rpctest.JoinNodes(ctxb, nodeSlice, rpctest.Blocks); err != nil {
  1653  		t.Fatalf("unable to join node on blocks: %v", err)
  1654  	}
  1655  
  1656  	// The two should be on the same blockheight.
  1657  	_, nodeHeight1, err := miner1.Node.GetBestBlock(ctxb)
  1658  	if err != nil {
  1659  		t.Fatalf("unable to get current blockheight %v", err)
  1660  	}
  1661  
  1662  	_, nodeHeight2, err := miner2.Node.GetBestBlock(ctxb)
  1663  	if err != nil {
  1664  		t.Fatalf("unable to get current blockheight %v", err)
  1665  	}
  1666  
  1667  	if nodeHeight1 != nodeHeight2 {
  1668  		t.Fatalf("expected both miners to be on the same height: %v vs %v",
  1669  			nodeHeight1, nodeHeight2)
  1670  	}
  1671  
  1672  	// We disconnect the two nodes, such that we can start mining on them
  1673  	// individually without the other one learning about the new blocks.
  1674  	err = rpctest.RemoveNode(ctxb, miner1, miner2)
  1675  	if err != nil {
  1676  		t.Fatalf("unable to remove node: %v", err)
  1677  	}
  1678  
  1679  	// Now mine on each chain separately
  1680  	blocks, err := vw.GenerateBlocks(ctxb, numBlocks)
  1681  	if err != nil {
  1682  		t.Fatalf("unable to generate single block: %v", err)
  1683  	}
  1684  
  1685  	// We generate an extra block on miner 2's chain to ensure it is the
  1686  	// longer chain.
  1687  	_, err = rpctest.AdjustedSimnetMiner(ctxb, miner2.Node, numBlocks+1)
  1688  	if err != nil {
  1689  		t.Fatalf("unable to generate single block: %v", err)
  1690  	}
  1691  
  1692  	// Sync the two chains to ensure they will sync to miner2's chain.
  1693  	if err := rpctest.ConnectNode(ctxb, miner1, miner2); err != nil {
  1694  		t.Fatalf("unable to connect harnesses: %v", err)
  1695  	}
  1696  	nodeSlice = []*rpctest.Harness{miner1, miner2}
  1697  	if err := rpctest.JoinNodes(ctxb, nodeSlice, rpctest.Blocks); err != nil {
  1698  		t.Fatalf("unable to join node on blocks: %v", err)
  1699  	}
  1700  
  1701  	// The two should be on the same block hash.
  1702  	timeout := time.After(10 * time.Second)
  1703  	for {
  1704  		nodeHash1, _, err := miner1.Node.GetBestBlock(ctxb)
  1705  		if err != nil {
  1706  			t.Fatalf("unable to get current block hash: %v", err)
  1707  		}
  1708  
  1709  		nodeHash2, _, err := miner2.Node.GetBestBlock(ctxb)
  1710  		if err != nil {
  1711  			t.Fatalf("unable to get current block hash: %v", err)
  1712  		}
  1713  
  1714  		if *nodeHash1 == *nodeHash2 {
  1715  			break
  1716  		}
  1717  		select {
  1718  		case <-timeout:
  1719  			t.Fatalf("Unable to sync two chains")
  1720  		case <-time.After(50 * time.Millisecond):
  1721  			continue
  1722  		}
  1723  	}
  1724  
  1725  	// Next, start the notifier with outdated best block information.
  1726  	// We set the notifier's best block to be the last block mined on the
  1727  	// shorter chain, to test that the notifier correctly rewinds to
  1728  	// the common ancestor between the two chains.
  1729  	syncHeight := nodeHeight1 + numBlocks + 1
  1730  	err = notifier.UnsafeStart(
  1731  		nodeHeight1+numBlocks, blocks[numBlocks-1], syncHeight, nil,
  1732  	)
  1733  	if err != nil {
  1734  		t.Fatalf("Unable to unsafe start the notifier: %v", err)
  1735  	}
  1736  	defer notifier.Stop()
  1737  
  1738  	// Create numClients clients who will listen for block notifications.
  1739  	clients := make([]*chainntnfs.BlockEpochEvent, 0, numClients)
  1740  	for i := 0; i < numClients; i++ {
  1741  		epochClient, err := notifier.RegisterBlockEpochNtfn(nil)
  1742  		if err != nil {
  1743  			t.Fatalf("unable to register for epoch notification: %v", err)
  1744  		}
  1745  
  1746  		// Drain the notification dispatched upon registration as we're
  1747  		// not interested in it.
  1748  		select {
  1749  		case <-epochClient.Epochs:
  1750  		case <-time.After(5 * time.Second):
  1751  			t.Fatal("expected to receive epoch for current block " +
  1752  				"upon registration")
  1753  		}
  1754  
  1755  		clients = append(clients, epochClient)
  1756  	}
  1757  
  1758  	// Generate a single block, which should trigger the notifier to rewind
  1759  	// to the common ancestor and dispatch notifications from there.
  1760  	_, err = rpctest.AdjustedSimnetMiner(ctxb, miner2.Node, 1)
  1761  	if err != nil {
  1762  		t.Fatalf("unable to generate single block: %v", err)
  1763  	}
  1764  
  1765  	// If the chain backend to the notifier stores information about reorged
  1766  	// blocks, the notifier is able to rewind the chain to the common
  1767  	// ancestor between the chain tip and its outdated best known block.
  1768  	// In this case, the client is expected to receive numBlocks + 2
  1769  	// notifications, 1 for each block the notifier has missed out on from
  1770  	// the longer chain.
  1771  	//
  1772  	// If the chain backend does not store information about reorged blocks,
  1773  	// the notifier has no way of knowing where to rewind to and therefore
  1774  	// the client is only expected to receive notifications for blocks
  1775  	// whose height is greater than the notifier's best known height: 2
  1776  	// notifications, in this case.
  1777  	var startingHeight int64
  1778  	switch notifier.(type) {
  1779  	default:
  1780  		startingHeight = nodeHeight1 + 1
  1781  	}
  1782  
  1783  	for expectedHeight := startingHeight; expectedHeight <=
  1784  		nodeHeight1+numBlocks+2; expectedHeight++ {
  1785  
  1786  		for _, epochClient := range clients {
  1787  			select {
  1788  			case block := <-epochClient.Epochs:
  1789  				if int64(block.Height) != expectedHeight {
  1790  					t.Fatalf("received block of height: %d, "+
  1791  						"expected: %d", block.Height,
  1792  						expectedHeight)
  1793  				}
  1794  			case <-time.After(20 * time.Second):
  1795  				t.Fatalf("did not receive historical notification "+
  1796  					"for height %d", expectedHeight)
  1797  			}
  1798  		}
  1799  	}
  1800  
  1801  	// Finally, ensure that an extra block notification wasn't received.
  1802  	anyExtras := make(chan struct{}, len(clients))
  1803  	for _, epochClient := range clients {
  1804  		wg.Add(1)
  1805  		go func(epochClient *chainntnfs.BlockEpochEvent) {
  1806  			defer wg.Done()
  1807  			select {
  1808  			case <-epochClient.Epochs:
  1809  				anyExtras <- struct{}{}
  1810  			case <-time.After(5 * time.Second):
  1811  			}
  1812  		}(epochClient)
  1813  	}
  1814  
  1815  	wg.Wait()
  1816  	close(anyExtras)
  1817  
  1818  	var extraCount int
  1819  	for range anyExtras {
  1820  		extraCount++
  1821  	}
  1822  
  1823  	if extraCount > 0 {
  1824  		t.Fatalf("received %d unexpected block notification", extraCount)
  1825  	}
  1826  }
  1827  
  1828  type txNtfnTestCase struct {
  1829  	name string
  1830  	test func(node *rpctest.Harness, vw *rpctest.VotingWallet, notifier chainntnfs.TestChainNotifier,
  1831  		scriptDispatch bool, t *testing.T)
  1832  }
  1833  
  1834  type blockNtfnTestCase struct {
  1835  	name string
  1836  	test func(node *rpctest.Harness, vw *rpctest.VotingWallet, notifier chainntnfs.TestChainNotifier,
  1837  		t *testing.T)
  1838  }
  1839  
  1840  type blockCatchupTestCase struct {
  1841  	name string
  1842  	test func(node *rpctest.Harness, vw *rpctest.VotingWallet, notifier chainntnfs.TestChainNotifier,
  1843  		t *testing.T)
  1844  }
  1845  
  1846  var txNtfnTests = []txNtfnTestCase{
  1847  	// These tests needs come before the others to prevent the reorg
  1848  	// messing with stake voting.
  1849  	{
  1850  		name: "reorg conf",
  1851  		test: testReorgConf,
  1852  	},
  1853  	{
  1854  		name: "reorg spend",
  1855  		test: testReorgSpend,
  1856  	},
  1857  	{
  1858  		name: "single conf ntfn",
  1859  		test: testSingleConfirmationNotification,
  1860  	},
  1861  	{
  1862  		name: "multi conf ntfn",
  1863  		test: testMultiConfirmationNotification,
  1864  	},
  1865  	{
  1866  		name: "batch conf ntfn",
  1867  		test: testBatchConfirmationNotification,
  1868  	},
  1869  	{
  1870  		name: "multi client conf",
  1871  		test: testMultiClientConfirmationNotification,
  1872  	},
  1873  	{
  1874  		name: "lazy ntfn consumer",
  1875  		test: testLazyNtfnConsumer,
  1876  	},
  1877  	{
  1878  		name: "historical conf dispatch",
  1879  		test: testTxConfirmedBeforeNtfnRegistration,
  1880  	},
  1881  	{
  1882  		name: "spend ntfn",
  1883  		test: testSpendNotification,
  1884  	},
  1885  	{
  1886  		name: "historical spend dispatch",
  1887  		test: testSpendBeforeNtfnRegistration,
  1888  	},
  1889  	{
  1890  		name: "cancel spend ntfn",
  1891  		test: testCancelSpendNtfn,
  1892  	},
  1893  }
  1894  
  1895  var blockNtfnTests = []blockNtfnTestCase{
  1896  	{
  1897  		name: "block epoch",
  1898  		test: testBlockEpochNotification,
  1899  	},
  1900  	{
  1901  		name: "cancel epoch ntfn",
  1902  		test: testCancelEpochNtfn,
  1903  	},
  1904  }
  1905  
  1906  var blockCatchupTests = []blockCatchupTestCase{
  1907  	// This test needs to come first to prevent it messing with stake
  1908  	// transactions for the others.
  1909  	{
  1910  		name: "test catch up on missed blocks w/ reorged best block",
  1911  		test: testCatchUpOnMissedBlocksWithReorg,
  1912  	},
  1913  	{
  1914  		name: "catch up client on historical block epoch ntfns",
  1915  		test: testCatchUpClientOnMissedBlocks,
  1916  	},
  1917  	{
  1918  		name: "test catch up on missed blocks",
  1919  		test: testCatchUpOnMissedBlocks,
  1920  	},
  1921  }
  1922  
  1923  // TestInterfaces tests all registered interfaces with a unified set of tests
  1924  // which exercise each of the required methods found within the ChainNotifier
  1925  // interface.
  1926  //
  1927  // NOTE: In the future, when additional implementations of the ChainNotifier
  1928  // interface have been implemented, in order to ensure the new concrete
  1929  // implementation is automatically tested, two steps must be undertaken. First,
  1930  // one needs add a "non-captured" (_) import from the new sub-package. This
  1931  // import should trigger an init() method within the package which registers
  1932  // the interface. Second, an additional case in the switch within the main loop
  1933  // below needs to be added which properly initializes the interface.
  1934  //
  1935  // syncerType may be "dcrd" or "spv", depending on what the backing wallet
  1936  // should be syncing to. This is only applicable to the dcrw and remotedcrw
  1937  // notifier types.
  1938  func TestInterfaces(t *testing.T, notifierType, syncerType string) {
  1939  	t.Parallel()
  1940  
  1941  	if chainntnfs.NotifierByName(notifierType) == nil {
  1942  		t.Fatalf("Notifier %s does not exist", notifierType)
  1943  	}
  1944  
  1945  	// newMiner initializes a new rpctest harness for testing and returns
  1946  	// that.
  1947  	newMiner := func(t *testing.T, notifierType string) (*rpctest.Harness, *rpctest.VotingWallet, func()) {
  1948  		// Initialize the harness around a dcrd node which will serve as our
  1949  		// dedicated miner to generate blocks, cause re-orgs, etc. We'll set up
  1950  		// this node with a chain length of 125, so we have plenty of DCR to
  1951  		// play around with.
  1952  		minerLogDir := fmt.Sprintf(".miner-logs-%s-%s", notifierType, syncerType)
  1953  		minerArgs := []string{"--debuglevel=debug", "--logdir=" + minerLogDir}
  1954  
  1955  		miner, err := testutils.NewSetupRPCTest(
  1956  			testctx.New(t), 5, netParams, nil, minerArgs, false, 0,
  1957  		)
  1958  		if err != nil {
  1959  			t.Fatalf("unable to create backend node: %v", err)
  1960  		}
  1961  
  1962  		// Generate the premine block the usual way.
  1963  		_, err = miner.Node.Generate(ctxb, 1)
  1964  		if err != nil {
  1965  			t.Fatalf("unable to generate premine: %v", err)
  1966  		}
  1967  
  1968  		// Generate enough blocks so that the network harness can have
  1969  		// funds to send to the voting wallet, Alice and Bob.
  1970  		_, err = rpctest.AdjustedSimnetMiner(ctxb, miner.Node, 64)
  1971  		if err != nil {
  1972  			t.Fatalf("unable to init chain: %v", err)
  1973  		}
  1974  
  1975  		vw, err := rpctest.NewVotingWallet(ctxb, miner)
  1976  		if err != nil {
  1977  			t.Fatalf("unable to create voting wallet: %v", err)
  1978  		}
  1979  
  1980  		// Use a custom miner on the voting wallet that ensures simnet blocks
  1981  		// are generated as fast as possible without triggering PoW difficulty
  1982  		// increases.
  1983  		vw.SetMiner(func(ctx context.Context, nb uint32) ([]*chainhash.Hash, error) {
  1984  			return rpctest.AdjustedSimnetMiner(ctxb, miner.Node, nb)
  1985  		})
  1986  
  1987  		vwCtx, vwCancel := context.WithCancel(ctxb)
  1988  		err = vw.Start(vwCtx)
  1989  		if err != nil {
  1990  			t.Fatalf("unable to start voting wallet: %v", err)
  1991  		}
  1992  
  1993  		tearDown := func() {
  1994  			vwCancel()
  1995  			miner.TearDown()
  1996  		}
  1997  
  1998  		return miner, vw, tearDown
  1999  	}
  2000  
  2001  	newNotifier := func(t *testing.T, notifierType string, startNotifier bool, miner *rpctest.Harness) (chainntnfs.TestChainNotifier, func()) {
  2002  		// Initialize a height hint cache for each notifier.
  2003  		tempDir, err := ioutil.TempDir("", "channeldb")
  2004  		if err != nil {
  2005  			t.Fatalf("unable to create temp dir: %v", err)
  2006  		}
  2007  		db, err := channeldb.Open(tempDir)
  2008  		if err != nil {
  2009  			t.Fatalf("unable to create db: %v", err)
  2010  		}
  2011  		testCfg := chainntnfs.CacheConfig{
  2012  			QueryDisable: false,
  2013  		}
  2014  		hintCache, err := chainntnfs.NewHeightHintCache(
  2015  			testCfg, db.Backend,
  2016  		)
  2017  		if err != nil {
  2018  			t.Fatalf("unable to create height hint cache: %v", err)
  2019  		}
  2020  
  2021  		var notifier chainntnfs.TestChainNotifier
  2022  		var tearDownNotifier func()
  2023  		switch notifierType {
  2024  		case "dcrd":
  2025  			backend := miner.RPCConfig()
  2026  			notifier, err = dcrdnotify.New(
  2027  				&backend, netParams, hintCache,
  2028  				hintCache, nil,
  2029  			)
  2030  			if err != nil {
  2031  				t.Fatalf("error initializing dcrd notifier: %v", err)
  2032  			}
  2033  
  2034  		case "dcrw":
  2035  			var w *wallet.Wallet
  2036  			var teardown func()
  2037  			switch syncerType {
  2038  			case "dcrd":
  2039  				backend := miner.RPCConfig()
  2040  				w, teardown = testutils.NewRPCSyncingTestWallet(t, &backend)
  2041  			case "spv":
  2042  				w, teardown = testutils.NewSPVSyncingTestWallet(t, miner.P2PAddress())
  2043  			default:
  2044  				t.Fatalf("unknown syncer type %s", syncerType)
  2045  			}
  2046  
  2047  			notifier, err = dcrwnotify.New(
  2048  				w, netParams, hintCache, hintCache, nil,
  2049  			)
  2050  			if err != nil {
  2051  				t.Fatalf("error initializing dcrw notifier: %v", err)
  2052  			}
  2053  			tearDownNotifier = teardown
  2054  
  2055  		case "remotedcrw":
  2056  			var c *grpc.ClientConn
  2057  			var teardown func()
  2058  			switch syncerType {
  2059  			case "dcrd":
  2060  				backend := miner.RPCConfig()
  2061  				c, teardown = testutils.NewRPCSyncingTestRemoteDcrwallet(t, &backend)
  2062  			case "spv":
  2063  				c, teardown = testutils.NewSPVSyncingTestRemoteDcrwallet(t, miner.P2PAddress())
  2064  			default:
  2065  				t.Fatalf("unknown syncer type %s", syncerType)
  2066  			}
  2067  			notifier, err = remotedcrwnotify.New(
  2068  				c, netParams, hintCache, hintCache, nil,
  2069  			)
  2070  			if err != nil {
  2071  				t.Fatalf("error initializing dcrw notifier: %v", err)
  2072  			}
  2073  			tearDownNotifier = teardown
  2074  
  2075  		default:
  2076  			t.Fatalf("unknown notifier type: %v", notifierType)
  2077  		}
  2078  
  2079  		if startNotifier {
  2080  			if err := notifier.Start(); err != nil {
  2081  				t.Fatalf("unable to start notifier %v: %v",
  2082  					notifierType, err)
  2083  			}
  2084  		}
  2085  
  2086  		cleanUp := func() {
  2087  			if startNotifier {
  2088  				notifier.Stop()
  2089  			}
  2090  			if tearDownNotifier != nil {
  2091  				tearDownNotifier()
  2092  			}
  2093  		}
  2094  
  2095  		return notifier, cleanUp
  2096  	}
  2097  
  2098  	log.Printf("Running %v ChainNotifier interface tests", len(txNtfnTests))
  2099  
  2100  	miner, vw, tearDownMiner := newMiner(t, notifierType)
  2101  	defer tearDownMiner()
  2102  
  2103  	notifier, tearDownNotifier := newNotifier(
  2104  		t, notifierType, true, miner,
  2105  	)
  2106  	defer tearDownNotifier()
  2107  
  2108  	for _, txNtfnTest := range txNtfnTests {
  2109  		for _, scriptDispatch := range []bool{false, true} {
  2110  			testName := txNtfnTest.name
  2111  			if scriptDispatch {
  2112  				testName += " with script dispatch"
  2113  			}
  2114  			success := t.Run(testName, func(t *testing.T) {
  2115  				txNtfnTest.test(
  2116  					miner, vw, notifier,
  2117  					scriptDispatch, t,
  2118  				)
  2119  			})
  2120  			if !success {
  2121  				return
  2122  			}
  2123  		}
  2124  	}
  2125  
  2126  	for _, blockNtfnTest := range blockNtfnTests {
  2127  		testName := blockNtfnTest.name
  2128  		success := t.Run(testName, func(t *testing.T) {
  2129  			blockNtfnTest.test(miner, vw, notifier, t)
  2130  		})
  2131  		if !success {
  2132  			return
  2133  		}
  2134  	}
  2135  
  2136  	// The first test for the next set of tests causes a
  2137  	// reorg, so recreate a new miner.
  2138  	miner, vw, tearDownMiner = newMiner(t, notifierType)
  2139  	defer tearDownMiner()
  2140  
  2141  	// Run catchup tests separately since they require restarting
  2142  	// the notifier every time.
  2143  	for _, blockCatchupTest := range blockCatchupTests {
  2144  		testName := blockCatchupTest.name
  2145  
  2146  		success := t.Run(testName, func(t *testing.T) {
  2147  			notifier, tearDownNotifier := newNotifier(
  2148  				t, notifierType, false, miner,
  2149  			)
  2150  			defer tearDownNotifier()
  2151  			blockCatchupTest.test(miner, vw, notifier, t)
  2152  		})
  2153  		if !success {
  2154  			return
  2155  		}
  2156  	}
  2157  }