diff --git a/chainntnfs/bitcoindnotify/bitcoind.go b/chainntnfs/bitcoindnotify/bitcoind.go index d5203de25..f9fbfaf65 100644 --- a/chainntnfs/bitcoindnotify/bitcoind.go +++ b/chainntnfs/bitcoindnotify/bitcoind.go @@ -9,6 +9,7 @@ import ( "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwallet/chain" @@ -39,7 +40,6 @@ type chainUpdate struct { // chain client. Multiple concurrent clients are supported. All notifications // are achieved via non-blocking sends on client channels. type BitcoindNotifier struct { - spendClientCounter uint64 // To be used atomically. epochClientCounter uint64 // To be used atomically. started int32 // To be used atomically. @@ -615,23 +615,11 @@ func (b *BitcoindNotifier) notifyBlockEpochClient(epochClient *blockEpochRegistr func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) { - // First, we'll construct a spend notification request and hand it off - // to the txNotifier. - spendID := atomic.AddUint64(&b.spendClientCounter, 1) - spendRequest, err := chainntnfs.NewSpendRequest(outpoint, pkScript) - if err != nil { - return nil, err - } - ntfn := &chainntnfs.SpendNtfn{ - SpendID: spendID, - SpendRequest: spendRequest, - Event: chainntnfs.NewSpendEvent(func() { - b.txNotifier.CancelSpend(spendRequest, spendID) - }), - HeightHint: heightHint, - } - - historicalDispatch, _, err := b.txNotifier.RegisterSpend(ntfn) + // Register the conf notification with the TxNotifier. A non-nil value + // for `dispatch` will be returned if we are required to perform a + // manual scan for the confirmation. Otherwise the notifier will begin + // watching at tip for the transaction to confirm. + ntfn, err := b.txNotifier.RegisterSpend(outpoint, pkScript, heightHint) if err != nil { return nil, err } @@ -640,17 +628,18 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // outpoint/output script as spent. // // TODO(wilmer): use LoadFilter API instead. - if spendRequest.OutPoint == chainntnfs.ZeroOutPoint { - addr, err := spendRequest.PkScript.Address(b.chainParams) + if outpoint == nil || *outpoint == chainntnfs.ZeroOutPoint { + _, addrs, _, err := txscript.ExtractPkScriptAddrs( + pkScript, b.chainParams, + ) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to parse script: %v", err) } - addrs := []btcutil.Address{addr} if err := b.chainConn.NotifyReceived(addrs); err != nil { return nil, err } } else { - ops := []*wire.OutPoint{&spendRequest.OutPoint} + ops := []*wire.OutPoint{outpoint} if err := b.chainConn.NotifySpent(ops); err != nil { return nil, err } @@ -659,7 +648,7 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // If the txNotifier didn't return any details to perform a historical // scan of the chain, then we can return early as there's nothing left // for us to do. - if historicalDispatch == nil { + if ntfn.HistoricalDispatch == nil { return ntfn.Event, nil } @@ -669,9 +658,9 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // We'll short-circuit the path when dispatching the spend of a script, // rather than an outpoint, as there aren't any additional checks we can // make for scripts. - if spendRequest.OutPoint == chainntnfs.ZeroOutPoint { + if ntfn.HistoricalDispatch.OutPoint == chainntnfs.ZeroOutPoint { select { - case b.notificationRegistry <- historicalDispatch: + case b.notificationRegistry <- ntfn.HistoricalDispatch: case <-b.quit: return nil, chainntnfs.ErrChainNotifierShuttingDown } @@ -686,16 +675,16 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // We'll start by checking the backend's UTXO set to determine whether // the outpoint has been spent. If it hasn't, we can return to the // caller as well. - txOut, err := b.chainConn.GetTxOut( - &spendRequest.OutPoint.Hash, spendRequest.OutPoint.Index, true, - ) + txOut, err := b.chainConn.GetTxOut(&outpoint.Hash, outpoint.Index, true) if err != nil { return nil, err } if txOut != nil { // We'll let the txNotifier know the outpoint is still unspent // in order to begin updating its spend hint. - err := b.txNotifier.UpdateSpendDetails(spendRequest, nil) + err := b.txNotifier.UpdateSpendDetails( + ntfn.HistoricalDispatch.SpendRequest, nil, + ) if err != nil { return nil, err } @@ -710,14 +699,14 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // index (if enabled) to determine if we have a better rescan starting // height. We can do this as the GetRawTransaction call will return the // hash of the block it was included in within the chain. - tx, err := b.chainConn.GetRawTransactionVerbose(&spendRequest.OutPoint.Hash) + tx, err := b.chainConn.GetRawTransactionVerbose(&outpoint.Hash) if err != nil { // Avoid returning an error if the transaction was not found to // proceed with fallback methods. jsonErr, ok := err.(*btcjson.RPCError) if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo { return nil, fmt.Errorf("unable to query for txid %v: %v", - spendRequest.OutPoint.Hash, err) + outpoint.Hash, err) } } @@ -740,15 +729,15 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, return nil, err } - if uint32(blockHeight) > historicalDispatch.StartHeight { - historicalDispatch.StartHeight = uint32(blockHeight) + if uint32(blockHeight) > ntfn.HistoricalDispatch.StartHeight { + ntfn.HistoricalDispatch.StartHeight = uint32(blockHeight) } } // Now that we've determined the starting point of our rescan, we can // dispatch it and return. select { - case b.notificationRegistry <- historicalDispatch: + case b.notificationRegistry <- ntfn.HistoricalDispatch: case <-b.quit: return nil, chainntnfs.ErrChainNotifierShuttingDown } diff --git a/chainntnfs/btcdnotify/btcd.go b/chainntnfs/btcdnotify/btcd.go index c174f4c85..cdd1e7789 100644 --- a/chainntnfs/btcdnotify/btcd.go +++ b/chainntnfs/btcdnotify/btcd.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/chainntnfs" @@ -50,7 +51,6 @@ type txUpdate struct { // notifications. Multiple concurrent clients are supported. All notifications // are achieved via non-blocking sends on client channels. type BtcdNotifier struct { - spendClientCounter uint64 // To be used atomically. epochClientCounter uint64 // To be used atomically. started int32 // To be used atomically. @@ -651,23 +651,11 @@ func (b *BtcdNotifier) notifyBlockEpochClient(epochClient *blockEpochRegistratio func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) { - // First, we'll construct a spend notification request and hand it off - // to the txNotifier. - spendID := atomic.AddUint64(&b.spendClientCounter, 1) - spendRequest, err := chainntnfs.NewSpendRequest(outpoint, pkScript) - if err != nil { - return nil, err - } - ntfn := &chainntnfs.SpendNtfn{ - SpendID: spendID, - SpendRequest: spendRequest, - Event: chainntnfs.NewSpendEvent(func() { - b.txNotifier.CancelSpend(spendRequest, spendID) - }), - HeightHint: heightHint, - } - - historicalDispatch, _, err := b.txNotifier.RegisterSpend(ntfn) + // Register the conf notification with the TxNotifier. A non-nil value + // for `dispatch` will be returned if we are required to perform a + // manual scan for the confirmation. Otherwise the notifier will begin + // watching at tip for the transaction to confirm. + ntfn, err := b.txNotifier.RegisterSpend(outpoint, pkScript, heightHint) if err != nil { return nil, err } @@ -676,17 +664,18 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // outpoint/output script as spent. // // TODO(wilmer): use LoadFilter API instead. - if spendRequest.OutPoint == chainntnfs.ZeroOutPoint { - addr, err := spendRequest.PkScript.Address(b.chainParams) + if outpoint == nil || *outpoint == chainntnfs.ZeroOutPoint { + _, addrs, _, err := txscript.ExtractPkScriptAddrs( + pkScript, b.chainParams, + ) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to parse script: %v", err) } - addrs := []btcutil.Address{addr} if err := b.chainConn.NotifyReceived(addrs); err != nil { return nil, err } } else { - ops := []*wire.OutPoint{&spendRequest.OutPoint} + ops := []*wire.OutPoint{outpoint} if err := b.chainConn.NotifySpent(ops); err != nil { return nil, err } @@ -695,7 +684,7 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // If the txNotifier didn't return any details to perform a historical // scan of the chain, then we can return early as there's nothing left // for us to do. - if historicalDispatch == nil { + if ntfn.HistoricalDispatch == nil { return ntfn.Event, nil } @@ -705,26 +694,29 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // We'll short-circuit the path when dispatching the spend of a script, // rather than an outpoint, as there aren't any additional checks we can // make for scripts. - if spendRequest.OutPoint == chainntnfs.ZeroOutPoint { + if outpoint == nil || *outpoint == chainntnfs.ZeroOutPoint { startHash, err := b.chainConn.GetBlockHash( - int64(historicalDispatch.StartHeight), + int64(ntfn.HistoricalDispatch.StartHeight), ) if err != nil { return nil, err } // TODO(wilmer): add retry logic if rescan fails? - addr, err := spendRequest.PkScript.Address(b.chainParams) + _, addrs, _, err := txscript.ExtractPkScriptAddrs( + pkScript, b.chainParams, + ) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to parse address: %v", err) } - addrs := []btcutil.Address{addr} + asyncResult := b.chainConn.RescanAsync(startHash, addrs, nil) go func() { if rescanErr := asyncResult.Receive(); rescanErr != nil { chainntnfs.Log.Errorf("Rescan to determine "+ "the spend details of %v failed: %v", - spendRequest, rescanErr) + ntfn.HistoricalDispatch.SpendRequest, + rescanErr) } }() @@ -738,16 +730,16 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // We'll start by checking the backend's UTXO set to determine whether // the outpoint has been spent. If it hasn't, we can return to the // caller as well. - txOut, err := b.chainConn.GetTxOut( - &spendRequest.OutPoint.Hash, spendRequest.OutPoint.Index, true, - ) + txOut, err := b.chainConn.GetTxOut(&outpoint.Hash, outpoint.Index, true) if err != nil { return nil, err } if txOut != nil { // We'll let the txNotifier know the outpoint is still unspent // in order to begin updating its spend hint. - err := b.txNotifier.UpdateSpendDetails(spendRequest, nil) + err := b.txNotifier.UpdateSpendDetails( + ntfn.HistoricalDispatch.SpendRequest, nil, + ) if err != nil { return nil, err } @@ -759,25 +751,25 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // set, we'll determine when it happened by scanning the chain. We'll // begin by fetching the block hash of our starting height. startHash, err := b.chainConn.GetBlockHash( - int64(historicalDispatch.StartHeight), + int64(ntfn.HistoricalDispatch.StartHeight), ) if err != nil { return nil, fmt.Errorf("unable to get block hash for height "+ - "%d: %v", historicalDispatch.StartHeight, err) + "%d: %v", ntfn.HistoricalDispatch.StartHeight, err) } // As a minimal optimization, we'll query the backend's transaction // index (if enabled) to determine if we have a better rescan starting // height. We can do this as the GetRawTransaction call will return the // hash of the block it was included in within the chain. - tx, err := b.chainConn.GetRawTransactionVerbose(&spendRequest.OutPoint.Hash) + tx, err := b.chainConn.GetRawTransactionVerbose(&outpoint.Hash) if err != nil { // Avoid returning an error if the transaction was not found to // proceed with fallback methods. jsonErr, ok := err.(*btcjson.RPCError) if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo { return nil, fmt.Errorf("unable to query for txid %v: %v", - spendRequest.OutPoint.Hash, err) + outpoint.Hash, err) } } @@ -801,7 +793,7 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, "block %v: %v", blockHash, err) } - if uint32(blockHeader.Height) > historicalDispatch.StartHeight { + if uint32(blockHeader.Height) > ntfn.HistoricalDispatch.StartHeight { startHash, err = b.chainConn.GetBlockHash( int64(blockHeader.Height), ) @@ -824,13 +816,12 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // // TODO(wilmer): add retry logic if rescan fails? asyncResult := b.chainConn.RescanAsync( - startHash, nil, []*wire.OutPoint{&spendRequest.OutPoint}, + startHash, nil, []*wire.OutPoint{outpoint}, ) go func() { if rescanErr := asyncResult.Receive(); rescanErr != nil { chainntnfs.Log.Errorf("Rescan to determine the spend "+ - "details of %v failed: %v", spendRequest, - rescanErr) + "details of %v failed: %v", outpoint, rescanErr) } }() diff --git a/chainntnfs/neutrinonotify/neutrino.go b/chainntnfs/neutrinonotify/neutrino.go index 76f6dcbcd..ab9c51e9d 100644 --- a/chainntnfs/neutrinonotify/neutrino.go +++ b/chainntnfs/neutrinonotify/neutrino.go @@ -37,7 +37,6 @@ const ( // TODO(roasbeef): heavily consolidate with NeutrinoNotifier code // * maybe combine into single package? type NeutrinoNotifier struct { - spendClientCounter uint64 // To be used atomically. epochClientCounter uint64 // To be used atomically. started int32 // To be used atomically. @@ -662,23 +661,11 @@ func (n *NeutrinoNotifier) notifyBlockEpochClient(epochClient *blockEpochRegistr func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) { - // First, we'll construct a spend notification request and hand it off - // to the txNotifier. - spendID := atomic.AddUint64(&n.spendClientCounter, 1) - spendRequest, err := chainntnfs.NewSpendRequest(outpoint, pkScript) - if err != nil { - return nil, err - } - ntfn := &chainntnfs.SpendNtfn{ - SpendID: spendID, - SpendRequest: spendRequest, - Event: chainntnfs.NewSpendEvent(func() { - n.txNotifier.CancelSpend(spendRequest, spendID) - }), - HeightHint: heightHint, - } - - historicalDispatch, txNotifierTip, err := n.txNotifier.RegisterSpend(ntfn) + // Register the conf notification with the TxNotifier. A non-nil value + // for `dispatch` will be returned if we are required to perform a + // manual scan for the confirmation. Otherwise the notifier will begin + // watching at tip for the transaction to confirm. + ntfn, err := n.txNotifier.RegisterSpend(outpoint, pkScript, heightHint) if err != nil { return nil, err } @@ -690,9 +677,12 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // // We'll update our filter first to ensure we can immediately detect the // spend at tip. + if outpoint == nil { + outpoint = &chainntnfs.ZeroOutPoint + } inputToWatch := neutrino.InputWithScript{ - OutPoint: spendRequest.OutPoint, - PkScript: spendRequest.PkScript.Script(), + OutPoint: *outpoint, + PkScript: pkScript, } updateOptions := []neutrino.UpdateOption{ neutrino.AddInputs(inputToWatch), @@ -703,10 +693,9 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // update. In the case of an output script spend request, we'll check if // we should perform a historical rescan and start from there, as we // cannot do so with GetUtxo since it matches outpoints. - rewindHeight := txNotifierTip - if historicalDispatch != nil && - spendRequest.OutPoint == chainntnfs.ZeroOutPoint { - rewindHeight = historicalDispatch.StartHeight + rewindHeight := ntfn.Height + if ntfn.HistoricalDispatch != nil && *outpoint == chainntnfs.ZeroOutPoint { + rewindHeight = ntfn.HistoricalDispatch.StartHeight } updateOptions = append(updateOptions, neutrino.Rewind(rewindHeight)) @@ -733,8 +722,7 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // scan of the chain, or if we already performed one like in the case of // output script spend requests, then we can return early as there's // nothing left for us to do. - if historicalDispatch == nil || - spendRequest.OutPoint == chainntnfs.ZeroOutPoint { + if ntfn.HistoricalDispatch == nil || *outpoint == chainntnfs.ZeroOutPoint { return ntfn.Event, nil } @@ -752,7 +740,7 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, currentHeight := uint32(n.bestBlock.Height) n.bestBlockMtx.RUnlock() - if currentHeight >= historicalDispatch.StartHeight { + if currentHeight >= ntfn.HistoricalDispatch.StartHeight { break } @@ -766,10 +754,10 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, spendReport, err := n.p2pNode.GetUtxo( neutrino.WatchInputs(inputToWatch), neutrino.StartBlock(&waddrmgr.BlockStamp{ - Height: int32(historicalDispatch.StartHeight), + Height: int32(ntfn.HistoricalDispatch.StartHeight), }), neutrino.EndBlock(&waddrmgr.BlockStamp{ - Height: int32(historicalDispatch.EndHeight), + Height: int32(ntfn.HistoricalDispatch.EndHeight), }), neutrino.QuitChan(n.quit), ) @@ -784,7 +772,7 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, if spendReport != nil && spendReport.SpendingTx != nil { spendingTxHash := spendReport.SpendingTx.TxHash() spendDetails = &chainntnfs.SpendDetail{ - SpentOutPoint: &spendRequest.OutPoint, + SpentOutPoint: outpoint, SpenderTxHash: &spendingTxHash, SpendingTx: spendReport.SpendingTx, SpenderInputIndex: spendReport.SpendingInputIndex, @@ -796,7 +784,9 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // not, we'll mark our historical rescan as complete to ensure the // outpoint's spend hint gets updated upon connected/disconnected // blocks. - err = n.txNotifier.UpdateSpendDetails(spendRequest, spendDetails) + err = n.txNotifier.UpdateSpendDetails( + ntfn.HistoricalDispatch.SpendRequest, spendDetails, + ) if err != nil { chainntnfs.Log.Errorf("Failed to update spend details: %v", err) return diff --git a/chainntnfs/txnotifier.go b/chainntnfs/txnotifier.go index 5e503f217..82961ab89 100644 --- a/chainntnfs/txnotifier.go +++ b/chainntnfs/txnotifier.go @@ -415,13 +415,33 @@ type HistoricalSpendDispatch struct { EndHeight uint32 } +// SpendRegistration encompasses all of the information required for callers to +// retrieve details about a spend event. +type SpendRegistration struct { + // Event contains references to the channels that the notifications are + // to be sent over. + Event *SpendEvent + + // HistoricalDispatch, if non-nil, signals to the client who registered + // the notification that they are responsible for attempting to manually + // rescan blocks for the txid/output script between the start and end + // heights. + HistoricalDispatch *HistoricalSpendDispatch + + // Height is the height of the TxNotifier at the time the spend + // notification was registered. This can be used so that backends can + // request to be notified of spends from this point forwards. + Height uint32 +} + // TxNotifier is a struct responsible for delivering transaction notifications // to subscribers. These notifications can be of two different types: // transaction/output script confirmations and/or outpoint/output script spends. // The TxNotifier will watch the blockchain as new blocks come in, in order to // satisfy its client requests. type TxNotifier struct { - confClientCounter uint64 // To be used atomically. + confClientCounter uint64 // To be used atomically. + spendClientCounter uint64 // To be used atomically. // currentHeight is the height of the tracked blockchain. It is used to // determine the number of confirmations a tx has and ensure blocks are @@ -885,29 +905,50 @@ func (n *TxNotifier) dispatchConfDetails( return nil } +// newSpendNtfn validates all of the parameters required to successfully create +// and register a spend notification. +func (n *TxNotifier) newSpendNtfn(outpoint *wire.OutPoint, + pkScript []byte, heightHint uint32) (*SpendNtfn, error) { + + spendRequest, err := NewSpendRequest(outpoint, pkScript) + if err != nil { + return nil, err + } + + spendID := atomic.AddUint64(&n.spendClientCounter, 1) + return &SpendNtfn{ + SpendID: spendID, + SpendRequest: spendRequest, + Event: NewSpendEvent(func() { + n.CancelSpend(spendRequest, spendID) + }), + HeightHint: heightHint, + }, nil +} + // RegisterSpend handles a new spend notification request. The client will be // notified once the outpoint/output script is detected as spent within the // chain. // -// The registration succeeds if no error is returned. If the returned -// HistoricalSpendDisaptch is non-nil, the caller is responsible for attempting -// to determine whether the outpoint/output script has been spent between the -// start and end heights. The notifier's current height is also returned so that -// backends can request to be notified of spends from this point forwards. -// // NOTE: If the outpoint/output script has already been spent within the chain // before the notifier's current tip, the spend details must be provided with // the UpdateSpendDetails method, otherwise we will wait for the outpoint/output // script to be spent at tip, even though it already has. -func (n *TxNotifier) RegisterSpend(ntfn *SpendNtfn) (*HistoricalSpendDispatch, - uint32, error) { +func (n *TxNotifier) RegisterSpend(outpoint *wire.OutPoint, pkScript []byte, + heightHint uint32) (*SpendRegistration, error) { select { case <-n.quit: - return nil, 0, ErrTxNotifierExiting + return nil, ErrTxNotifierExiting default: } + // We'll start by performing a series of validation checks. + ntfn, err := n.newSpendNtfn(outpoint, pkScript, heightHint) + if err != nil { + return nil, err + } + // Before proceeding to register the notification, we'll query our spend // hint cache to determine whether a better one exists. startHeight := ntfn.HeightHint @@ -953,9 +994,16 @@ func (n *TxNotifier) RegisterSpend(ntfn *SpendNtfn) (*HistoricalSpendDispatch, "registration since rescan has finished", ntfn.SpendRequest) - return nil, n.currentHeight, n.dispatchSpendDetails( - ntfn, spendSet.details, - ) + err := n.dispatchSpendDetails(ntfn, spendSet.details) + if err != nil { + return nil, err + } + + return &SpendRegistration{ + Event: ntfn.Event, + HistoricalDispatch: nil, + Height: n.currentHeight, + }, nil // If there is an active rescan to determine whether the request has // been spent, then we won't trigger another one. @@ -963,7 +1011,11 @@ func (n *TxNotifier) RegisterSpend(ntfn *SpendNtfn) (*HistoricalSpendDispatch, Log.Debugf("Waiting for pending rescan to finish before "+ "notifying %v at tip", ntfn.SpendRequest) - return nil, n.currentHeight, nil + return &SpendRegistration{ + Event: ntfn.Event, + HistoricalDispatch: nil, + Height: n.currentHeight, + }, nil // Otherwise, we'll fall through and let the caller know that a rescan // should be dispatched to determine whether the request has already @@ -983,7 +1035,11 @@ func (n *TxNotifier) RegisterSpend(ntfn *SpendNtfn) (*HistoricalSpendDispatch, // spend hints for this request get updated upon // connected/disconnected blocks. spendSet.rescanStatus = rescanComplete - return nil, n.currentHeight, nil + return &SpendRegistration{ + Event: ntfn.Event, + HistoricalDispatch: nil, + Height: n.currentHeight, + }, nil } // We'll set the rescan status to pending to ensure subsequent @@ -993,11 +1049,15 @@ func (n *TxNotifier) RegisterSpend(ntfn *SpendNtfn) (*HistoricalSpendDispatch, Log.Debugf("Dispatching historical spend rescan for %v", ntfn.SpendRequest) - return &HistoricalSpendDispatch{ - SpendRequest: ntfn.SpendRequest, - StartHeight: startHeight, - EndHeight: n.currentHeight, - }, n.currentHeight, nil + return &SpendRegistration{ + Event: ntfn.Event, + HistoricalDispatch: &HistoricalSpendDispatch{ + SpendRequest: ntfn.SpendRequest, + StartHeight: startHeight, + EndHeight: n.currentHeight, + }, + Height: n.currentHeight, + }, nil } // CancelSpend cancels an existing request for a spend notification of an diff --git a/chainntnfs/txnotifier_test.go b/chainntnfs/txnotifier_test.go index ecfc327f7..f79fd59d9 100644 --- a/chainntnfs/txnotifier_test.go +++ b/chainntnfs/txnotifier_test.go @@ -479,14 +479,9 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) { // We'll start off by registering for a spend notification of an // outpoint. - ntfn := &chainntnfs.SpendNtfn{ - SpendRequest: chainntnfs.SpendRequest{ - OutPoint: wire.OutPoint{Index: 1}, - PkScript: testScript, - }, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(ntfn); err != nil { + op := wire.OutPoint{Index: 1} + ntfn, err := n.RegisterSpend(&op, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -503,14 +498,14 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) { // spend notification. spendTx := wire.NewMsgTx(2) spendTx.AddTxIn(&wire.TxIn{ - PreviousOutPoint: ntfn.OutPoint, + PreviousOutPoint: op, SignatureScript: testSigScript, }) spendTxHash := spendTx.TxHash() block := btcutil.NewBlock(&wire.MsgBlock{ Transactions: []*wire.MsgTx{spendTx}, }) - err := n.ConnectTip(block.Hash(), 11, block.Transactions()) + err = n.ConnectTip(block.Hash(), 11, block.Transactions()) if err != nil { t.Fatalf("unable to connect block: %v", err) } @@ -519,7 +514,7 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) { } expectedSpendDetails := &chainntnfs.SpendDetail{ - SpentOutPoint: &ntfn.OutPoint, + SpentOutPoint: &op, SpenderTxHash: &spendTxHash, SpendingTx: spendTx, SpenderInputIndex: 0, @@ -593,11 +588,8 @@ 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{ - SpendRequest: chainntnfs.SpendRequest{OutPoint: spentOutpoint}, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(ntfn); err != nil { + ntfn, err := n.RegisterSpend(&spentOutpoint, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -611,7 +603,9 @@ 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.SpendRequest, expectedSpendDetails) + err = n.UpdateSpendDetails( + ntfn.HistoricalDispatch.SpendRequest, expectedSpendDetails, + ) if err != nil { t.Fatalf("unable to update spend details: %v", err) } @@ -721,35 +715,23 @@ 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. - spendRequest := chainntnfs.SpendRequest{ - OutPoint: wire.OutPoint{Index: 1}, - } - ntfn1 := &chainntnfs.SpendNtfn{ - SpendID: 0, - SpendRequest: spendRequest, - Event: chainntnfs.NewSpendEvent(nil), - } - historicalDispatch1, _, err := n.RegisterSpend(ntfn1) + op := wire.OutPoint{Index: 1} + ntfn1, err := n.RegisterSpend(&op, testRawScript, 1) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } - if historicalDispatch1 == nil { + if ntfn1.HistoricalDispatch == nil { t.Fatal("expected to receive historical dispatch request") } // We'll register another spend notification for the same outpoint. This // should not request a historical spend rescan since the first one is // still pending. - ntfn2 := &chainntnfs.SpendNtfn{ - SpendID: 1, - SpendRequest: spendRequest, - Event: chainntnfs.NewSpendEvent(nil), - } - historicalDispatch2, _, err := n.RegisterSpend(ntfn2) + ntfn2, err := n.RegisterSpend(&op, testRawScript, 1) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } - if historicalDispatch2 != nil { + if ntfn2.HistoricalDispatch != nil { t.Fatal("received unexpected historical rescan request") } @@ -758,27 +740,24 @@ func TestTxNotifierMultipleHistoricalSpendRescans(t *testing.T) { // historical rescan request since the confirmation details should be // cached. spendDetails := &chainntnfs.SpendDetail{ - SpentOutPoint: &ntfn2.OutPoint, + SpentOutPoint: &op, SpenderTxHash: &chainntnfs.ZeroHash, SpendingTx: wire.NewMsgTx(2), SpenderInputIndex: 0, SpendingHeight: startingHeight - 1, } - err = n.UpdateSpendDetails(ntfn2.SpendRequest, spendDetails) + err = n.UpdateSpendDetails( + ntfn1.HistoricalDispatch.SpendRequest, spendDetails, + ) if err != nil { t.Fatalf("unable to update spend details: %v", err) } - ntfn3 := &chainntnfs.SpendNtfn{ - SpendID: 2, - SpendRequest: spendRequest, - Event: chainntnfs.NewSpendEvent(nil), - } - historicalDispatch3, _, err := n.RegisterSpend(ntfn3) + ntfn3, err := n.RegisterSpend(&op, testRawScript, 1) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } - if historicalDispatch3 != nil { + if ntfn3.HistoricalDispatch != nil { t.Fatal("received unexpected historical rescan request") } } @@ -872,19 +851,14 @@ 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) + op := wire.OutPoint{Index: 1} + spendNtfns := make([]*chainntnfs.SpendRegistration, numNtfns) for i := uint64(0); i < numNtfns; i++ { - spendNtfns[i] = &chainntnfs.SpendNtfn{ - SpendID: i, - SpendRequest: spendRequest, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(spendNtfns[i]); err != nil { + ntfn, err := n.RegisterSpend(&op, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend ntfn #%d: %v", i, err) } + spendNtfns[i] = ntfn } // Ensure none of them have received the spend details. @@ -901,13 +875,15 @@ func TestTxNotifierMultipleHistoricalNtfns(t *testing.T) { // following spend details. We'll let the notifier know so that it can // stop watching at tip. expectedSpendDetails := &chainntnfs.SpendDetail{ - SpentOutPoint: &spendNtfns[0].OutPoint, + SpentOutPoint: &op, SpenderTxHash: &chainntnfs.ZeroHash, SpendingTx: wire.NewMsgTx(2), SpenderInputIndex: 0, SpendingHeight: startingHeight - 1, } - err = n.UpdateSpendDetails(spendNtfns[0].SpendRequest, expectedSpendDetails) + err = n.UpdateSpendDetails( + spendNtfns[0].HistoricalDispatch.SpendRequest, expectedSpendDetails, + ) if err != nil { t.Fatalf("unable to update spend details: %v", err) } @@ -928,16 +904,11 @@ func TestTxNotifierMultipleHistoricalNtfns(t *testing.T) { // cached, we'll register another client for the same outpoint. We // should not see a historical rescan request and the spend notification // should come through immediately. - extraSpendNtfn := &chainntnfs.SpendNtfn{ - SpendID: numNtfns + 1, - SpendRequest: spendRequest, - Event: chainntnfs.NewSpendEvent(nil), - } - historicalSpendRescan, _, err := n.RegisterSpend(extraSpendNtfn) + extraSpendNtfn, err := n.RegisterSpend(&op, testRawScript, 1) if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } - if historicalSpendRescan != nil { + if extraSpendNtfn.HistoricalDispatch != nil { t.Fatal("received unexpected historical rescan request") } @@ -1035,26 +1006,15 @@ func TestTxNotifierCancelSpend(t *testing.T) { // We'll register two notification requests. Only the second one will be // canceled. - ntfn1 := &chainntnfs.SpendNtfn{ - SpendID: 0, - SpendRequest: chainntnfs.SpendRequest{ - OutPoint: wire.OutPoint{Index: 1}, - PkScript: testScript, - }, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(ntfn1); err != nil { + op1 := wire.OutPoint{Index: 1} + ntfn1, err := n.RegisterSpend(&op1, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } - ntfn2 := &chainntnfs.SpendNtfn{ - SpendID: 1, - SpendRequest: chainntnfs.SpendRequest{ - OutPoint: wire.OutPoint{Index: 2}, - }, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(ntfn2); err != nil { + op2 := wire.OutPoint{Index: 2} + ntfn2, err := n.RegisterSpend(&op2, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -1062,12 +1022,12 @@ func TestTxNotifierCancelSpend(t *testing.T) { // block containing it. spendTx := wire.NewMsgTx(2) spendTx.AddTxIn(&wire.TxIn{ - PreviousOutPoint: ntfn1.OutPoint, + PreviousOutPoint: op1, SignatureScript: testSigScript, }) spendTxHash := spendTx.TxHash() expectedSpendDetails := &chainntnfs.SpendDetail{ - SpentOutPoint: &ntfn1.OutPoint, + SpentOutPoint: &op1, SpenderTxHash: &spendTxHash, SpendingTx: spendTx, SpenderInputIndex: 0, @@ -1080,9 +1040,9 @@ 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.SpendRequest, ntfn2.SpendID) + n.CancelSpend(ntfn2.HistoricalDispatch.SpendRequest, 2) - err := n.ConnectTip(block.Hash(), startingHeight+1, block.Transactions()) + err = n.ConnectTip(block.Hash(), startingHeight+1, block.Transactions()) if err != nil { t.Fatalf("unable to connect block: %v", err) } @@ -1404,35 +1364,29 @@ 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. - spendRequest1 := chainntnfs.SpendRequest{ - OutPoint: wire.OutPoint{Index: 1}, - PkScript: testScript, - } + op1 := wire.OutPoint{Index: 1} spendTx1 := wire.NewMsgTx(2) spendTx1.AddTxIn(&wire.TxIn{ - PreviousOutPoint: spendRequest1.OutPoint, + PreviousOutPoint: op1, SignatureScript: testSigScript, }) spendTxHash1 := spendTx1.TxHash() expectedSpendDetails1 := &chainntnfs.SpendDetail{ - SpentOutPoint: &spendRequest1.OutPoint, + SpentOutPoint: &op1, SpenderTxHash: &spendTxHash1, SpendingTx: spendTx1, SpenderInputIndex: 0, SpendingHeight: startingHeight + 1, } - spendRequest2 := chainntnfs.SpendRequest{ - OutPoint: wire.OutPoint{Index: 2}, - PkScript: testScript, - } + op2 := wire.OutPoint{Index: 2} spendTx2 := wire.NewMsgTx(2) spendTx2.AddTxIn(&wire.TxIn{ PreviousOutPoint: chainntnfs.ZeroOutPoint, SignatureScript: testSigScript, }) spendTx2.AddTxIn(&wire.TxIn{ - PreviousOutPoint: spendRequest2.OutPoint, + PreviousOutPoint: op2, SignatureScript: testSigScript, }) spendTxHash2 := spendTx2.TxHash() @@ -1441,7 +1395,7 @@ func TestTxNotifierSpendReorg(t *testing.T) { // different height, so we'll need to construct the spend details for // before and after the reorg. expectedSpendDetails2BeforeReorg := chainntnfs.SpendDetail{ - SpentOutPoint: &spendRequest2.OutPoint, + SpentOutPoint: &op2, SpenderTxHash: &spendTxHash2, SpendingTx: spendTx2, SpenderInputIndex: 1, @@ -1454,21 +1408,13 @@ func TestTxNotifierSpendReorg(t *testing.T) { expectedSpendDetails2AfterReorg.SpendingHeight++ // We'll register for a spend notification for each outpoint above. - ntfn1 := &chainntnfs.SpendNtfn{ - SpendID: 78, - SpendRequest: spendRequest1, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(ntfn1); err != nil { + ntfn1, err := n.RegisterSpend(&op1, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } - ntfn2 := &chainntnfs.SpendNtfn{ - SpendID: 21, - SpendRequest: spendRequest2, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(ntfn2); err != nil { + ntfn2, err := n.RegisterSpend(&op2, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -1477,7 +1423,7 @@ func TestTxNotifierSpendReorg(t *testing.T) { block1 := btcutil.NewBlock(&wire.MsgBlock{ Transactions: []*wire.MsgTx{spendTx1}, }) - err := n.ConnectTip(block1.Hash(), startingHeight+1, block1.Transactions()) + err = n.ConnectTip(block1.Hash(), startingHeight+1, block1.Transactions()) if err != nil { t.Fatalf("unable to connect block: %v", err) } @@ -1836,40 +1782,27 @@ func TestTxNotifierSpendHintCache(t *testing.T) { ) // Create two test outpoints and register them for spend notifications. - ntfn1 := &chainntnfs.SpendNtfn{ - SpendID: 1, - SpendRequest: chainntnfs.SpendRequest{ - OutPoint: wire.OutPoint{Index: 1}, - PkScript: testScript, - }, - Event: chainntnfs.NewSpendEvent(nil), - } - ntfn2 := &chainntnfs.SpendNtfn{ - SpendID: 2, - SpendRequest: chainntnfs.SpendRequest{ - OutPoint: wire.OutPoint{Index: 2}, - PkScript: testScript, - }, - Event: chainntnfs.NewSpendEvent(nil), - } - - if _, _, err := n.RegisterSpend(ntfn1); err != nil { + op1 := wire.OutPoint{Index: 1} + ntfn1, err := n.RegisterSpend(&op1, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend for op1: %v", err) } - if _, _, err := n.RegisterSpend(ntfn2); err != nil { + op2 := wire.OutPoint{Index: 2} + ntfn2, err := n.RegisterSpend(&op2, testRawScript, 1) + if 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(ntfn1.SpendRequest) + _, err = hintCache.QuerySpendHint(ntfn1.HistoricalDispatch.SpendRequest) if err != chainntnfs.ErrSpendHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "expected: %v, got %v", chainntnfs.ErrSpendHintNotFound, err) } - _, err = hintCache.QuerySpendHint(ntfn2.SpendRequest) + _, err = hintCache.QuerySpendHint(ntfn2.HistoricalDispatch.SpendRequest) if err != chainntnfs.ErrSpendHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "expected: %v, got %v", chainntnfs.ErrSpendHintNotFound, @@ -1891,13 +1824,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(ntfn1.SpendRequest) + _, err = hintCache.QuerySpendHint(ntfn1.HistoricalDispatch.SpendRequest) if err != chainntnfs.ErrSpendHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "expected: %v, got %v", chainntnfs.ErrSpendHintNotFound, err) } - _, err = hintCache.QuerySpendHint(ntfn2.SpendRequest) + _, err = hintCache.QuerySpendHint(ntfn2.HistoricalDispatch.SpendRequest) if err != chainntnfs.ErrSpendHintNotFound { t.Fatalf("unexpected error when querying for height hint "+ "expected: %v, got %v", chainntnfs.ErrSpendHintNotFound, @@ -1907,10 +1840,12 @@ 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.SpendRequest, nil); err != nil { + err = n.UpdateSpendDetails(ntfn1.HistoricalDispatch.SpendRequest, nil) + if err != nil { t.Fatalf("unable to update spend details: %v", err) } - if err := n.UpdateSpendDetails(ntfn2.SpendRequest, nil); err != nil { + err = n.UpdateSpendDetails(ntfn2.HistoricalDispatch.SpendRequest, nil) + if err != nil { t.Fatalf("unable to update spend details: %v", err) } @@ -1918,7 +1853,7 @@ func TestTxNotifierSpendHintCache(t *testing.T) { // of the first outpoint. spendTx1 := wire.NewMsgTx(2) spendTx1.AddTxIn(&wire.TxIn{ - PreviousOutPoint: ntfn1.OutPoint, + PreviousOutPoint: op1, SignatureScript: testSigScript, }) block1 := btcutil.NewBlock(&wire.MsgBlock{ @@ -1935,14 +1870,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.SpendRequest) + op1Hint, err := hintCache.QuerySpendHint(ntfn1.HistoricalDispatch.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.SpendRequest) + op2Hint, err := hintCache.QuerySpendHint(ntfn2.HistoricalDispatch.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op2: %v", err) } @@ -1953,7 +1888,7 @@ 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, + PreviousOutPoint: op2, SignatureScript: testSigScript, }) block2 := btcutil.NewBlock(&wire.MsgBlock{ @@ -1970,14 +1905,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.SpendRequest) + op1Hint, err = hintCache.QuerySpendHint(ntfn1.HistoricalDispatch.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.SpendRequest) + op2Hint, err = hintCache.QuerySpendHint(ntfn2.HistoricalDispatch.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op2: %v", err) } @@ -1995,14 +1930,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.SpendRequest) + op1Hint, err = hintCache.QuerySpendHint(ntfn1.HistoricalDispatch.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.SpendRequest) + op2Hint, err = hintCache.QuerySpendHint(ntfn2.HistoricalDispatch.SpendRequest) if err != nil { t.Fatalf("unable to query for spend hint of op2: %v", err) } @@ -2027,16 +1962,8 @@ func TestTxNotifierNtfnDone(t *testing.T) { if err != nil { t.Fatalf("unable to register conf ntfn: %v", err) } - - spendNtfn := &chainntnfs.SpendNtfn{ - SpendID: 2, - SpendRequest: chainntnfs.SpendRequest{ - OutPoint: chainntnfs.ZeroOutPoint, - PkScript: testScript, - }, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(spendNtfn); err != nil { + spendNtfn, err := n.RegisterSpend(&chainntnfs.ZeroOutPoint, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend: %v", err) } @@ -2165,13 +2092,8 @@ func TestTxNotifierTearDown(t *testing.T) { if err != nil { t.Fatalf("unable to register conf ntfn: %v", err) } - - spendNtfn := &chainntnfs.SpendNtfn{ - SpendID: 1, - SpendRequest: chainntnfs.SpendRequest{OutPoint: chainntnfs.ZeroOutPoint}, - Event: chainntnfs.NewSpendEvent(nil), - } - if _, _, err := n.RegisterSpend(spendNtfn); err != nil { + spendNtfn, err := n.RegisterSpend(&chainntnfs.ZeroOutPoint, testRawScript, 1) + if err != nil { t.Fatalf("unable to register spend ntfn: %v", err) } @@ -2212,7 +2134,8 @@ func TestTxNotifierTearDown(t *testing.T) { if err == nil { t.Fatal("expected confirmation registration to fail") } - if _, _, err := n.RegisterSpend(spendNtfn); err == nil { + _, err = n.RegisterSpend(&chainntnfs.ZeroOutPoint, testRawScript, 1) + if err == nil { t.Fatal("expected spend registration to fail") } }