mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
Merge pull request #6730 from Roasbeef/notifier-optional-block
chainntfns: add new option for conf notifications to send block
This commit is contained in:
commit
17014b592e
@ -564,6 +564,7 @@ func (b *BitcoindNotifier) confDetailsManually(confRequest chainntnfs.ConfReques
|
||||
BlockHash: blockHash,
|
||||
BlockHeight: height,
|
||||
TxIndex: uint32(txIndex),
|
||||
Block: block,
|
||||
}, chainntnfs.TxFoundManually, nil
|
||||
}
|
||||
}
|
||||
@ -584,12 +585,12 @@ func (b *BitcoindNotifier) handleBlockConnected(block chainntnfs.BlockEpoch) err
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get block: %v", err)
|
||||
}
|
||||
txns := btcutil.NewBlock(rawBlock).Transactions()
|
||||
utilBlock := btcutil.NewBlock(rawBlock)
|
||||
|
||||
// We'll then extend the txNotifier's height with the information of
|
||||
// this new block, which will handle all of the notification logic for
|
||||
// us.
|
||||
err = b.txNotifier.ConnectTip(block.Hash, uint32(block.Height), txns)
|
||||
err = b.txNotifier.ConnectTip(utilBlock, uint32(block.Height))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to connect tip: %v", err)
|
||||
}
|
||||
@ -844,15 +845,15 @@ func (b *BitcoindNotifier) historicalSpendDetails(
|
||||
// channel. Once it has reached all of its confirmations, a notification will be
|
||||
// sent across the 'Confirmed' channel.
|
||||
func (b *BitcoindNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
||||
pkScript []byte,
|
||||
numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, error) {
|
||||
pkScript []byte, numConfs, heightHint uint32,
|
||||
opts ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
|
||||
|
||||
// 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.RegisterConf(
|
||||
txid, pkScript, numConfs, heightHint,
|
||||
txid, pkScript, numConfs, heightHint, opts...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -263,13 +263,14 @@ func (b *BtcdNotifier) onBlockConnected(hash *chainhash.Hash, height int32, t ti
|
||||
// chain. The slice of transactions will only be populated if the block
|
||||
// includes a transaction that confirmed one of our watched txids, or spends
|
||||
// one of the outputs currently being watched.
|
||||
//
|
||||
// TODO(halseth): this is currently used for complete blocks. Change to use
|
||||
// onFilteredBlockConnected and onFilteredBlockDisconnected, making it easier
|
||||
// to unify with the Neutrino implementation.
|
||||
type filteredBlock struct {
|
||||
hash chainhash.Hash
|
||||
height uint32
|
||||
txns []*btcutil.Tx
|
||||
block *btcutil.Block
|
||||
|
||||
// connected is true if this update is a new block and false if it is a
|
||||
// disconnected block.
|
||||
@ -619,6 +620,7 @@ func (b *BtcdNotifier) confDetailsManually(confRequest chainntnfs.ConfRequest,
|
||||
BlockHash: blockHash,
|
||||
BlockHeight: height,
|
||||
TxIndex: uint32(txIndex),
|
||||
Block: block,
|
||||
}, chainntnfs.TxFoundManually, nil
|
||||
}
|
||||
}
|
||||
@ -644,16 +646,14 @@ func (b *BtcdNotifier) handleBlockConnected(epoch chainntnfs.BlockEpoch) error {
|
||||
newBlock := &filteredBlock{
|
||||
hash: *epoch.Hash,
|
||||
height: uint32(epoch.Height),
|
||||
txns: btcutil.NewBlock(rawBlock).Transactions(),
|
||||
block: btcutil.NewBlock(rawBlock),
|
||||
connect: true,
|
||||
}
|
||||
|
||||
// We'll then extend the txNotifier's height with the information of
|
||||
// this new block, which will handle all of the notification logic for
|
||||
// us.
|
||||
err = b.txNotifier.ConnectTip(
|
||||
&newBlock.hash, newBlock.height, newBlock.txns,
|
||||
)
|
||||
err = b.txNotifier.ConnectTip(newBlock.block, newBlock.height)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to connect tip: %v", err)
|
||||
}
|
||||
@ -903,15 +903,15 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
||||
// channel. Once it has reached all of its confirmations, a notification will be
|
||||
// sent across the 'Confirmed' channel.
|
||||
func (b *BtcdNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
||||
pkScript []byte,
|
||||
numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, error) {
|
||||
pkScript []byte, numConfs, heightHint uint32,
|
||||
opts ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
|
||||
|
||||
// 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.RegisterConf(
|
||||
txid, pkScript, numConfs, heightHint,
|
||||
txid, pkScript, numConfs, heightHint, opts...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -8,7 +8,9 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/btcjson"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
@ -67,6 +69,31 @@ func (t TxConfStatus) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
// notifierOptions is a set of functional options that allow callers to further
|
||||
// modify the type of chain event notifications they receive.
|
||||
type notifierOptions struct {
|
||||
// includeBlock if true, then the dispatched confirmation notification
|
||||
// will include the block that mined the transaction.
|
||||
includeBlock bool
|
||||
}
|
||||
|
||||
// defaultNotifierOptions returns the set of default options for the notifier.
|
||||
func defaultNotifierOptions() *notifierOptions {
|
||||
return ¬ifierOptions{}
|
||||
}
|
||||
|
||||
// NotifierOption is a functional option that allows a caller to modify the
|
||||
// events received from the notifier.
|
||||
type NotifierOption func(*notifierOptions)
|
||||
|
||||
// WithIncludeBlock is an optional argument that allows the calelr to specify
|
||||
// that the block that mined a transaction should be included in the response.
|
||||
func WithIncludeBlock() NotifierOption {
|
||||
return func(o *notifierOptions) {
|
||||
o.includeBlock = true
|
||||
}
|
||||
}
|
||||
|
||||
// ChainNotifier represents a trusted source to receive notifications concerning
|
||||
// targeted events on the Bitcoin blockchain. The interface specification is
|
||||
// intentionally general in order to support a wide array of chain notification
|
||||
@ -97,7 +124,8 @@ type ChainNotifier interface {
|
||||
// NOTE: Dispatching notifications to multiple clients subscribed to
|
||||
// the same (txid, numConfs) tuple MUST be supported.
|
||||
RegisterConfirmationsNtfn(txid *chainhash.Hash, pkScript []byte,
|
||||
numConfs, heightHint uint32) (*ConfirmationEvent, error)
|
||||
numConfs, heightHint uint32,
|
||||
opts ...NotifierOption) (*ConfirmationEvent, error)
|
||||
|
||||
// RegisterSpendNtfn registers an intent to be notified once the target
|
||||
// outpoint is successfully spent within a transaction. The script that
|
||||
@ -166,6 +194,12 @@ type TxConfirmation struct {
|
||||
|
||||
// Tx is the transaction for which the notification was requested for.
|
||||
Tx *wire.MsgTx
|
||||
|
||||
// Block is the block that contains the transaction referenced above.
|
||||
//
|
||||
// NOTE: This is only specified if the confirmation request opts to
|
||||
// have the response include the block itself.
|
||||
Block *wire.MsgBlock
|
||||
}
|
||||
|
||||
// ConfirmationEvent encapsulates a confirmation notification. With this struct,
|
||||
@ -628,9 +662,8 @@ type TxIndexConn interface {
|
||||
// block that the transaction confirmed.
|
||||
GetRawTransactionVerbose(*chainhash.Hash) (*btcjson.TxRawResult, error)
|
||||
|
||||
// GetBlockVerbose returns the block identified by the chain hash along
|
||||
// with additional information such as the block's height in the chain.
|
||||
GetBlockVerbose(*chainhash.Hash) (*btcjson.GetBlockVerboseResult, error)
|
||||
// GetBlock returns the block identified by the chain hash.
|
||||
GetBlock(*chainhash.Hash) (*wire.MsgBlock, error)
|
||||
}
|
||||
|
||||
// ConfDetailsFromTxIndex looks up whether a transaction is already included in
|
||||
@ -700,26 +733,38 @@ func ConfDetailsFromTxIndex(chainConn TxIndexConn, r ConfRequest,
|
||||
fmt.Errorf("unable to get block hash %v for "+
|
||||
"historical dispatch: %v", rawTxRes.BlockHash, err)
|
||||
}
|
||||
block, err := chainConn.GetBlockVerbose(blockHash)
|
||||
block, err := chainConn.GetBlock(blockHash)
|
||||
if err != nil {
|
||||
return nil, TxNotFoundIndex,
|
||||
fmt.Errorf("unable to get block with hash %v for "+
|
||||
"historical dispatch: %v", blockHash, err)
|
||||
}
|
||||
|
||||
// In the modern chain (the only one we really care about for LN), the
|
||||
// coinbase transaction of all blocks will include the block height.
|
||||
// Therefore we can save another query, and just use that height
|
||||
// directly.
|
||||
blockHeight, err := blockchain.ExtractCoinbaseHeight(
|
||||
btcutil.NewTx(block.Transactions[0]),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, TxNotFoundIndex, fmt.Errorf("unable to extract "+
|
||||
"coinbase height: %w", err)
|
||||
}
|
||||
|
||||
// If the block was obtained, locate the transaction's index within the
|
||||
// block so we can give the subscriber full confirmation details.
|
||||
txidStr := r.TxID.String()
|
||||
for txIndex, txHash := range block.Tx {
|
||||
if txHash != txidStr {
|
||||
for txIndex, blockTx := range block.Transactions {
|
||||
if blockTx.TxHash() != r.TxID {
|
||||
continue
|
||||
}
|
||||
|
||||
return &TxConfirmation{
|
||||
Tx: &tx,
|
||||
BlockHash: blockHash,
|
||||
BlockHeight: uint32(block.Height),
|
||||
BlockHeight: uint32(blockHeight),
|
||||
TxIndex: uint32(txIndex),
|
||||
Block: block,
|
||||
}, TxFoundIndex, nil
|
||||
}
|
||||
|
||||
|
@ -636,6 +636,7 @@ func (n *NeutrinoNotifier) historicalConfDetails(confRequest chainntnfs.ConfRequ
|
||||
BlockHash: blockHash,
|
||||
BlockHeight: scanHeight,
|
||||
TxIndex: uint32(i),
|
||||
Block: block.MsgBlock(),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
@ -649,11 +650,19 @@ func (n *NeutrinoNotifier) historicalConfDetails(confRequest chainntnfs.ConfRequ
|
||||
//
|
||||
// NOTE: This method must be called with the bestBlockMtx lock held.
|
||||
func (n *NeutrinoNotifier) handleBlockConnected(newBlock *filteredBlock) error {
|
||||
// We'll extend the txNotifier's height with the information of this new
|
||||
// block, which will handle all of the notification logic for us.
|
||||
err := n.txNotifier.ConnectTip(
|
||||
&newBlock.hash, newBlock.height, newBlock.txns,
|
||||
)
|
||||
// We'll extend the txNotifier's height with the information of this
|
||||
// new block, which will handle all of the notification logic for us.
|
||||
//
|
||||
// We actually need the _full_ block here as well in order to be able
|
||||
// to send the full block back up to the client. The neutrino client
|
||||
// itself will only dispatch a block if one of the items we're looking
|
||||
// for matches, so ultimately passing it the full block will still only
|
||||
// result in the items we care about being dispatched.
|
||||
rawBlock, err := n.GetBlock(newBlock.hash)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get full block: %v", err)
|
||||
}
|
||||
err = n.txNotifier.ConnectTip(rawBlock, newBlock.height)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to connect tip: %v", err)
|
||||
}
|
||||
@ -899,15 +908,15 @@ func (n *NeutrinoNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
|
||||
// channel. Once it has reached all of its confirmations, a notification will be
|
||||
// sent across the 'Confirmed' channel.
|
||||
func (n *NeutrinoNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
||||
pkScript []byte,
|
||||
numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, error) {
|
||||
pkScript []byte, numConfs, heightHint uint32,
|
||||
opts ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
|
||||
|
||||
// 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.RegisterConf(
|
||||
txid, pkScript, numConfs, heightHint,
|
||||
txid, pkScript, numConfs, heightHint, opts...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -160,6 +160,13 @@ func testBatchConfirmationNotification(miner *rpctest.Harness,
|
||||
// verify they're each notified at the proper number of confirmations
|
||||
// below.
|
||||
for i, numConfs := range confSpread {
|
||||
// All the clients with an even index will ask for the block
|
||||
// along side the conf ntfn.
|
||||
var opts []chainntnfs.NotifierOption
|
||||
if i%2 == 0 {
|
||||
opts = append(opts, chainntnfs.WithIncludeBlock())
|
||||
}
|
||||
|
||||
txid, pkScript, err := chainntnfs.GetTestTxidAndScript(miner)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create test addr: %v", err)
|
||||
@ -168,10 +175,12 @@ func testBatchConfirmationNotification(miner *rpctest.Harness,
|
||||
if scriptDispatch {
|
||||
confIntent, err = notifier.RegisterConfirmationsNtfn(
|
||||
nil, pkScript, numConfs, uint32(currentHeight),
|
||||
opts...,
|
||||
)
|
||||
} else {
|
||||
confIntent, err = notifier.RegisterConfirmationsNtfn(
|
||||
txid, pkScript, numConfs, uint32(currentHeight),
|
||||
opts...,
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
@ -218,6 +227,12 @@ func testBatchConfirmationNotification(miner *rpctest.Harness,
|
||||
"conf height: expected %v, got %v",
|
||||
initialConfHeight, conf.BlockHeight)
|
||||
}
|
||||
|
||||
// If this is an even client index, then we expect the
|
||||
// block to be populated. Otherwise, it should be
|
||||
// empty.
|
||||
expectBlock := i%2 == 0
|
||||
require.Equal(t, expectBlock, conf.Block != nil)
|
||||
continue
|
||||
case <-time.After(20 * time.Second):
|
||||
t.Fatalf("confirmation notification never received: %v", numConfs)
|
||||
@ -547,6 +562,7 @@ func testTxConfirmedBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
if scriptDispatch {
|
||||
ntfn1, err = notifier.RegisterConfirmationsNtfn(
|
||||
nil, pkScript1, 1, uint32(currentHeight),
|
||||
chainntnfs.WithIncludeBlock(),
|
||||
)
|
||||
} else {
|
||||
ntfn1, err = notifier.RegisterConfirmationsNtfn(
|
||||
@ -579,6 +595,13 @@ func testTxConfirmedBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
t.Fatalf("incorrect block height: expected %v, got %v",
|
||||
confInfo.BlockHeight, currentHeight)
|
||||
}
|
||||
|
||||
// Ensure that if this was a script dispatch, the block is set
|
||||
// as well.
|
||||
if scriptDispatch {
|
||||
require.NotNil(t, confInfo.Block)
|
||||
}
|
||||
|
||||
break
|
||||
case <-time.After(20 * time.Second):
|
||||
t.Fatalf("confirmation notification never received")
|
||||
@ -591,6 +614,7 @@ func testTxConfirmedBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
if scriptDispatch {
|
||||
ntfn2, err = notifier.RegisterConfirmationsNtfn(
|
||||
nil, pkScript2, 3, uint32(currentHeight),
|
||||
chainntnfs.WithIncludeBlock(),
|
||||
)
|
||||
} else {
|
||||
ntfn2, err = notifier.RegisterConfirmationsNtfn(
|
||||
@ -622,6 +646,7 @@ func testTxConfirmedBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
if scriptDispatch {
|
||||
ntfn3, err = notifier.RegisterConfirmationsNtfn(
|
||||
nil, pkScript3, 1, uint32(currentHeight-1),
|
||||
chainntnfs.WithIncludeBlock(),
|
||||
)
|
||||
} else {
|
||||
ntfn3, err = notifier.RegisterConfirmationsNtfn(
|
||||
@ -640,7 +665,10 @@ func testTxConfirmedBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
require.NoError(t, err, "unable to register ntfn")
|
||||
|
||||
select {
|
||||
case <-ntfn3.Confirmed:
|
||||
case confInfo := <-ntfn3.Confirmed:
|
||||
if scriptDispatch {
|
||||
require.NotNil(t, confInfo.Block)
|
||||
}
|
||||
case <-time.After(10 * time.Second):
|
||||
t.Fatalf("confirmation notification never received")
|
||||
}
|
||||
|
@ -265,6 +265,10 @@ type ConfNtfn struct {
|
||||
|
||||
// dispatched is false if the confirmed notification has not been sent yet.
|
||||
dispatched bool
|
||||
|
||||
// includeBlock is true if the dispatched notification should also have
|
||||
// the block included with it.
|
||||
includeBlock bool
|
||||
}
|
||||
|
||||
// HistoricalConfDispatch parametrizes a manual rescan for a particular
|
||||
@ -576,7 +580,8 @@ func NewTxNotifier(startHeight uint32, reorgSafetyLimit uint32,
|
||||
// newConfNtfn validates all of the parameters required to successfully create
|
||||
// and register a confirmation notification.
|
||||
func (n *TxNotifier) newConfNtfn(txid *chainhash.Hash,
|
||||
pkScript []byte, numConfs, heightHint uint32) (*ConfNtfn, error) {
|
||||
pkScript []byte, numConfs, heightHint uint32,
|
||||
opts *notifierOptions) (*ConfNtfn, error) {
|
||||
|
||||
// An accompanying output script must always be provided.
|
||||
if len(pkScript) == 0 {
|
||||
@ -609,7 +614,8 @@ func (n *TxNotifier) newConfNtfn(txid *chainhash.Hash,
|
||||
Event: NewConfirmationEvent(numConfs, func() {
|
||||
n.CancelConf(confRequest, confID)
|
||||
}),
|
||||
HeightHint: heightHint,
|
||||
HeightHint: heightHint,
|
||||
includeBlock: opts.includeBlock,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -622,7 +628,8 @@ func (n *TxNotifier) newConfNtfn(txid *chainhash.Hash,
|
||||
// UpdateConfDetails method, otherwise we will wait for the transaction/output
|
||||
// script to confirm even though it already has.
|
||||
func (n *TxNotifier) RegisterConf(txid *chainhash.Hash, pkScript []byte,
|
||||
numConfs, heightHint uint32) (*ConfRegistration, error) {
|
||||
numConfs, heightHint uint32,
|
||||
optFuncs ...NotifierOption) (*ConfRegistration, error) {
|
||||
|
||||
select {
|
||||
case <-n.quit:
|
||||
@ -630,8 +637,13 @@ func (n *TxNotifier) RegisterConf(txid *chainhash.Hash, pkScript []byte,
|
||||
default:
|
||||
}
|
||||
|
||||
opts := defaultNotifierOptions()
|
||||
for _, optFunc := range optFuncs {
|
||||
optFunc(opts)
|
||||
}
|
||||
|
||||
// We'll start by performing a series of validation checks.
|
||||
ntfn, err := n.newConfNtfn(txid, pkScript, numConfs, heightHint)
|
||||
ntfn, err := n.newConfNtfn(txid, pkScript, numConfs, heightHint, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -682,6 +694,14 @@ func (n *TxNotifier) RegisterConf(txid *chainhash.Hash, pkScript []byte,
|
||||
"registration since rescan has finished",
|
||||
ntfn.ConfRequest)
|
||||
|
||||
// The default notification we assigned above includes the
|
||||
// block along with the rest of the details. However not all
|
||||
// clients want the block, so we make a copy here w/o the block
|
||||
// if needed so we can give clients only what they ask for.
|
||||
if !ntfn.includeBlock && confSet.details != nil {
|
||||
confSet.details.Block = nil
|
||||
}
|
||||
|
||||
err := n.dispatchConfDetails(ntfn, confSet.details)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -888,7 +908,16 @@ func (n *TxNotifier) UpdateConfDetails(confRequest ConfRequest,
|
||||
// notifications that have not yet been delivered.
|
||||
confSet.details = details
|
||||
for _, ntfn := range confSet.ntfns {
|
||||
err = n.dispatchConfDetails(ntfn, details)
|
||||
// The default notification we assigned above includes the
|
||||
// block along with the rest of the details. However not all
|
||||
// clients want the block, so we make a copy here w/o the block
|
||||
// if needed so we can give clients only what they ask for.
|
||||
confDetails := *details
|
||||
if !ntfn.includeBlock {
|
||||
confDetails.Block = nil
|
||||
}
|
||||
|
||||
err = n.dispatchConfDetails(ntfn, &confDetails)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1207,7 +1236,7 @@ func (n *TxNotifier) ProcessRelevantSpendTx(tx *btcutil.Tx,
|
||||
onSpend := func(request SpendRequest, details *SpendDetail) {
|
||||
spends = append(spends, spend{&request, details})
|
||||
}
|
||||
n.filterTx(tx, nil, blockHeight, nil, onSpend)
|
||||
n.filterTx(nil, tx, blockHeight, nil, onSpend)
|
||||
|
||||
// After the transaction has been filtered, we can finally dispatch
|
||||
// notifications for each request.
|
||||
@ -1391,8 +1420,8 @@ func (n *TxNotifier) dispatchSpendDetails(ntfn *SpendNtfn, details *SpendDetail)
|
||||
// NOTE: In order to actually dispatch the relevant transaction notifications to
|
||||
// clients, NotifyHeight must be called with the same block height in order to
|
||||
// maintain correctness.
|
||||
func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
|
||||
txns []*btcutil.Tx) error {
|
||||
func (n *TxNotifier) ConnectTip(block *btcutil.Block,
|
||||
blockHeight uint32) error {
|
||||
|
||||
select {
|
||||
case <-n.quit:
|
||||
@ -1413,13 +1442,18 @@ func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
|
||||
|
||||
// First, we'll iterate over all the transactions found in this block to
|
||||
// determine if it includes any relevant transactions to the TxNotifier.
|
||||
Log.Debugf("Filtering %d txns for %d spend requests at height %d",
|
||||
len(txns), len(n.spendNotifications), blockHeight)
|
||||
for _, tx := range txns {
|
||||
n.filterTx(
|
||||
tx, blockHash, blockHeight, n.handleConfDetailsAtTip,
|
||||
n.handleSpendDetailsAtTip,
|
||||
)
|
||||
if block != nil {
|
||||
Log.Debugf("Filtering %d txns for %d spend requests at "+
|
||||
"height %d", len(block.Transactions()),
|
||||
len(n.spendNotifications), blockHeight)
|
||||
|
||||
for _, tx := range block.Transactions() {
|
||||
n.filterTx(
|
||||
block, tx, blockHeight,
|
||||
n.handleConfDetailsAtTip,
|
||||
n.handleSpendDetailsAtTip,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've determined which requests were confirmed and spent
|
||||
@ -1469,7 +1503,7 @@ func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
|
||||
// filterTx determines whether the transaction spends or confirms any
|
||||
// outstanding pending requests. The onConf and onSpend callbacks can be used to
|
||||
// retrieve all the requests fulfilled by this transaction as they occur.
|
||||
func (n *TxNotifier) filterTx(tx *btcutil.Tx, blockHash *chainhash.Hash,
|
||||
func (n *TxNotifier) filterTx(block *btcutil.Block, tx *btcutil.Tx,
|
||||
blockHeight uint32, onConf func(ConfRequest, *TxConfirmation),
|
||||
onSpend func(SpendRequest, *SpendDetail)) {
|
||||
|
||||
@ -1548,13 +1582,14 @@ func (n *TxNotifier) filterTx(tx *btcutil.Tx, blockHash *chainhash.Hash,
|
||||
notifyDetails := func(confRequest ConfRequest) {
|
||||
Log.Debugf("Found initial confirmation of %v: "+
|
||||
"height=%d, hash=%v", confRequest,
|
||||
blockHeight, blockHash)
|
||||
blockHeight, block.Hash())
|
||||
|
||||
details := &TxConfirmation{
|
||||
Tx: tx.MsgTx(),
|
||||
BlockHash: blockHash,
|
||||
BlockHash: block.Hash(),
|
||||
BlockHeight: blockHeight,
|
||||
TxIndex: uint32(tx.Index()),
|
||||
Block: block.MsgBlock(),
|
||||
}
|
||||
|
||||
onConf(confRequest, details)
|
||||
@ -1721,8 +1756,17 @@ func (n *TxNotifier) NotifyHeight(height uint32) error {
|
||||
Log.Infof("Dispatching %v confirmation notification for %v",
|
||||
ntfn.NumConfirmations, ntfn.ConfRequest)
|
||||
|
||||
// The default notification we assigned above includes the
|
||||
// block along with the rest of the details. However not all
|
||||
// clients want the block, so we make a copy here w/o the block
|
||||
// if needed so we can give clients only what they ask for.
|
||||
confDetails := *confSet.details
|
||||
if !ntfn.includeBlock {
|
||||
confDetails.Block = nil
|
||||
}
|
||||
|
||||
select {
|
||||
case ntfn.Event.Confirmed <- confSet.details:
|
||||
case ntfn.Event.Confirmed <- &confDetails:
|
||||
ntfn.dispatched = true
|
||||
case <-n.quit:
|
||||
return ErrTxNotifierExiting
|
||||
|
@ -256,7 +256,7 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{&tx1, &tx2},
|
||||
})
|
||||
|
||||
err = n.ConnectTip(block1.Hash(), 11, block1.Transactions())
|
||||
err = n.ConnectTip(block1, 11)
|
||||
require.NoError(t, err, "Failed to connect block")
|
||||
if err := n.NotifyHeight(11); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -316,7 +316,7 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) {
|
||||
// Create a new block and add it to the TxNotifier at the next height.
|
||||
// This should confirm tx2.
|
||||
block2 := btcutil.NewBlock(&wire.MsgBlock{})
|
||||
err = n.ConnectTip(block2.Hash(), 12, block2.Transactions())
|
||||
err = n.ConnectTip(block2, 12)
|
||||
require.NoError(t, err, "Failed to connect block")
|
||||
if err := n.NotifyHeight(12); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -460,7 +460,7 @@ func TestTxNotifierHistoricalConfDispatch(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{&tx3},
|
||||
})
|
||||
|
||||
err = n.ConnectTip(block.Hash(), 11, block.Transactions())
|
||||
err = n.ConnectTip(block, 11)
|
||||
require.NoError(t, err, "Failed to connect block")
|
||||
if err := n.NotifyHeight(11); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -536,7 +536,7 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) {
|
||||
block := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{spendTx},
|
||||
})
|
||||
err = n.ConnectTip(block.Hash(), 11, block.Transactions())
|
||||
err = n.ConnectTip(block, 11)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(11); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -569,7 +569,7 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) {
|
||||
block = btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{spendOfSpend},
|
||||
})
|
||||
err = n.ConnectTip(block.Hash(), 12, block.Transactions())
|
||||
err = n.ConnectTip(block, 12)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(12); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -609,7 +609,7 @@ func TestTxNotifierFutureConfDispatchReuseSafe(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{&tx1},
|
||||
})
|
||||
currentBlock++
|
||||
err = n.ConnectTip(block.Hash(), currentBlock, block.Transactions())
|
||||
err = n.ConnectTip(block, currentBlock)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(currentBlock); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -662,7 +662,7 @@ func TestTxNotifierFutureConfDispatchReuseSafe(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{&tx2},
|
||||
})
|
||||
currentBlock++
|
||||
err = n.ConnectTip(block2.Hash(), currentBlock, block2.Transactions())
|
||||
err = n.ConnectTip(block2, currentBlock)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(currentBlock); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -706,9 +706,7 @@ func TestTxNotifierFutureConfDispatchReuseSafe(t *testing.T) {
|
||||
for currentBlock < 15 {
|
||||
block := btcutil.NewBlock(&wire.MsgBlock{})
|
||||
currentBlock++
|
||||
err = n.ConnectTip(
|
||||
block.Hash(), currentBlock, block.Transactions(),
|
||||
)
|
||||
err = n.ConnectTip(block, currentBlock)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to connect block: %v", err)
|
||||
}
|
||||
@ -801,7 +799,7 @@ func TestTxNotifierHistoricalSpendDispatch(t *testing.T) {
|
||||
block := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{spendOfSpend},
|
||||
})
|
||||
err = n.ConnectTip(block.Hash(), startingHeight+1, block.Transactions())
|
||||
err = n.ConnectTip(block, startingHeight+1)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(startingHeight + 1); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1110,7 +1108,7 @@ func TestTxNotifierCancelConf(t *testing.T) {
|
||||
// Cancel the second notification before connecting the block.
|
||||
ntfn2.Event.Cancel()
|
||||
|
||||
err = n.ConnectTip(block.Hash(), startingHeight+1, block.Transactions())
|
||||
err = n.ConnectTip(block, startingHeight+1)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
|
||||
// Cancel the third notification before notifying to ensure its queued
|
||||
@ -1155,7 +1153,7 @@ func TestTxNotifierCancelConf(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{},
|
||||
})
|
||||
|
||||
err = n.ConnectTip(block1.Hash(), startingHeight+2, block1.Transactions())
|
||||
err = n.ConnectTip(block1, startingHeight+2)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
|
||||
if err := n.NotifyHeight(startingHeight + 2); err != nil {
|
||||
@ -1187,7 +1185,7 @@ func TestTxNotifierCancelConf(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{},
|
||||
})
|
||||
|
||||
err = n.ConnectTip(block2.Hash(), startingHeight+3, block2.Transactions())
|
||||
err = n.ConnectTip(block2, startingHeight+3)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
|
||||
if err := n.NotifyHeight(startingHeight + 3); err != nil {
|
||||
@ -1241,7 +1239,7 @@ func TestTxNotifierCancelSpend(t *testing.T) {
|
||||
// cancel the second request.
|
||||
n.CancelSpend(ntfn2.HistoricalDispatch.SpendRequest, 2)
|
||||
|
||||
err = n.ConnectTip(block.Hash(), startingHeight+1, block.Transactions())
|
||||
err = n.ConnectTip(block, startingHeight+1)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(startingHeight + 1); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1320,13 +1318,13 @@ func TestTxNotifierConfReorg(t *testing.T) {
|
||||
block1 := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{&tx1},
|
||||
})
|
||||
if err := n.ConnectTip(nil, 8, block1.Transactions()); err != nil {
|
||||
if err := n.ConnectTip(block1, 8); err != nil {
|
||||
t.Fatalf("Failed to connect block: %v", err)
|
||||
}
|
||||
if err := n.NotifyHeight(8); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
}
|
||||
if err := n.ConnectTip(nil, 9, nil); err != nil {
|
||||
if err := n.ConnectTip(nil, 9); err != nil {
|
||||
t.Fatalf("Failed to connect block: %v", err)
|
||||
}
|
||||
if err := n.NotifyHeight(9); err != nil {
|
||||
@ -1336,7 +1334,7 @@ func TestTxNotifierConfReorg(t *testing.T) {
|
||||
block2 := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{&tx2, &tx3},
|
||||
})
|
||||
if err := n.ConnectTip(nil, 10, block2.Transactions()); err != nil {
|
||||
if err := n.ConnectTip(block2, 10); err != nil {
|
||||
t.Fatalf("Failed to connect block: %v", err)
|
||||
}
|
||||
if err := n.NotifyHeight(10); err != nil {
|
||||
@ -1399,14 +1397,14 @@ func TestTxNotifierConfReorg(t *testing.T) {
|
||||
t.Fatalf("Failed to connect block: %v", err)
|
||||
}
|
||||
|
||||
if err := n.ConnectTip(nil, 10, nil); err != nil {
|
||||
if err := n.ConnectTip(nil, 10); err != nil {
|
||||
t.Fatalf("Failed to connect block: %v", err)
|
||||
}
|
||||
if err := n.NotifyHeight(10); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
}
|
||||
|
||||
if err := n.ConnectTip(nil, 11, nil); err != nil {
|
||||
if err := n.ConnectTip(nil, 11); err != nil {
|
||||
t.Fatalf("Failed to connect block: %v", err)
|
||||
}
|
||||
if err := n.NotifyHeight(11); err != nil {
|
||||
@ -1456,13 +1454,13 @@ func TestTxNotifierConfReorg(t *testing.T) {
|
||||
})
|
||||
block4 := btcutil.NewBlock(&wire.MsgBlock{})
|
||||
|
||||
err = n.ConnectTip(block3.Hash(), 12, block3.Transactions())
|
||||
err = n.ConnectTip(block3, 12)
|
||||
require.NoError(t, err, "Failed to connect block")
|
||||
if err := n.NotifyHeight(12); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
}
|
||||
|
||||
err = n.ConnectTip(block4.Hash(), 13, block4.Transactions())
|
||||
err = n.ConnectTip(block4, 13)
|
||||
require.NoError(t, err, "Failed to connect block")
|
||||
if err := n.NotifyHeight(13); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1600,7 +1598,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, startingHeight+1)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(startingHeight + 1); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1628,7 +1626,7 @@ func TestTxNotifierSpendReorg(t *testing.T) {
|
||||
block2 := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{spendTx2},
|
||||
})
|
||||
err = n.ConnectTip(block2.Hash(), startingHeight+2, block2.Transactions())
|
||||
err = n.ConnectTip(block2, startingHeight+2)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(startingHeight + 2); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1680,9 +1678,7 @@ func TestTxNotifierSpendReorg(t *testing.T) {
|
||||
// We'll now extend the chain with an empty block, to ensure that we can
|
||||
// properly detect when an outpoint has been re-spent at a later height.
|
||||
emptyBlock := btcutil.NewBlock(&wire.MsgBlock{})
|
||||
err = n.ConnectTip(
|
||||
emptyBlock.Hash(), startingHeight+2, emptyBlock.Transactions(),
|
||||
)
|
||||
err = n.ConnectTip(emptyBlock, startingHeight+2)
|
||||
require.NoError(t, err, "unable to disconnect block")
|
||||
if err := n.NotifyHeight(startingHeight + 2); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1703,9 +1699,7 @@ func TestTxNotifierSpendReorg(t *testing.T) {
|
||||
|
||||
// Finally, extend the chain with another block containing the same
|
||||
// spending transaction of the second outpoint.
|
||||
err = n.ConnectTip(
|
||||
block2.Hash(), startingHeight+3, block2.Transactions(),
|
||||
)
|
||||
err = n.ConnectTip(block2, startingHeight+3)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(startingHeight + 3); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1767,7 +1761,7 @@ func TestTxNotifierSpendReorgMissed(t *testing.T) {
|
||||
block := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{spendTx},
|
||||
})
|
||||
err := n.ConnectTip(block.Hash(), startingHeight+1, block.Transactions())
|
||||
err := n.ConnectTip(block, startingHeight+1)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(startingHeight + 1); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1875,7 +1869,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{&txDummy},
|
||||
})
|
||||
|
||||
err = n.ConnectTip(block1.Hash(), txDummyHeight, block1.Transactions())
|
||||
err = n.ConnectTip(block1, txDummyHeight)
|
||||
require.NoError(t, err, "Failed to connect block")
|
||||
if err := n.NotifyHeight(txDummyHeight); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1912,7 +1906,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{&tx1},
|
||||
})
|
||||
|
||||
err = n.ConnectTip(block2.Hash(), tx1Height, block2.Transactions())
|
||||
err = n.ConnectTip(block2, tx1Height)
|
||||
require.NoError(t, err, "Failed to connect block")
|
||||
if err := n.NotifyHeight(tx1Height); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -1941,7 +1935,7 @@ func TestTxNotifierConfirmHintCache(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{&tx2},
|
||||
})
|
||||
|
||||
err = n.ConnectTip(block3.Hash(), tx2Height, block3.Transactions())
|
||||
err = n.ConnectTip(block3, tx2Height)
|
||||
require.NoError(t, err, "Failed to connect block")
|
||||
if err := n.NotifyHeight(tx2Height); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -2037,9 +2031,7 @@ func TestTxNotifierSpendHintCache(t *testing.T) {
|
||||
|
||||
// Create a new empty block and extend the chain.
|
||||
emptyBlock := btcutil.NewBlock(&wire.MsgBlock{})
|
||||
err = n.ConnectTip(
|
||||
emptyBlock.Hash(), dummyHeight, emptyBlock.Transactions(),
|
||||
)
|
||||
err = n.ConnectTip(emptyBlock, dummyHeight)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(dummyHeight); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -2079,7 +2071,7 @@ func TestTxNotifierSpendHintCache(t *testing.T) {
|
||||
block1 := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{spendTx1},
|
||||
})
|
||||
err = n.ConnectTip(block1.Hash(), op1Height, block1.Transactions())
|
||||
err = n.ConnectTip(block1, op1Height)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(op1Height); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -2108,7 +2100,7 @@ func TestTxNotifierSpendHintCache(t *testing.T) {
|
||||
block2 := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{spendTx2},
|
||||
})
|
||||
err = n.ConnectTip(block2.Hash(), op2Height, block2.Transactions())
|
||||
err = n.ConnectTip(block2, op2Height)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(op2Height); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -2194,9 +2186,7 @@ func TestTxNotifierSpendDuringHistoricalRescan(t *testing.T) {
|
||||
// Create a new empty block and extend the chain.
|
||||
height := uint32(startingHeight) + 1
|
||||
emptyBlock := btcutil.NewBlock(&wire.MsgBlock{})
|
||||
err = n.ConnectTip(
|
||||
emptyBlock.Hash(), height, emptyBlock.Transactions(),
|
||||
)
|
||||
err = n.ConnectTip(emptyBlock, height)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(height); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -2237,9 +2227,7 @@ func TestTxNotifierSpendDuringHistoricalRescan(t *testing.T) {
|
||||
block = btcutil.NewBlock(&wire.MsgBlock{})
|
||||
}
|
||||
|
||||
err = n.ConnectTip(
|
||||
block.Hash(), height, block.Transactions(),
|
||||
)
|
||||
err = n.ConnectTip(block, height)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to connect block: %v", err)
|
||||
}
|
||||
@ -2290,7 +2278,7 @@ func TestTxNotifierSpendDuringHistoricalRescan(t *testing.T) {
|
||||
block2 := btcutil.NewBlock(&wire.MsgBlock{
|
||||
Transactions: []*wire.MsgTx{spendTx2},
|
||||
})
|
||||
err = n.ConnectTip(block2.Hash(), height, block2.Transactions())
|
||||
err = n.ConnectTip(block2, height)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(height); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -2309,9 +2297,7 @@ func TestTxNotifierSpendDuringHistoricalRescan(t *testing.T) {
|
||||
height++
|
||||
block := btcutil.NewBlock(&wire.MsgBlock{})
|
||||
|
||||
err := n.ConnectTip(
|
||||
block.Hash(), height, block.Transactions(),
|
||||
)
|
||||
err := n.ConnectTip(block, height)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to connect block: %v", err)
|
||||
}
|
||||
@ -2368,7 +2354,7 @@ func TestTxNotifierNtfnDone(t *testing.T) {
|
||||
Transactions: []*wire.MsgTx{tx, spendTx},
|
||||
})
|
||||
|
||||
err = n.ConnectTip(block.Hash(), 11, block.Transactions())
|
||||
err = n.ConnectTip(block, 11)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(11); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -2418,7 +2404,7 @@ func TestTxNotifierNtfnDone(t *testing.T) {
|
||||
|
||||
// We'll reconnect the block that satisfies both of these requests.
|
||||
// We should see notifications dispatched for both once again.
|
||||
err = n.ConnectTip(block.Hash(), 11, block.Transactions())
|
||||
err = n.ConnectTip(block, 11)
|
||||
require.NoError(t, err, "unable to connect block")
|
||||
if err := n.NotifyHeight(11); err != nil {
|
||||
t.Fatalf("unable to dispatch notifications: %v", err)
|
||||
@ -2442,7 +2428,7 @@ func TestTxNotifierNtfnDone(t *testing.T) {
|
||||
nextHeight := uint32(12)
|
||||
for i := nextHeight; i < nextHeight+reorgSafetyLimit; i++ {
|
||||
dummyBlock := btcutil.NewBlock(&wire.MsgBlock{})
|
||||
if err := n.ConnectTip(dummyBlock.Hash(), i, nil); err != nil {
|
||||
if err := n.ConnectTip(dummyBlock, i); err != nil {
|
||||
t.Fatalf("unable to connect block: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,8 @@ func (n *NoChainBackend) RelayFeePerKW() chainfee.SatPerKWeight {
|
||||
}
|
||||
|
||||
func (n *NoChainBackend) RegisterConfirmationsNtfn(*chainhash.Hash, []byte,
|
||||
uint32, uint32) (*chainntnfs.ConfirmationEvent, error) {
|
||||
uint32, uint32,
|
||||
...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
|
||||
|
||||
return nil, errNotImplemented
|
||||
}
|
||||
|
@ -420,7 +420,8 @@ func newMockNotifier() *mockNotifier {
|
||||
}
|
||||
|
||||
func (m *mockNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
||||
_ []byte, numConfs, _ uint32) (*chainntnfs.ConfirmationEvent, error) {
|
||||
_ []byte, numConfs, _ uint32,
|
||||
opts ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Release Notes
|
||||
|
||||
## RPC
|
||||
|
||||
The `RegisterConfirmationsNtfn` call of the `chainnotifier` RPC sub-server [now
|
||||
optionally supports returning the entire block that confirmed the
|
||||
transaction](https://github.com/lightningnetwork/lnd/pull/6730).
|
||||
|
||||
## Misc
|
||||
* Warning messages from peers are now recognized and
|
||||
[logged](https://github.com/lightningnetwork/lnd/pull/6546) by lnd.
|
||||
|
@ -164,7 +164,7 @@ type mockNotifier struct {
|
||||
}
|
||||
|
||||
func (m *mockNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
||||
_ []byte, numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, error) {
|
||||
_ []byte, numConfs, heightHint uint32, opts ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
|
||||
|
||||
if numConfs == 6 {
|
||||
return &chainntnfs.ConfirmationEvent{
|
||||
|
@ -45,6 +45,10 @@ type ConfRequest struct {
|
||||
//could have been included in a block. This should in most cases be set to the
|
||||
//broadcast height of the transaction/output script.
|
||||
HeightHint uint32 `protobuf:"varint,4,opt,name=height_hint,json=heightHint,proto3" json:"height_hint,omitempty"`
|
||||
//
|
||||
//If true, then the block that mines the specified txid/script will be
|
||||
//included in eventual the notification event.
|
||||
IncludeBlock bool `protobuf:"varint,5,opt,name=include_block,json=includeBlock,proto3" json:"include_block,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfRequest) Reset() {
|
||||
@ -107,6 +111,13 @@ func (x *ConfRequest) GetHeightHint() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ConfRequest) GetIncludeBlock() bool {
|
||||
if x != nil {
|
||||
return x.IncludeBlock
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfDetails struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -121,6 +132,10 @@ type ConfDetails struct {
|
||||
BlockHeight uint32 `protobuf:"varint,3,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"`
|
||||
// The index of the confirmed transaction within the transaction.
|
||||
TxIndex uint32 `protobuf:"varint,4,opt,name=tx_index,json=txIndex,proto3" json:"tx_index,omitempty"`
|
||||
//
|
||||
//The raw bytes of the block that mined the transaction. Only included if
|
||||
//include_block was set in the request.
|
||||
RawBlock []byte `protobuf:"bytes,5,opt,name=raw_block,json=rawBlock,proto3" json:"raw_block,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfDetails) Reset() {
|
||||
@ -183,6 +198,13 @@ func (x *ConfDetails) GetTxIndex() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ConfDetails) GetRawBlock() []byte {
|
||||
if x != nil {
|
||||
return x.RawBlock
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Reorg struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -675,86 +697,90 @@ var File_chainrpc_chainnotifier_proto protoreflect.FileDescriptor
|
||||
var file_chainrpc_chainnotifier_proto_rawDesc = []byte{
|
||||
0x0a, 0x1c, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e,
|
||||
0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08,
|
||||
0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x22, 0x77, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x73,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x73,
|
||||
0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x48, 0x69, 0x6e,
|
||||
0x74, 0x22, 0x81, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c,
|
||||
0x73, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x05, 0x72, 0x61, 0x77, 0x54, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x62,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x78,
|
||||
0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, 0x78,
|
||||
0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x07, 0x0a, 0x05, 0x52, 0x65, 0x6f, 0x72, 0x67, 0x22, 0x6a,
|
||||
0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x68, 0x61, 0x69,
|
||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
|
||||
0x48, 0x00, 0x52, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x12, 0x27, 0x0a, 0x05, 0x72, 0x65, 0x6f, 0x72,
|
||||
0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x52, 0x65, 0x6f, 0x72, 0x67, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x6f, 0x72,
|
||||
0x67, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x34, 0x0a, 0x08, 0x4f, 0x75,
|
||||
0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78,
|
||||
0x22, 0x77, 0x0a, 0x0c, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x12, 0x2e, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75,
|
||||
0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x69, 0x67,
|
||||
0x68, 0x74, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x68,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x48, 0x69, 0x6e, 0x74, 0x22, 0xfc, 0x01, 0x0a, 0x0c, 0x53, 0x70,
|
||||
0x65, 0x6e, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x3f, 0x0a, 0x11, 0x73, 0x70,
|
||||
0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
|
||||
0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x22, 0x9c, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
|
||||
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x68, 0x69, 0x6e, 0x74,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x48, 0x69,
|
||||
0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75,
|
||||
0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x9e, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x61, 0x77, 0x5f, 0x74,
|
||||
0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x72, 0x61, 0x77, 0x54, 0x78, 0x12, 0x1d,
|
||||
0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x21, 0x0a,
|
||||
0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x0d, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74,
|
||||
0x12, 0x19, 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x0d, 0x52, 0x07, 0x74, 0x78, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x72,
|
||||
0x61, 0x77, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08,
|
||||
0x72, 0x61, 0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x07, 0x0a, 0x05, 0x52, 0x65, 0x6f, 0x72,
|
||||
0x67, 0x22, 0x6a, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2b,
|
||||
0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63,
|
||||
0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x44, 0x65, 0x74, 0x61,
|
||||
0x69, 0x6c, 0x73, 0x48, 0x00, 0x52, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x12, 0x27, 0x0a, 0x05, 0x72,
|
||||
0x65, 0x6f, 0x72, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x68, 0x61,
|
||||
0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6f, 0x72, 0x67, 0x48, 0x00, 0x52, 0x05, 0x72,
|
||||
0x65, 0x6f, 0x72, 0x67, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x34, 0x0a,
|
||||
0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73,
|
||||
0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x22, 0x77, 0x0a, 0x0c, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x10, 0x73, 0x70, 0x65, 0x6e, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x72,
|
||||
0x61, 0x77, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x78, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x72, 0x61, 0x77, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x54, 0x78, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f,
|
||||
0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x73,
|
||||
0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x30, 0x0a,
|
||||
0x14, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f,
|
||||
0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x73, 0x70, 0x65,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12,
|
||||
0x27, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x69, 0x67,
|
||||
0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69,
|
||||
0x6e, 0x67, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x6e, 0x0a, 0x0a, 0x53, 0x70, 0x65, 0x6e,
|
||||
0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x48, 0x00, 0x52,
|
||||
0x05, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x05, 0x72, 0x65, 0x6f, 0x72, 0x67, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x52, 0x65, 0x6f, 0x72, 0x67, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x6f, 0x72, 0x67, 0x42,
|
||||
0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x38, 0x0a, 0x0a, 0x42, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65,
|
||||
0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67,
|
||||
0x68, 0x74, 0x32, 0xe7, 0x01, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x6f, 0x74, 0x69,
|
||||
0x66, 0x69, 0x65, 0x72, 0x12, 0x49, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4e, 0x74, 0x66,
|
||||
0x6e, 0x12, 0x15, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12,
|
||||
0x43, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, 0x6e, 0x64,
|
||||
0x4e, 0x74, 0x66, 0x6e, 0x12, 0x16, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x53, 0x70, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x63,
|
||||
0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x76, 0x65,
|
||||
0x6e, 0x74, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
||||
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x4e, 0x74, 0x66, 0x6e, 0x12, 0x14,
|
||||
0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45,
|
||||
0x70, 0x6f, 0x63, 0x68, 0x1a, 0x14, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x30, 0x01, 0x42, 0x30, 0x5a, 0x2e,
|
||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74,
|
||||
0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f,
|
||||
0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x68,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x0a, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x48, 0x69, 0x6e, 0x74, 0x22, 0xfc, 0x01, 0x0a,
|
||||
0x0c, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x3f, 0x0a,
|
||||
0x11, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x10, 0x73, 0x70,
|
||||
0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x26,
|
||||
0x0a, 0x0f, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74,
|
||||
0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x72, 0x61, 0x77, 0x53, 0x70, 0x65, 0x6e,
|
||||
0x64, 0x69, 0x6e, 0x67, 0x54, 0x78, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69,
|
||||
0x6e, 0x67, 0x5f, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x78, 0x48, 0x61, 0x73, 0x68,
|
||||
0x12, 0x30, 0x0a, 0x14, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12,
|
||||
0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x68,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x73, 0x70, 0x65,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x6e, 0x0a, 0x0a, 0x53,
|
||||
0x70, 0x65, 0x6e, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x70, 0x65,
|
||||
0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
|
||||
0x48, 0x00, 0x52, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x05, 0x72, 0x65, 0x6f,
|
||||
0x72, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6f, 0x72, 0x67, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x6f,
|
||||
0x72, 0x67, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x38, 0x0a, 0x0a, 0x42,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73,
|
||||
0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x68,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x32, 0xe7, 0x01, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4e,
|
||||
0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x49, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73,
|
||||
0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x4e, 0x74, 0x66, 0x6e, 0x12, 0x15, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x63, 0x68,
|
||||
0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
||||
0x30, 0x01, 0x12, 0x43, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x70,
|
||||
0x65, 0x6e, 0x64, 0x4e, 0x74, 0x66, 0x6e, 0x12, 0x16, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x14, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x70, 0x65, 0x6e, 0x64,
|
||||
0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, 0x73,
|
||||
0x74, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x4e, 0x74, 0x66,
|
||||
0x6e, 0x12, 0x14, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x1a, 0x14, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x30, 0x01, 0x42,
|
||||
0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69,
|
||||
0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c,
|
||||
0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x70,
|
||||
0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -72,6 +72,12 @@ message ConfRequest {
|
||||
broadcast height of the transaction/output script.
|
||||
*/
|
||||
uint32 height_hint = 4;
|
||||
|
||||
/*
|
||||
If true, then the block that mines the specified txid/script will be
|
||||
included in eventual the notification event.
|
||||
*/
|
||||
bool include_block = 5;
|
||||
}
|
||||
|
||||
message ConfDetails {
|
||||
@ -87,6 +93,12 @@ message ConfDetails {
|
||||
|
||||
// The index of the confirmed transaction within the transaction.
|
||||
uint32 tx_index = 4;
|
||||
|
||||
/*
|
||||
The raw bytes of the block that mined the transaction. Only included if
|
||||
include_block was set in the request.
|
||||
*/
|
||||
bytes raw_block = 5;
|
||||
}
|
||||
|
||||
message Reorg {
|
||||
|
@ -184,6 +184,11 @@
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "The index of the confirmed transaction within the transaction."
|
||||
},
|
||||
"raw_block": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "The raw bytes of the block that mined the transaction. Only included if\ninclude_block was set in the request."
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -222,6 +227,10 @@
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "The earliest height in the chain for which the transaction/output script\ncould have been included in a block. This should in most cases be set to the\nbroadcast height of the transaction/output script."
|
||||
},
|
||||
"include_block": {
|
||||
"type": "boolean",
|
||||
"description": "If true, then the block that mines the specified txid/script will be\nincluded in eventual the notification event."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -257,9 +257,14 @@ func (s *Server) RegisterConfirmationsNtfn(in *ConfRequest,
|
||||
var txid chainhash.Hash
|
||||
copy(txid[:], in.Txid)
|
||||
|
||||
var opts []chainntnfs.NotifierOption
|
||||
if in.IncludeBlock {
|
||||
opts = append(opts, chainntnfs.WithIncludeBlock())
|
||||
}
|
||||
|
||||
// We'll then register for the spend notification of the request.
|
||||
confEvent, err := s.cfg.ChainNotifier.RegisterConfirmationsNtfn(
|
||||
&txid, in.Script, in.NumConfs, in.HeightHint,
|
||||
&txid, in.Script, in.NumConfs, in.HeightHint, opts...,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -284,11 +289,26 @@ func (s *Server) RegisterConfirmationsNtfn(in *ConfRequest,
|
||||
return err
|
||||
}
|
||||
|
||||
// If the block was included (should only be there if
|
||||
// IncludeBlock is true), then we'll encode the bytes
|
||||
// to send with the response.
|
||||
var blockBytes []byte
|
||||
if details.Block != nil {
|
||||
var blockBuf bytes.Buffer
|
||||
err := details.Block.Serialize(&blockBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blockBytes = blockBuf.Bytes()
|
||||
}
|
||||
|
||||
rpcConfDetails := &ConfDetails{
|
||||
RawTx: rawTxBuf.Bytes(),
|
||||
BlockHash: details.BlockHash[:],
|
||||
BlockHeight: details.BlockHeight,
|
||||
TxIndex: details.TxIndex,
|
||||
RawBlock: blockBytes,
|
||||
}
|
||||
|
||||
conf := &ConfEvent{
|
||||
|
@ -1297,12 +1297,16 @@ func confirmAddress(ctx context.Context, t *harnessTest,
|
||||
|
||||
_, currentHeight, err := net.Miner.Client.GetBestBlock()
|
||||
require.NoError(t.t, err)
|
||||
|
||||
// We'll register for a conf notification, and also request the block
|
||||
// that included it as well.
|
||||
confClient, err := node.ChainClient.RegisterConfirmationsNtfn(
|
||||
ctx, &chainrpc.ConfRequest{
|
||||
Script: addrPkScript,
|
||||
Txid: txid[:],
|
||||
HeightHint: uint32(currentHeight),
|
||||
NumConfs: 1,
|
||||
Script: addrPkScript,
|
||||
Txid: txid[:],
|
||||
HeightHint: uint32(currentHeight),
|
||||
NumConfs: 1,
|
||||
IncludeBlock: true,
|
||||
},
|
||||
)
|
||||
require.NoError(t.t, err)
|
||||
@ -1310,12 +1314,18 @@ func confirmAddress(ctx context.Context, t *harnessTest,
|
||||
// Mine another block to clean up the mempool.
|
||||
mineBlocks(t, net, 1, 1)
|
||||
|
||||
// We now expect our confirmation to go through.
|
||||
// We now expect our confirmation to go through, and also that the
|
||||
// block was specified.
|
||||
confMsg, err := confClient.Recv()
|
||||
require.NoError(t.t, err)
|
||||
conf := confMsg.GetConf()
|
||||
require.NotNil(t.t, conf)
|
||||
require.Equal(t.t, conf.BlockHeight, uint32(currentHeight+1))
|
||||
require.NotNil(t.t, conf.RawBlock)
|
||||
|
||||
// We should also be able to decode the raw block.
|
||||
var blk wire.MsgBlock
|
||||
require.NoError(t.t, blk.Deserialize(bytes.NewReader(conf.RawBlock)))
|
||||
}
|
||||
|
||||
// deriveSigningKeys derives three signing keys and returns their descriptors,
|
||||
|
@ -16,8 +16,8 @@ type ChainNotifier struct {
|
||||
// RegisterConfirmationsNtfn returns a ConfirmationEvent that contains a channel
|
||||
// that the tx confirmation will go over.
|
||||
func (c *ChainNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
||||
pkScript []byte, numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent,
|
||||
error) {
|
||||
pkScript []byte, numConfs, heightHint uint32,
|
||||
opts ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
|
||||
|
||||
return &chainntnfs.ConfirmationEvent{
|
||||
Confirmed: c.ConfChan,
|
||||
|
@ -109,8 +109,8 @@ func (m *MockNotifier) sendSpend(channel chan *chainntnfs.SpendDetail,
|
||||
|
||||
// RegisterConfirmationsNtfn registers for tx confirm notifications.
|
||||
func (m *MockNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
||||
_ []byte, numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent,
|
||||
error) {
|
||||
_ []byte, numConfs, heightHint uint32,
|
||||
opt ...chainntnfs.NotifierOption) (*chainntnfs.ConfirmationEvent, error) {
|
||||
|
||||
return &chainntnfs.ConfirmationEvent{
|
||||
Confirmed: m.getConfChannel(txid),
|
||||
|
Loading…
Reference in New Issue
Block a user