chainntnfs: refactor common registration code within RegisterSpendNtfn
This commit is contained in:
parent
5089311ca1
commit
7821eb6ffb
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/btcjson"
|
"github.com/btcsuite/btcd/btcjson"
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/btcsuite/btcwallet/chain"
|
"github.com/btcsuite/btcwallet/chain"
|
||||||
@ -39,7 +40,6 @@ type chainUpdate struct {
|
|||||||
// chain client. Multiple concurrent clients are supported. All notifications
|
// chain client. Multiple concurrent clients are supported. All notifications
|
||||||
// are achieved via non-blocking sends on client channels.
|
// are achieved via non-blocking sends on client channels.
|
||||||
type BitcoindNotifier struct {
|
type BitcoindNotifier struct {
|
||||||
spendClientCounter uint64 // To be used atomically.
|
|
||||||
epochClientCounter uint64 // To be used atomically.
|
epochClientCounter uint64 // To be used atomically.
|
||||||
|
|
||||||
started int32 // 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,
|
func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
||||||
pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
|
pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
|
||||||
|
|
||||||
// First, we'll construct a spend notification request and hand it off
|
// Register the conf notification with the TxNotifier. A non-nil value
|
||||||
// to the txNotifier.
|
// for `dispatch` will be returned if we are required to perform a
|
||||||
spendID := atomic.AddUint64(&b.spendClientCounter, 1)
|
// manual scan for the confirmation. Otherwise the notifier will begin
|
||||||
spendRequest, err := chainntnfs.NewSpendRequest(outpoint, pkScript)
|
// watching at tip for the transaction to confirm.
|
||||||
if err != nil {
|
ntfn, err := b.txNotifier.RegisterSpend(outpoint, pkScript, heightHint)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -640,17 +628,18 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
|||||||
// outpoint/output script as spent.
|
// outpoint/output script as spent.
|
||||||
//
|
//
|
||||||
// TODO(wilmer): use LoadFilter API instead.
|
// TODO(wilmer): use LoadFilter API instead.
|
||||||
if spendRequest.OutPoint == chainntnfs.ZeroOutPoint {
|
if outpoint == nil || *outpoint == chainntnfs.ZeroOutPoint {
|
||||||
addr, err := spendRequest.PkScript.Address(b.chainParams)
|
_, addrs, _, err := txscript.ExtractPkScriptAddrs(
|
||||||
|
pkScript, b.chainParams,
|
||||||
|
)
|
||||||
if err != nil {
|
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 {
|
if err := b.chainConn.NotifyReceived(addrs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ops := []*wire.OutPoint{&spendRequest.OutPoint}
|
ops := []*wire.OutPoint{outpoint}
|
||||||
if err := b.chainConn.NotifySpent(ops); err != nil {
|
if err := b.chainConn.NotifySpent(ops); err != nil {
|
||||||
return nil, err
|
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
|
// 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
|
// scan of the chain, then we can return early as there's nothing left
|
||||||
// for us to do.
|
// for us to do.
|
||||||
if historicalDispatch == nil {
|
if ntfn.HistoricalDispatch == nil {
|
||||||
return ntfn.Event, 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,
|
// 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
|
// rather than an outpoint, as there aren't any additional checks we can
|
||||||
// make for scripts.
|
// make for scripts.
|
||||||
if spendRequest.OutPoint == chainntnfs.ZeroOutPoint {
|
if ntfn.HistoricalDispatch.OutPoint == chainntnfs.ZeroOutPoint {
|
||||||
select {
|
select {
|
||||||
case b.notificationRegistry <- historicalDispatch:
|
case b.notificationRegistry <- ntfn.HistoricalDispatch:
|
||||||
case <-b.quit:
|
case <-b.quit:
|
||||||
return nil, chainntnfs.ErrChainNotifierShuttingDown
|
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
|
// 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
|
// the outpoint has been spent. If it hasn't, we can return to the
|
||||||
// caller as well.
|
// caller as well.
|
||||||
txOut, err := b.chainConn.GetTxOut(
|
txOut, err := b.chainConn.GetTxOut(&outpoint.Hash, outpoint.Index, true)
|
||||||
&spendRequest.OutPoint.Hash, spendRequest.OutPoint.Index, true,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if txOut != nil {
|
if txOut != nil {
|
||||||
// We'll let the txNotifier know the outpoint is still unspent
|
// We'll let the txNotifier know the outpoint is still unspent
|
||||||
// in order to begin updating its spend hint.
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// index (if enabled) to determine if we have a better rescan starting
|
||||||
// height. We can do this as the GetRawTransaction call will return the
|
// height. We can do this as the GetRawTransaction call will return the
|
||||||
// hash of the block it was included in within the chain.
|
// 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 {
|
if err != nil {
|
||||||
// Avoid returning an error if the transaction was not found to
|
// Avoid returning an error if the transaction was not found to
|
||||||
// proceed with fallback methods.
|
// proceed with fallback methods.
|
||||||
jsonErr, ok := err.(*btcjson.RPCError)
|
jsonErr, ok := err.(*btcjson.RPCError)
|
||||||
if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo {
|
if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo {
|
||||||
return nil, fmt.Errorf("unable to query for txid %v: %v",
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if uint32(blockHeight) > historicalDispatch.StartHeight {
|
if uint32(blockHeight) > ntfn.HistoricalDispatch.StartHeight {
|
||||||
historicalDispatch.StartHeight = uint32(blockHeight)
|
ntfn.HistoricalDispatch.StartHeight = uint32(blockHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we've determined the starting point of our rescan, we can
|
// Now that we've determined the starting point of our rescan, we can
|
||||||
// dispatch it and return.
|
// dispatch it and return.
|
||||||
select {
|
select {
|
||||||
case b.notificationRegistry <- historicalDispatch:
|
case b.notificationRegistry <- ntfn.HistoricalDispatch:
|
||||||
case <-b.quit:
|
case <-b.quit:
|
||||||
return nil, chainntnfs.ErrChainNotifierShuttingDown
|
return nil, chainntnfs.ErrChainNotifierShuttingDown
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/rpcclient"
|
"github.com/btcsuite/btcd/rpcclient"
|
||||||
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
@ -50,7 +51,6 @@ type txUpdate struct {
|
|||||||
// notifications. Multiple concurrent clients are supported. All notifications
|
// notifications. Multiple concurrent clients are supported. All notifications
|
||||||
// are achieved via non-blocking sends on client channels.
|
// are achieved via non-blocking sends on client channels.
|
||||||
type BtcdNotifier struct {
|
type BtcdNotifier struct {
|
||||||
spendClientCounter uint64 // To be used atomically.
|
|
||||||
epochClientCounter uint64 // To be used atomically.
|
epochClientCounter uint64 // To be used atomically.
|
||||||
|
|
||||||
started int32 // 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,
|
func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
||||||
pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
|
pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
|
||||||
|
|
||||||
// First, we'll construct a spend notification request and hand it off
|
// Register the conf notification with the TxNotifier. A non-nil value
|
||||||
// to the txNotifier.
|
// for `dispatch` will be returned if we are required to perform a
|
||||||
spendID := atomic.AddUint64(&b.spendClientCounter, 1)
|
// manual scan for the confirmation. Otherwise the notifier will begin
|
||||||
spendRequest, err := chainntnfs.NewSpendRequest(outpoint, pkScript)
|
// watching at tip for the transaction to confirm.
|
||||||
if err != nil {
|
ntfn, err := b.txNotifier.RegisterSpend(outpoint, pkScript, heightHint)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -676,17 +664,18 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
|||||||
// outpoint/output script as spent.
|
// outpoint/output script as spent.
|
||||||
//
|
//
|
||||||
// TODO(wilmer): use LoadFilter API instead.
|
// TODO(wilmer): use LoadFilter API instead.
|
||||||
if spendRequest.OutPoint == chainntnfs.ZeroOutPoint {
|
if outpoint == nil || *outpoint == chainntnfs.ZeroOutPoint {
|
||||||
addr, err := spendRequest.PkScript.Address(b.chainParams)
|
_, addrs, _, err := txscript.ExtractPkScriptAddrs(
|
||||||
|
pkScript, b.chainParams,
|
||||||
|
)
|
||||||
if err != nil {
|
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 {
|
if err := b.chainConn.NotifyReceived(addrs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ops := []*wire.OutPoint{&spendRequest.OutPoint}
|
ops := []*wire.OutPoint{outpoint}
|
||||||
if err := b.chainConn.NotifySpent(ops); err != nil {
|
if err := b.chainConn.NotifySpent(ops); err != nil {
|
||||||
return nil, err
|
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
|
// 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
|
// scan of the chain, then we can return early as there's nothing left
|
||||||
// for us to do.
|
// for us to do.
|
||||||
if historicalDispatch == nil {
|
if ntfn.HistoricalDispatch == nil {
|
||||||
return ntfn.Event, 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,
|
// 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
|
// rather than an outpoint, as there aren't any additional checks we can
|
||||||
// make for scripts.
|
// make for scripts.
|
||||||
if spendRequest.OutPoint == chainntnfs.ZeroOutPoint {
|
if outpoint == nil || *outpoint == chainntnfs.ZeroOutPoint {
|
||||||
startHash, err := b.chainConn.GetBlockHash(
|
startHash, err := b.chainConn.GetBlockHash(
|
||||||
int64(historicalDispatch.StartHeight),
|
int64(ntfn.HistoricalDispatch.StartHeight),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(wilmer): add retry logic if rescan fails?
|
// 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 {
|
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)
|
asyncResult := b.chainConn.RescanAsync(startHash, addrs, nil)
|
||||||
go func() {
|
go func() {
|
||||||
if rescanErr := asyncResult.Receive(); rescanErr != nil {
|
if rescanErr := asyncResult.Receive(); rescanErr != nil {
|
||||||
chainntnfs.Log.Errorf("Rescan to determine "+
|
chainntnfs.Log.Errorf("Rescan to determine "+
|
||||||
"the spend details of %v failed: %v",
|
"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
|
// 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
|
// the outpoint has been spent. If it hasn't, we can return to the
|
||||||
// caller as well.
|
// caller as well.
|
||||||
txOut, err := b.chainConn.GetTxOut(
|
txOut, err := b.chainConn.GetTxOut(&outpoint.Hash, outpoint.Index, true)
|
||||||
&spendRequest.OutPoint.Hash, spendRequest.OutPoint.Index, true,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if txOut != nil {
|
if txOut != nil {
|
||||||
// We'll let the txNotifier know the outpoint is still unspent
|
// We'll let the txNotifier know the outpoint is still unspent
|
||||||
// in order to begin updating its spend hint.
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// set, we'll determine when it happened by scanning the chain. We'll
|
||||||
// begin by fetching the block hash of our starting height.
|
// begin by fetching the block hash of our starting height.
|
||||||
startHash, err := b.chainConn.GetBlockHash(
|
startHash, err := b.chainConn.GetBlockHash(
|
||||||
int64(historicalDispatch.StartHeight),
|
int64(ntfn.HistoricalDispatch.StartHeight),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to get block hash for height "+
|
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
|
// As a minimal optimization, we'll query the backend's transaction
|
||||||
// index (if enabled) to determine if we have a better rescan starting
|
// index (if enabled) to determine if we have a better rescan starting
|
||||||
// height. We can do this as the GetRawTransaction call will return the
|
// height. We can do this as the GetRawTransaction call will return the
|
||||||
// hash of the block it was included in within the chain.
|
// 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 {
|
if err != nil {
|
||||||
// Avoid returning an error if the transaction was not found to
|
// Avoid returning an error if the transaction was not found to
|
||||||
// proceed with fallback methods.
|
// proceed with fallback methods.
|
||||||
jsonErr, ok := err.(*btcjson.RPCError)
|
jsonErr, ok := err.(*btcjson.RPCError)
|
||||||
if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo {
|
if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo {
|
||||||
return nil, fmt.Errorf("unable to query for txid %v: %v",
|
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)
|
"block %v: %v", blockHash, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if uint32(blockHeader.Height) > historicalDispatch.StartHeight {
|
if uint32(blockHeader.Height) > ntfn.HistoricalDispatch.StartHeight {
|
||||||
startHash, err = b.chainConn.GetBlockHash(
|
startHash, err = b.chainConn.GetBlockHash(
|
||||||
int64(blockHeader.Height),
|
int64(blockHeader.Height),
|
||||||
)
|
)
|
||||||
@ -824,13 +816,12 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
|||||||
//
|
//
|
||||||
// TODO(wilmer): add retry logic if rescan fails?
|
// TODO(wilmer): add retry logic if rescan fails?
|
||||||
asyncResult := b.chainConn.RescanAsync(
|
asyncResult := b.chainConn.RescanAsync(
|
||||||
startHash, nil, []*wire.OutPoint{&spendRequest.OutPoint},
|
startHash, nil, []*wire.OutPoint{outpoint},
|
||||||
)
|
)
|
||||||
go func() {
|
go func() {
|
||||||
if rescanErr := asyncResult.Receive(); rescanErr != nil {
|
if rescanErr := asyncResult.Receive(); rescanErr != nil {
|
||||||
chainntnfs.Log.Errorf("Rescan to determine the spend "+
|
chainntnfs.Log.Errorf("Rescan to determine the spend "+
|
||||||
"details of %v failed: %v", spendRequest,
|
"details of %v failed: %v", outpoint, rescanErr)
|
||||||
rescanErr)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ const (
|
|||||||
// TODO(roasbeef): heavily consolidate with NeutrinoNotifier code
|
// TODO(roasbeef): heavily consolidate with NeutrinoNotifier code
|
||||||
// * maybe combine into single package?
|
// * maybe combine into single package?
|
||||||
type NeutrinoNotifier struct {
|
type NeutrinoNotifier struct {
|
||||||
spendClientCounter uint64 // To be used atomically.
|
|
||||||
epochClientCounter uint64 // To be used atomically.
|
epochClientCounter uint64 // To be used atomically.
|
||||||
|
|
||||||
started int32 // 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,
|
func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
||||||
pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
|
pkScript []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
|
||||||
|
|
||||||
// First, we'll construct a spend notification request and hand it off
|
// Register the conf notification with the TxNotifier. A non-nil value
|
||||||
// to the txNotifier.
|
// for `dispatch` will be returned if we are required to perform a
|
||||||
spendID := atomic.AddUint64(&n.spendClientCounter, 1)
|
// manual scan for the confirmation. Otherwise the notifier will begin
|
||||||
spendRequest, err := chainntnfs.NewSpendRequest(outpoint, pkScript)
|
// watching at tip for the transaction to confirm.
|
||||||
if err != nil {
|
ntfn, err := n.txNotifier.RegisterSpend(outpoint, pkScript, heightHint)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// We'll update our filter first to ensure we can immediately detect the
|
||||||
// spend at tip.
|
// spend at tip.
|
||||||
|
if outpoint == nil {
|
||||||
|
outpoint = &chainntnfs.ZeroOutPoint
|
||||||
|
}
|
||||||
inputToWatch := neutrino.InputWithScript{
|
inputToWatch := neutrino.InputWithScript{
|
||||||
OutPoint: spendRequest.OutPoint,
|
OutPoint: *outpoint,
|
||||||
PkScript: spendRequest.PkScript.Script(),
|
PkScript: pkScript,
|
||||||
}
|
}
|
||||||
updateOptions := []neutrino.UpdateOption{
|
updateOptions := []neutrino.UpdateOption{
|
||||||
neutrino.AddInputs(inputToWatch),
|
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
|
// 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
|
// we should perform a historical rescan and start from there, as we
|
||||||
// cannot do so with GetUtxo since it matches outpoints.
|
// cannot do so with GetUtxo since it matches outpoints.
|
||||||
rewindHeight := txNotifierTip
|
rewindHeight := ntfn.Height
|
||||||
if historicalDispatch != nil &&
|
if ntfn.HistoricalDispatch != nil && *outpoint == chainntnfs.ZeroOutPoint {
|
||||||
spendRequest.OutPoint == chainntnfs.ZeroOutPoint {
|
rewindHeight = ntfn.HistoricalDispatch.StartHeight
|
||||||
rewindHeight = historicalDispatch.StartHeight
|
|
||||||
}
|
}
|
||||||
updateOptions = append(updateOptions, neutrino.Rewind(rewindHeight))
|
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
|
// 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
|
// output script spend requests, then we can return early as there's
|
||||||
// nothing left for us to do.
|
// nothing left for us to do.
|
||||||
if historicalDispatch == nil ||
|
if ntfn.HistoricalDispatch == nil || *outpoint == chainntnfs.ZeroOutPoint {
|
||||||
spendRequest.OutPoint == chainntnfs.ZeroOutPoint {
|
|
||||||
return ntfn.Event, nil
|
return ntfn.Event, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,7 +740,7 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
|||||||
currentHeight := uint32(n.bestBlock.Height)
|
currentHeight := uint32(n.bestBlock.Height)
|
||||||
n.bestBlockMtx.RUnlock()
|
n.bestBlockMtx.RUnlock()
|
||||||
|
|
||||||
if currentHeight >= historicalDispatch.StartHeight {
|
if currentHeight >= ntfn.HistoricalDispatch.StartHeight {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,10 +754,10 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
|||||||
spendReport, err := n.p2pNode.GetUtxo(
|
spendReport, err := n.p2pNode.GetUtxo(
|
||||||
neutrino.WatchInputs(inputToWatch),
|
neutrino.WatchInputs(inputToWatch),
|
||||||
neutrino.StartBlock(&waddrmgr.BlockStamp{
|
neutrino.StartBlock(&waddrmgr.BlockStamp{
|
||||||
Height: int32(historicalDispatch.StartHeight),
|
Height: int32(ntfn.HistoricalDispatch.StartHeight),
|
||||||
}),
|
}),
|
||||||
neutrino.EndBlock(&waddrmgr.BlockStamp{
|
neutrino.EndBlock(&waddrmgr.BlockStamp{
|
||||||
Height: int32(historicalDispatch.EndHeight),
|
Height: int32(ntfn.HistoricalDispatch.EndHeight),
|
||||||
}),
|
}),
|
||||||
neutrino.QuitChan(n.quit),
|
neutrino.QuitChan(n.quit),
|
||||||
)
|
)
|
||||||
@ -784,7 +772,7 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
|||||||
if spendReport != nil && spendReport.SpendingTx != nil {
|
if spendReport != nil && spendReport.SpendingTx != nil {
|
||||||
spendingTxHash := spendReport.SpendingTx.TxHash()
|
spendingTxHash := spendReport.SpendingTx.TxHash()
|
||||||
spendDetails = &chainntnfs.SpendDetail{
|
spendDetails = &chainntnfs.SpendDetail{
|
||||||
SpentOutPoint: &spendRequest.OutPoint,
|
SpentOutPoint: outpoint,
|
||||||
SpenderTxHash: &spendingTxHash,
|
SpenderTxHash: &spendingTxHash,
|
||||||
SpendingTx: spendReport.SpendingTx,
|
SpendingTx: spendReport.SpendingTx,
|
||||||
SpenderInputIndex: spendReport.SpendingInputIndex,
|
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
|
// not, we'll mark our historical rescan as complete to ensure the
|
||||||
// outpoint's spend hint gets updated upon connected/disconnected
|
// outpoint's spend hint gets updated upon connected/disconnected
|
||||||
// blocks.
|
// blocks.
|
||||||
err = n.txNotifier.UpdateSpendDetails(spendRequest, spendDetails)
|
err = n.txNotifier.UpdateSpendDetails(
|
||||||
|
ntfn.HistoricalDispatch.SpendRequest, spendDetails,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
chainntnfs.Log.Errorf("Failed to update spend details: %v", err)
|
chainntnfs.Log.Errorf("Failed to update spend details: %v", err)
|
||||||
return
|
return
|
||||||
|
@ -415,13 +415,33 @@ type HistoricalSpendDispatch struct {
|
|||||||
EndHeight uint32
|
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
|
// TxNotifier is a struct responsible for delivering transaction notifications
|
||||||
// to subscribers. These notifications can be of two different types:
|
// to subscribers. These notifications can be of two different types:
|
||||||
// transaction/output script confirmations and/or outpoint/output script spends.
|
// transaction/output script confirmations and/or outpoint/output script spends.
|
||||||
// The TxNotifier will watch the blockchain as new blocks come in, in order to
|
// The TxNotifier will watch the blockchain as new blocks come in, in order to
|
||||||
// satisfy its client requests.
|
// satisfy its client requests.
|
||||||
type TxNotifier struct {
|
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
|
// currentHeight is the height of the tracked blockchain. It is used to
|
||||||
// determine the number of confirmations a tx has and ensure blocks are
|
// determine the number of confirmations a tx has and ensure blocks are
|
||||||
@ -885,29 +905,50 @@ func (n *TxNotifier) dispatchConfDetails(
|
|||||||
return nil
|
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
|
// RegisterSpend handles a new spend notification request. The client will be
|
||||||
// notified once the outpoint/output script is detected as spent within the
|
// notified once the outpoint/output script is detected as spent within the
|
||||||
// chain.
|
// 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
|
// 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
|
// before the notifier's current tip, the spend details must be provided with
|
||||||
// the UpdateSpendDetails method, otherwise we will wait for the outpoint/output
|
// the UpdateSpendDetails method, otherwise we will wait for the outpoint/output
|
||||||
// script to be spent at tip, even though it already has.
|
// script to be spent at tip, even though it already has.
|
||||||
func (n *TxNotifier) RegisterSpend(ntfn *SpendNtfn) (*HistoricalSpendDispatch,
|
func (n *TxNotifier) RegisterSpend(outpoint *wire.OutPoint, pkScript []byte,
|
||||||
uint32, error) {
|
heightHint uint32) (*SpendRegistration, error) {
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-n.quit:
|
case <-n.quit:
|
||||||
return nil, 0, ErrTxNotifierExiting
|
return nil, ErrTxNotifierExiting
|
||||||
default:
|
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
|
// Before proceeding to register the notification, we'll query our spend
|
||||||
// hint cache to determine whether a better one exists.
|
// hint cache to determine whether a better one exists.
|
||||||
startHeight := ntfn.HeightHint
|
startHeight := ntfn.HeightHint
|
||||||
@ -953,9 +994,16 @@ func (n *TxNotifier) RegisterSpend(ntfn *SpendNtfn) (*HistoricalSpendDispatch,
|
|||||||
"registration since rescan has finished",
|
"registration since rescan has finished",
|
||||||
ntfn.SpendRequest)
|
ntfn.SpendRequest)
|
||||||
|
|
||||||
return nil, n.currentHeight, n.dispatchSpendDetails(
|
err := n.dispatchSpendDetails(ntfn, spendSet.details)
|
||||||
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
|
// If there is an active rescan to determine whether the request has
|
||||||
// been spent, then we won't trigger another one.
|
// 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 "+
|
Log.Debugf("Waiting for pending rescan to finish before "+
|
||||||
"notifying %v at tip", ntfn.SpendRequest)
|
"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
|
// Otherwise, we'll fall through and let the caller know that a rescan
|
||||||
// should be dispatched to determine whether the request has already
|
// 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
|
// spend hints for this request get updated upon
|
||||||
// connected/disconnected blocks.
|
// connected/disconnected blocks.
|
||||||
spendSet.rescanStatus = rescanComplete
|
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
|
// 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",
|
Log.Debugf("Dispatching historical spend rescan for %v",
|
||||||
ntfn.SpendRequest)
|
ntfn.SpendRequest)
|
||||||
|
|
||||||
return &HistoricalSpendDispatch{
|
return &SpendRegistration{
|
||||||
SpendRequest: ntfn.SpendRequest,
|
Event: ntfn.Event,
|
||||||
StartHeight: startHeight,
|
HistoricalDispatch: &HistoricalSpendDispatch{
|
||||||
EndHeight: n.currentHeight,
|
SpendRequest: ntfn.SpendRequest,
|
||||||
}, n.currentHeight, nil
|
StartHeight: startHeight,
|
||||||
|
EndHeight: n.currentHeight,
|
||||||
|
},
|
||||||
|
Height: n.currentHeight,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CancelSpend cancels an existing request for a spend notification of an
|
// CancelSpend cancels an existing request for a spend notification of an
|
||||||
|
@ -479,14 +479,9 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) {
|
|||||||
|
|
||||||
// We'll start off by registering for a spend notification of an
|
// We'll start off by registering for a spend notification of an
|
||||||
// outpoint.
|
// outpoint.
|
||||||
ntfn := &chainntnfs.SpendNtfn{
|
op := wire.OutPoint{Index: 1}
|
||||||
SpendRequest: chainntnfs.SpendRequest{
|
ntfn, err := n.RegisterSpend(&op, testRawScript, 1)
|
||||||
OutPoint: wire.OutPoint{Index: 1},
|
if err != nil {
|
||||||
PkScript: testScript,
|
|
||||||
},
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(ntfn); err != nil {
|
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,14 +498,14 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) {
|
|||||||
// spend notification.
|
// spend notification.
|
||||||
spendTx := wire.NewMsgTx(2)
|
spendTx := wire.NewMsgTx(2)
|
||||||
spendTx.AddTxIn(&wire.TxIn{
|
spendTx.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: ntfn.OutPoint,
|
PreviousOutPoint: op,
|
||||||
SignatureScript: testSigScript,
|
SignatureScript: testSigScript,
|
||||||
})
|
})
|
||||||
spendTxHash := spendTx.TxHash()
|
spendTxHash := spendTx.TxHash()
|
||||||
block := btcutil.NewBlock(&wire.MsgBlock{
|
block := btcutil.NewBlock(&wire.MsgBlock{
|
||||||
Transactions: []*wire.MsgTx{spendTx},
|
Transactions: []*wire.MsgTx{spendTx},
|
||||||
})
|
})
|
||||||
err := n.ConnectTip(block.Hash(), 11, block.Transactions())
|
err = n.ConnectTip(block.Hash(), 11, block.Transactions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to connect block: %v", err)
|
t.Fatalf("unable to connect block: %v", err)
|
||||||
}
|
}
|
||||||
@ -519,7 +514,7 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedSpendDetails := &chainntnfs.SpendDetail{
|
expectedSpendDetails := &chainntnfs.SpendDetail{
|
||||||
SpentOutPoint: &ntfn.OutPoint,
|
SpentOutPoint: &op,
|
||||||
SpenderTxHash: &spendTxHash,
|
SpenderTxHash: &spendTxHash,
|
||||||
SpendingTx: spendTx,
|
SpendingTx: spendTx,
|
||||||
SpenderInputIndex: 0,
|
SpenderInputIndex: 0,
|
||||||
@ -593,11 +588,8 @@ func TestTxNotifierHistoricalSpendDispatch(t *testing.T) {
|
|||||||
|
|
||||||
// We'll register for a spend notification of the outpoint and ensure
|
// We'll register for a spend notification of the outpoint and ensure
|
||||||
// that a notification isn't dispatched.
|
// that a notification isn't dispatched.
|
||||||
ntfn := &chainntnfs.SpendNtfn{
|
ntfn, err := n.RegisterSpend(&spentOutpoint, testRawScript, 1)
|
||||||
SpendRequest: chainntnfs.SpendRequest{OutPoint: spentOutpoint},
|
if err != nil {
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(ntfn); err != nil {
|
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
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
|
// 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.
|
// as it is not possible for it to view historical events in the chain.
|
||||||
// By doing this, we replicate the functionality of the ChainNotifier.
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to update spend details: %v", err)
|
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
|
// The first registration for an outpoint in the notifier should request
|
||||||
// a historical spend rescan as it does not have a historical view of
|
// a historical spend rescan as it does not have a historical view of
|
||||||
// the chain.
|
// the chain.
|
||||||
spendRequest := chainntnfs.SpendRequest{
|
op := wire.OutPoint{Index: 1}
|
||||||
OutPoint: wire.OutPoint{Index: 1},
|
ntfn1, err := n.RegisterSpend(&op, testRawScript, 1)
|
||||||
}
|
|
||||||
ntfn1 := &chainntnfs.SpendNtfn{
|
|
||||||
SpendID: 0,
|
|
||||||
SpendRequest: spendRequest,
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
historicalDispatch1, _, err := n.RegisterSpend(ntfn1)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
if historicalDispatch1 == nil {
|
if ntfn1.HistoricalDispatch == nil {
|
||||||
t.Fatal("expected to receive historical dispatch request")
|
t.Fatal("expected to receive historical dispatch request")
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll register another spend notification for the same outpoint. This
|
// We'll register another spend notification for the same outpoint. This
|
||||||
// should not request a historical spend rescan since the first one is
|
// should not request a historical spend rescan since the first one is
|
||||||
// still pending.
|
// still pending.
|
||||||
ntfn2 := &chainntnfs.SpendNtfn{
|
ntfn2, err := n.RegisterSpend(&op, testRawScript, 1)
|
||||||
SpendID: 1,
|
|
||||||
SpendRequest: spendRequest,
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
historicalDispatch2, _, err := n.RegisterSpend(ntfn2)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
if historicalDispatch2 != nil {
|
if ntfn2.HistoricalDispatch != nil {
|
||||||
t.Fatal("received unexpected historical rescan request")
|
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
|
// historical rescan request since the confirmation details should be
|
||||||
// cached.
|
// cached.
|
||||||
spendDetails := &chainntnfs.SpendDetail{
|
spendDetails := &chainntnfs.SpendDetail{
|
||||||
SpentOutPoint: &ntfn2.OutPoint,
|
SpentOutPoint: &op,
|
||||||
SpenderTxHash: &chainntnfs.ZeroHash,
|
SpenderTxHash: &chainntnfs.ZeroHash,
|
||||||
SpendingTx: wire.NewMsgTx(2),
|
SpendingTx: wire.NewMsgTx(2),
|
||||||
SpenderInputIndex: 0,
|
SpenderInputIndex: 0,
|
||||||
SpendingHeight: startingHeight - 1,
|
SpendingHeight: startingHeight - 1,
|
||||||
}
|
}
|
||||||
err = n.UpdateSpendDetails(ntfn2.SpendRequest, spendDetails)
|
err = n.UpdateSpendDetails(
|
||||||
|
ntfn1.HistoricalDispatch.SpendRequest, spendDetails,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to update spend details: %v", err)
|
t.Fatalf("unable to update spend details: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfn3 := &chainntnfs.SpendNtfn{
|
ntfn3, err := n.RegisterSpend(&op, testRawScript, 1)
|
||||||
SpendID: 2,
|
|
||||||
SpendRequest: spendRequest,
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
historicalDispatch3, _, err := n.RegisterSpend(ntfn3)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
if historicalDispatch3 != nil {
|
if ntfn3.HistoricalDispatch != nil {
|
||||||
t.Fatal("received unexpected historical rescan request")
|
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.
|
// Similarly, we'll do the same thing but for spend notifications.
|
||||||
spendRequest := chainntnfs.SpendRequest{
|
op := wire.OutPoint{Index: 1}
|
||||||
OutPoint: wire.OutPoint{Index: 1},
|
spendNtfns := make([]*chainntnfs.SpendRegistration, numNtfns)
|
||||||
}
|
|
||||||
spendNtfns := make([]*chainntnfs.SpendNtfn, numNtfns)
|
|
||||||
for i := uint64(0); i < numNtfns; i++ {
|
for i := uint64(0); i < numNtfns; i++ {
|
||||||
spendNtfns[i] = &chainntnfs.SpendNtfn{
|
ntfn, err := n.RegisterSpend(&op, testRawScript, 1)
|
||||||
SpendID: i,
|
if err != nil {
|
||||||
SpendRequest: spendRequest,
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(spendNtfns[i]); err != nil {
|
|
||||||
t.Fatalf("unable to register spend ntfn #%d: %v", i, err)
|
t.Fatalf("unable to register spend ntfn #%d: %v", i, err)
|
||||||
}
|
}
|
||||||
|
spendNtfns[i] = ntfn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure none of them have received the spend details.
|
// 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
|
// following spend details. We'll let the notifier know so that it can
|
||||||
// stop watching at tip.
|
// stop watching at tip.
|
||||||
expectedSpendDetails := &chainntnfs.SpendDetail{
|
expectedSpendDetails := &chainntnfs.SpendDetail{
|
||||||
SpentOutPoint: &spendNtfns[0].OutPoint,
|
SpentOutPoint: &op,
|
||||||
SpenderTxHash: &chainntnfs.ZeroHash,
|
SpenderTxHash: &chainntnfs.ZeroHash,
|
||||||
SpendingTx: wire.NewMsgTx(2),
|
SpendingTx: wire.NewMsgTx(2),
|
||||||
SpenderInputIndex: 0,
|
SpenderInputIndex: 0,
|
||||||
SpendingHeight: startingHeight - 1,
|
SpendingHeight: startingHeight - 1,
|
||||||
}
|
}
|
||||||
err = n.UpdateSpendDetails(spendNtfns[0].SpendRequest, expectedSpendDetails)
|
err = n.UpdateSpendDetails(
|
||||||
|
spendNtfns[0].HistoricalDispatch.SpendRequest, expectedSpendDetails,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to update spend details: %v", err)
|
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
|
// cached, we'll register another client for the same outpoint. We
|
||||||
// should not see a historical rescan request and the spend notification
|
// should not see a historical rescan request and the spend notification
|
||||||
// should come through immediately.
|
// should come through immediately.
|
||||||
extraSpendNtfn := &chainntnfs.SpendNtfn{
|
extraSpendNtfn, err := n.RegisterSpend(&op, testRawScript, 1)
|
||||||
SpendID: numNtfns + 1,
|
|
||||||
SpendRequest: spendRequest,
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
historicalSpendRescan, _, err := n.RegisterSpend(extraSpendNtfn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
if historicalSpendRescan != nil {
|
if extraSpendNtfn.HistoricalDispatch != nil {
|
||||||
t.Fatal("received unexpected historical rescan request")
|
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
|
// We'll register two notification requests. Only the second one will be
|
||||||
// canceled.
|
// canceled.
|
||||||
ntfn1 := &chainntnfs.SpendNtfn{
|
op1 := wire.OutPoint{Index: 1}
|
||||||
SpendID: 0,
|
ntfn1, err := n.RegisterSpend(&op1, testRawScript, 1)
|
||||||
SpendRequest: chainntnfs.SpendRequest{
|
if err != nil {
|
||||||
OutPoint: wire.OutPoint{Index: 1},
|
|
||||||
PkScript: testScript,
|
|
||||||
},
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(ntfn1); err != nil {
|
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfn2 := &chainntnfs.SpendNtfn{
|
op2 := wire.OutPoint{Index: 2}
|
||||||
SpendID: 1,
|
ntfn2, err := n.RegisterSpend(&op2, testRawScript, 1)
|
||||||
SpendRequest: chainntnfs.SpendRequest{
|
if err != nil {
|
||||||
OutPoint: wire.OutPoint{Index: 2},
|
|
||||||
},
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(ntfn2); err != nil {
|
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,12 +1022,12 @@ func TestTxNotifierCancelSpend(t *testing.T) {
|
|||||||
// block containing it.
|
// block containing it.
|
||||||
spendTx := wire.NewMsgTx(2)
|
spendTx := wire.NewMsgTx(2)
|
||||||
spendTx.AddTxIn(&wire.TxIn{
|
spendTx.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: ntfn1.OutPoint,
|
PreviousOutPoint: op1,
|
||||||
SignatureScript: testSigScript,
|
SignatureScript: testSigScript,
|
||||||
})
|
})
|
||||||
spendTxHash := spendTx.TxHash()
|
spendTxHash := spendTx.TxHash()
|
||||||
expectedSpendDetails := &chainntnfs.SpendDetail{
|
expectedSpendDetails := &chainntnfs.SpendDetail{
|
||||||
SpentOutPoint: &ntfn1.OutPoint,
|
SpentOutPoint: &op1,
|
||||||
SpenderTxHash: &spendTxHash,
|
SpenderTxHash: &spendTxHash,
|
||||||
SpendingTx: spendTx,
|
SpendingTx: spendTx,
|
||||||
SpenderInputIndex: 0,
|
SpenderInputIndex: 0,
|
||||||
@ -1080,9 +1040,9 @@ func TestTxNotifierCancelSpend(t *testing.T) {
|
|||||||
|
|
||||||
// Before extending the notifier's tip with the dummy block above, we'll
|
// Before extending the notifier's tip with the dummy block above, we'll
|
||||||
// cancel the second request.
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to connect block: %v", err)
|
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
|
// 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
|
// first will be spent and will not experience a reorg, while the second
|
||||||
// one will.
|
// one will.
|
||||||
spendRequest1 := chainntnfs.SpendRequest{
|
op1 := wire.OutPoint{Index: 1}
|
||||||
OutPoint: wire.OutPoint{Index: 1},
|
|
||||||
PkScript: testScript,
|
|
||||||
}
|
|
||||||
spendTx1 := wire.NewMsgTx(2)
|
spendTx1 := wire.NewMsgTx(2)
|
||||||
spendTx1.AddTxIn(&wire.TxIn{
|
spendTx1.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: spendRequest1.OutPoint,
|
PreviousOutPoint: op1,
|
||||||
SignatureScript: testSigScript,
|
SignatureScript: testSigScript,
|
||||||
})
|
})
|
||||||
spendTxHash1 := spendTx1.TxHash()
|
spendTxHash1 := spendTx1.TxHash()
|
||||||
expectedSpendDetails1 := &chainntnfs.SpendDetail{
|
expectedSpendDetails1 := &chainntnfs.SpendDetail{
|
||||||
SpentOutPoint: &spendRequest1.OutPoint,
|
SpentOutPoint: &op1,
|
||||||
SpenderTxHash: &spendTxHash1,
|
SpenderTxHash: &spendTxHash1,
|
||||||
SpendingTx: spendTx1,
|
SpendingTx: spendTx1,
|
||||||
SpenderInputIndex: 0,
|
SpenderInputIndex: 0,
|
||||||
SpendingHeight: startingHeight + 1,
|
SpendingHeight: startingHeight + 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
spendRequest2 := chainntnfs.SpendRequest{
|
op2 := wire.OutPoint{Index: 2}
|
||||||
OutPoint: wire.OutPoint{Index: 2},
|
|
||||||
PkScript: testScript,
|
|
||||||
}
|
|
||||||
spendTx2 := wire.NewMsgTx(2)
|
spendTx2 := wire.NewMsgTx(2)
|
||||||
spendTx2.AddTxIn(&wire.TxIn{
|
spendTx2.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: chainntnfs.ZeroOutPoint,
|
PreviousOutPoint: chainntnfs.ZeroOutPoint,
|
||||||
SignatureScript: testSigScript,
|
SignatureScript: testSigScript,
|
||||||
})
|
})
|
||||||
spendTx2.AddTxIn(&wire.TxIn{
|
spendTx2.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: spendRequest2.OutPoint,
|
PreviousOutPoint: op2,
|
||||||
SignatureScript: testSigScript,
|
SignatureScript: testSigScript,
|
||||||
})
|
})
|
||||||
spendTxHash2 := spendTx2.TxHash()
|
spendTxHash2 := spendTx2.TxHash()
|
||||||
@ -1441,7 +1395,7 @@ func TestTxNotifierSpendReorg(t *testing.T) {
|
|||||||
// different height, so we'll need to construct the spend details for
|
// different height, so we'll need to construct the spend details for
|
||||||
// before and after the reorg.
|
// before and after the reorg.
|
||||||
expectedSpendDetails2BeforeReorg := chainntnfs.SpendDetail{
|
expectedSpendDetails2BeforeReorg := chainntnfs.SpendDetail{
|
||||||
SpentOutPoint: &spendRequest2.OutPoint,
|
SpentOutPoint: &op2,
|
||||||
SpenderTxHash: &spendTxHash2,
|
SpenderTxHash: &spendTxHash2,
|
||||||
SpendingTx: spendTx2,
|
SpendingTx: spendTx2,
|
||||||
SpenderInputIndex: 1,
|
SpenderInputIndex: 1,
|
||||||
@ -1454,21 +1408,13 @@ func TestTxNotifierSpendReorg(t *testing.T) {
|
|||||||
expectedSpendDetails2AfterReorg.SpendingHeight++
|
expectedSpendDetails2AfterReorg.SpendingHeight++
|
||||||
|
|
||||||
// We'll register for a spend notification for each outpoint above.
|
// We'll register for a spend notification for each outpoint above.
|
||||||
ntfn1 := &chainntnfs.SpendNtfn{
|
ntfn1, err := n.RegisterSpend(&op1, testRawScript, 1)
|
||||||
SpendID: 78,
|
if err != nil {
|
||||||
SpendRequest: spendRequest1,
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(ntfn1); err != nil {
|
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfn2 := &chainntnfs.SpendNtfn{
|
ntfn2, err := n.RegisterSpend(&op2, testRawScript, 1)
|
||||||
SpendID: 21,
|
if err != nil {
|
||||||
SpendRequest: spendRequest2,
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(ntfn2); err != nil {
|
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1477,7 +1423,7 @@ func TestTxNotifierSpendReorg(t *testing.T) {
|
|||||||
block1 := btcutil.NewBlock(&wire.MsgBlock{
|
block1 := btcutil.NewBlock(&wire.MsgBlock{
|
||||||
Transactions: []*wire.MsgTx{spendTx1},
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to connect block: %v", err)
|
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.
|
// Create two test outpoints and register them for spend notifications.
|
||||||
ntfn1 := &chainntnfs.SpendNtfn{
|
op1 := wire.OutPoint{Index: 1}
|
||||||
SpendID: 1,
|
ntfn1, err := n.RegisterSpend(&op1, testRawScript, 1)
|
||||||
SpendRequest: chainntnfs.SpendRequest{
|
if err != nil {
|
||||||
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 {
|
|
||||||
t.Fatalf("unable to register spend for op1: %v", err)
|
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)
|
t.Fatalf("unable to register spend for op2: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both outpoints should not have a spend hint set upon registration, as
|
// Both outpoints should not have a spend hint set upon registration, as
|
||||||
// we must first determine whether they have already been spent in the
|
// we must first determine whether they have already been spent in the
|
||||||
// chain.
|
// chain.
|
||||||
_, err := hintCache.QuerySpendHint(ntfn1.SpendRequest)
|
_, err = hintCache.QuerySpendHint(ntfn1.HistoricalDispatch.SpendRequest)
|
||||||
if err != chainntnfs.ErrSpendHintNotFound {
|
if err != chainntnfs.ErrSpendHintNotFound {
|
||||||
t.Fatalf("unexpected error when querying for height hint "+
|
t.Fatalf("unexpected error when querying for height hint "+
|
||||||
"expected: %v, got %v", chainntnfs.ErrSpendHintNotFound,
|
"expected: %v, got %v", chainntnfs.ErrSpendHintNotFound,
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
_, err = hintCache.QuerySpendHint(ntfn2.SpendRequest)
|
_, err = hintCache.QuerySpendHint(ntfn2.HistoricalDispatch.SpendRequest)
|
||||||
if err != chainntnfs.ErrSpendHintNotFound {
|
if err != chainntnfs.ErrSpendHintNotFound {
|
||||||
t.Fatalf("unexpected error when querying for height hint "+
|
t.Fatalf("unexpected error when querying for height hint "+
|
||||||
"expected: %v, got %v", chainntnfs.ErrSpendHintNotFound,
|
"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
|
// Since we haven't called UpdateSpendDetails on any of the test
|
||||||
// outpoints, this implies that there is a still a pending historical
|
// outpoints, this implies that there is a still a pending historical
|
||||||
// rescan for them, so their spend hints should not be created/updated.
|
// 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 {
|
if err != chainntnfs.ErrSpendHintNotFound {
|
||||||
t.Fatalf("unexpected error when querying for height hint "+
|
t.Fatalf("unexpected error when querying for height hint "+
|
||||||
"expected: %v, got %v", chainntnfs.ErrSpendHintNotFound,
|
"expected: %v, got %v", chainntnfs.ErrSpendHintNotFound,
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
_, err = hintCache.QuerySpendHint(ntfn2.SpendRequest)
|
_, err = hintCache.QuerySpendHint(ntfn2.HistoricalDispatch.SpendRequest)
|
||||||
if err != chainntnfs.ErrSpendHintNotFound {
|
if err != chainntnfs.ErrSpendHintNotFound {
|
||||||
t.Fatalf("unexpected error when querying for height hint "+
|
t.Fatalf("unexpected error when querying for height hint "+
|
||||||
"expected: %v, got %v", chainntnfs.ErrSpendHintNotFound,
|
"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
|
// Now, we'll simulate that their historical rescans have finished by
|
||||||
// calling UpdateSpendDetails. This should allow their spend hints to be
|
// calling UpdateSpendDetails. This should allow their spend hints to be
|
||||||
// updated upon every block connected/disconnected.
|
// 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)
|
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)
|
t.Fatalf("unable to update spend details: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1918,7 +1853,7 @@ func TestTxNotifierSpendHintCache(t *testing.T) {
|
|||||||
// of the first outpoint.
|
// of the first outpoint.
|
||||||
spendTx1 := wire.NewMsgTx(2)
|
spendTx1 := wire.NewMsgTx(2)
|
||||||
spendTx1.AddTxIn(&wire.TxIn{
|
spendTx1.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: ntfn1.OutPoint,
|
PreviousOutPoint: op1,
|
||||||
SignatureScript: testSigScript,
|
SignatureScript: testSigScript,
|
||||||
})
|
})
|
||||||
block1 := btcutil.NewBlock(&wire.MsgBlock{
|
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
|
// Both outpoints should have their spend hints reflect the height of
|
||||||
// the new block being connected due to the first outpoint being spent
|
// the new block being connected due to the first outpoint being spent
|
||||||
// at this height, and the second outpoint still being unspent.
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for spend hint of op1: %v", err)
|
t.Fatalf("unable to query for spend hint of op1: %v", err)
|
||||||
}
|
}
|
||||||
if op1Hint != op1Height {
|
if op1Hint != op1Height {
|
||||||
t.Fatalf("expected hint %d, got %d", op1Height, op1Hint)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for spend hint of op2: %v", err)
|
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.
|
// Then, we'll create another block that spends the second outpoint.
|
||||||
spendTx2 := wire.NewMsgTx(2)
|
spendTx2 := wire.NewMsgTx(2)
|
||||||
spendTx2.AddTxIn(&wire.TxIn{
|
spendTx2.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: ntfn2.OutPoint,
|
PreviousOutPoint: op2,
|
||||||
SignatureScript: testSigScript,
|
SignatureScript: testSigScript,
|
||||||
})
|
})
|
||||||
block2 := btcutil.NewBlock(&wire.MsgBlock{
|
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
|
// Only the second outpoint should have its spend hint updated due to
|
||||||
// being spent within the new block. The first outpoint's spend hint
|
// being spent within the new block. The first outpoint's spend hint
|
||||||
// should remain the same as it's already been spent before.
|
// 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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for spend hint of op1: %v", err)
|
t.Fatalf("unable to query for spend hint of op1: %v", err)
|
||||||
}
|
}
|
||||||
if op1Hint != op1Height {
|
if op1Hint != op1Height {
|
||||||
t.Fatalf("expected hint %d, got %d", op1Height, op1Hint)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for spend hint of op2: %v", err)
|
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
|
// to the previous height, as that's where its spending transaction was
|
||||||
// included in within the chain. The first outpoint's spend hint should
|
// included in within the chain. The first outpoint's spend hint should
|
||||||
// remain the same.
|
// remain the same.
|
||||||
op1Hint, err = hintCache.QuerySpendHint(ntfn1.SpendRequest)
|
op1Hint, err = hintCache.QuerySpendHint(ntfn1.HistoricalDispatch.SpendRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for spend hint of op1: %v", err)
|
t.Fatalf("unable to query for spend hint of op1: %v", err)
|
||||||
}
|
}
|
||||||
if op1Hint != op1Height {
|
if op1Hint != op1Height {
|
||||||
t.Fatalf("expected hint %d, got %d", op1Height, op1Hint)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to query for spend hint of op2: %v", err)
|
t.Fatalf("unable to query for spend hint of op2: %v", err)
|
||||||
}
|
}
|
||||||
@ -2027,16 +1962,8 @@ func TestTxNotifierNtfnDone(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to register conf ntfn: %v", err)
|
t.Fatalf("unable to register conf ntfn: %v", err)
|
||||||
}
|
}
|
||||||
|
spendNtfn, err := n.RegisterSpend(&chainntnfs.ZeroOutPoint, testRawScript, 1)
|
||||||
spendNtfn := &chainntnfs.SpendNtfn{
|
if err != nil {
|
||||||
SpendID: 2,
|
|
||||||
SpendRequest: chainntnfs.SpendRequest{
|
|
||||||
OutPoint: chainntnfs.ZeroOutPoint,
|
|
||||||
PkScript: testScript,
|
|
||||||
},
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(spendNtfn); err != nil {
|
|
||||||
t.Fatalf("unable to register spend: %v", err)
|
t.Fatalf("unable to register spend: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2165,13 +2092,8 @@ func TestTxNotifierTearDown(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to register conf ntfn: %v", err)
|
t.Fatalf("unable to register conf ntfn: %v", err)
|
||||||
}
|
}
|
||||||
|
spendNtfn, err := n.RegisterSpend(&chainntnfs.ZeroOutPoint, testRawScript, 1)
|
||||||
spendNtfn := &chainntnfs.SpendNtfn{
|
if err != nil {
|
||||||
SpendID: 1,
|
|
||||||
SpendRequest: chainntnfs.SpendRequest{OutPoint: chainntnfs.ZeroOutPoint},
|
|
||||||
Event: chainntnfs.NewSpendEvent(nil),
|
|
||||||
}
|
|
||||||
if _, _, err := n.RegisterSpend(spendNtfn); err != nil {
|
|
||||||
t.Fatalf("unable to register spend ntfn: %v", err)
|
t.Fatalf("unable to register spend ntfn: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2212,7 +2134,8 @@ func TestTxNotifierTearDown(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected confirmation registration to fail")
|
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")
|
t.Fatal("expected spend registration to fail")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user