chainntnfs: include transaction in confirmation details
This commit is contained in:
parent
5ab30cf7ea
commit
50650d054e
@ -1,6 +1,8 @@
|
|||||||
package bitcoindnotify
|
package bitcoindnotify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
@ -462,7 +464,7 @@ func (b *BitcoindNotifier) confDetailsFromTxIndex(txid *chainhash.Hash,
|
|||||||
|
|
||||||
// If the transaction has some or all of its confirmations required,
|
// If the transaction has some or all of its confirmations required,
|
||||||
// then we may be able to dispatch it immediately.
|
// then we may be able to dispatch it immediately.
|
||||||
tx, err := b.chainConn.GetRawTransactionVerbose(txid)
|
rawTxRes, err := b.chainConn.GetRawTransactionVerbose(txid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If the transaction lookup was successful, but it wasn't found
|
// If the transaction lookup was successful, but it wasn't found
|
||||||
// within the index itself, then we can exit early. We'll also
|
// within the index itself, then we can exit early. We'll also
|
||||||
@ -483,18 +485,18 @@ func (b *BitcoindNotifier) confDetailsFromTxIndex(txid *chainhash.Hash,
|
|||||||
// Make sure we actually retrieved a transaction that is included in a
|
// Make sure we actually retrieved a transaction that is included in a
|
||||||
// block. If not, the transaction must be unconfirmed (in the mempool),
|
// block. If not, the transaction must be unconfirmed (in the mempool),
|
||||||
// and we'll return TxFoundMempool together with a nil TxConfirmation.
|
// and we'll return TxFoundMempool together with a nil TxConfirmation.
|
||||||
if tx.BlockHash == "" {
|
if rawTxRes.BlockHash == "" {
|
||||||
return nil, chainntnfs.TxFoundMempool, nil
|
return nil, chainntnfs.TxFoundMempool, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// As we need to fully populate the returned TxConfirmation struct,
|
// As we need to fully populate the returned TxConfirmation struct,
|
||||||
// grab the block in which the transaction was confirmed so we can
|
// grab the block in which the transaction was confirmed so we can
|
||||||
// locate its exact index within the block.
|
// locate its exact index within the block.
|
||||||
blockHash, err := chainhash.NewHashFromStr(tx.BlockHash)
|
blockHash, err := chainhash.NewHashFromStr(rawTxRes.BlockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, chainntnfs.TxNotFoundIndex,
|
return nil, chainntnfs.TxNotFoundIndex,
|
||||||
fmt.Errorf("unable to get block hash %v for "+
|
fmt.Errorf("unable to get block hash %v for "+
|
||||||
"historical dispatch: %v", tx.BlockHash, err)
|
"historical dispatch: %v", rawTxRes.BlockHash, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err := b.chainConn.GetBlockVerbose(blockHash)
|
block, err := b.chainConn.GetBlockVerbose(blockHash)
|
||||||
@ -506,23 +508,39 @@ func (b *BitcoindNotifier) confDetailsFromTxIndex(txid *chainhash.Hash,
|
|||||||
|
|
||||||
// If the block was obtained, locate the transaction's index within the
|
// If the block was obtained, locate the transaction's index within the
|
||||||
// block so we can give the subscriber full confirmation details.
|
// block so we can give the subscriber full confirmation details.
|
||||||
targetTxidStr := txid.String()
|
txidStr := txid.String()
|
||||||
for txIndex, txHash := range block.Tx {
|
for txIndex, txHash := range block.Tx {
|
||||||
if txHash == targetTxidStr {
|
if txHash != txidStr {
|
||||||
details := &chainntnfs.TxConfirmation{
|
continue
|
||||||
BlockHash: blockHash,
|
|
||||||
BlockHeight: uint32(block.Height),
|
|
||||||
TxIndex: uint32(txIndex),
|
|
||||||
}
|
|
||||||
return details, chainntnfs.TxFoundIndex, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deserialize the hex-encoded transaction to include it in the
|
||||||
|
// confirmation details.
|
||||||
|
rawTx, err := hex.DecodeString(rawTxRes.Hex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, chainntnfs.TxFoundIndex,
|
||||||
|
fmt.Errorf("unable to deserialize tx %v: %v",
|
||||||
|
txHash, err)
|
||||||
|
}
|
||||||
|
var tx wire.MsgTx
|
||||||
|
if err := tx.Deserialize(bytes.NewReader(rawTx)); err != nil {
|
||||||
|
return nil, chainntnfs.TxFoundIndex,
|
||||||
|
fmt.Errorf("unable to deserialize tx %v: %v",
|
||||||
|
txHash, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &chainntnfs.TxConfirmation{
|
||||||
|
Tx: &tx,
|
||||||
|
BlockHash: blockHash,
|
||||||
|
BlockHeight: uint32(block.Height),
|
||||||
|
TxIndex: uint32(txIndex),
|
||||||
|
}, chainntnfs.TxFoundIndex, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// We return an error because we should have found the transaction
|
// We return an error because we should have found the transaction
|
||||||
// within the block, but didn't.
|
// within the block, but didn't.
|
||||||
return nil, chainntnfs.TxNotFoundIndex,
|
return nil, chainntnfs.TxNotFoundIndex, fmt.Errorf("unable to locate "+
|
||||||
fmt.Errorf("unable to locate tx %v in block %v", txid,
|
"tx %v in block %v", txid, blockHash)
|
||||||
blockHash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// confDetailsManually looks up whether a transaction/output script has already
|
// confDetailsManually looks up whether a transaction/output script has already
|
||||||
@ -568,6 +586,7 @@ func (b *BitcoindNotifier) confDetailsManually(confRequest chainntnfs.ConfReques
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &chainntnfs.TxConfirmation{
|
return &chainntnfs.TxConfirmation{
|
||||||
|
Tx: tx,
|
||||||
BlockHash: blockHash,
|
BlockHash: blockHash,
|
||||||
BlockHeight: height,
|
BlockHeight: height,
|
||||||
TxIndex: uint32(txIndex),
|
TxIndex: uint32(txIndex),
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package btcdnotify
|
package btcdnotify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
@ -514,7 +516,7 @@ func (b *BtcdNotifier) confDetailsFromTxIndex(txid *chainhash.Hash,
|
|||||||
|
|
||||||
// If the transaction has some or all of its confirmations required,
|
// If the transaction has some or all of its confirmations required,
|
||||||
// then we may be able to dispatch it immediately.
|
// then we may be able to dispatch it immediately.
|
||||||
tx, err := b.chainConn.GetRawTransactionVerbose(txid)
|
rawTxRes, err := b.chainConn.GetRawTransactionVerbose(txid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If the transaction lookup was successful, but it wasn't found
|
// If the transaction lookup was successful, but it wasn't found
|
||||||
// within the index itself, then we can exit early. We'll also
|
// within the index itself, then we can exit early. We'll also
|
||||||
@ -535,20 +537,19 @@ func (b *BtcdNotifier) confDetailsFromTxIndex(txid *chainhash.Hash,
|
|||||||
// Make sure we actually retrieved a transaction that is included in a
|
// Make sure we actually retrieved a transaction that is included in a
|
||||||
// block. If not, the transaction must be unconfirmed (in the mempool),
|
// block. If not, the transaction must be unconfirmed (in the mempool),
|
||||||
// and we'll return TxFoundMempool together with a nil TxConfirmation.
|
// and we'll return TxFoundMempool together with a nil TxConfirmation.
|
||||||
if tx.BlockHash == "" {
|
if rawTxRes.BlockHash == "" {
|
||||||
return nil, chainntnfs.TxFoundMempool, nil
|
return nil, chainntnfs.TxFoundMempool, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// As we need to fully populate the returned TxConfirmation struct,
|
// As we need to fully populate the returned TxConfirmation struct,
|
||||||
// grab the block in which the transaction was confirmed so we can
|
// grab the block in which the transaction was confirmed so we can
|
||||||
// locate its exact index within the block.
|
// locate its exact index within the block.
|
||||||
blockHash, err := chainhash.NewHashFromStr(tx.BlockHash)
|
blockHash, err := chainhash.NewHashFromStr(rawTxRes.BlockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, chainntnfs.TxNotFoundIndex,
|
return nil, chainntnfs.TxNotFoundIndex,
|
||||||
fmt.Errorf("unable to get block hash %v for "+
|
fmt.Errorf("unable to get block hash %v for "+
|
||||||
"historical dispatch: %v", tx.BlockHash, err)
|
"historical dispatch: %v", rawTxRes.BlockHash, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err := b.chainConn.GetBlockVerbose(blockHash)
|
block, err := b.chainConn.GetBlockVerbose(blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, chainntnfs.TxNotFoundIndex,
|
return nil, chainntnfs.TxNotFoundIndex,
|
||||||
@ -558,23 +559,39 @@ func (b *BtcdNotifier) confDetailsFromTxIndex(txid *chainhash.Hash,
|
|||||||
|
|
||||||
// If the block was obtained, locate the transaction's index within the
|
// If the block was obtained, locate the transaction's index within the
|
||||||
// block so we can give the subscriber full confirmation details.
|
// block so we can give the subscriber full confirmation details.
|
||||||
targetTxidStr := txid.String()
|
txidStr := txid.String()
|
||||||
for txIndex, txHash := range block.Tx {
|
for txIndex, txHash := range block.Tx {
|
||||||
if txHash == targetTxidStr {
|
if txHash != txidStr {
|
||||||
details := &chainntnfs.TxConfirmation{
|
continue
|
||||||
BlockHash: blockHash,
|
|
||||||
BlockHeight: uint32(block.Height),
|
|
||||||
TxIndex: uint32(txIndex),
|
|
||||||
}
|
|
||||||
return details, chainntnfs.TxFoundIndex, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deserialize the hex-encoded transaction to include it in the
|
||||||
|
// confirmation details.
|
||||||
|
rawTx, err := hex.DecodeString(rawTxRes.Hex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, chainntnfs.TxFoundIndex,
|
||||||
|
fmt.Errorf("unable to deserialize tx %v: %v",
|
||||||
|
txHash, err)
|
||||||
|
}
|
||||||
|
var tx wire.MsgTx
|
||||||
|
if err := tx.Deserialize(bytes.NewReader(rawTx)); err != nil {
|
||||||
|
return nil, chainntnfs.TxFoundIndex,
|
||||||
|
fmt.Errorf("unable to deserialize tx %v: %v",
|
||||||
|
txHash, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &chainntnfs.TxConfirmation{
|
||||||
|
Tx: &tx,
|
||||||
|
BlockHash: blockHash,
|
||||||
|
BlockHeight: uint32(block.Height),
|
||||||
|
TxIndex: uint32(txIndex),
|
||||||
|
}, chainntnfs.TxFoundIndex, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// We return an error because we should have found the transaction
|
// We return an error because we should have found the transaction
|
||||||
// within the block, but didn't.
|
// within the block, but didn't.
|
||||||
return nil, chainntnfs.TxNotFoundIndex,
|
return nil, chainntnfs.TxNotFoundIndex, fmt.Errorf("unable to locate "+
|
||||||
fmt.Errorf("unable to locate tx %v in block %v", txid,
|
"tx %v in block %v", txid, blockHash)
|
||||||
blockHash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// confDetailsManually looks up whether a transaction/output script has already
|
// confDetailsManually looks up whether a transaction/output script has already
|
||||||
@ -621,6 +638,7 @@ func (b *BtcdNotifier) confDetailsManually(confRequest chainntnfs.ConfRequest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &chainntnfs.TxConfirmation{
|
return &chainntnfs.TxConfirmation{
|
||||||
|
Tx: tx,
|
||||||
BlockHash: blockHash,
|
BlockHash: blockHash,
|
||||||
BlockHeight: height,
|
BlockHeight: height,
|
||||||
TxIndex: uint32(txIndex),
|
TxIndex: uint32(txIndex),
|
||||||
|
@ -150,6 +150,9 @@ type TxConfirmation struct {
|
|||||||
// TxIndex is the index within the block of the ultimate confirmed
|
// TxIndex is the index within the block of the ultimate confirmed
|
||||||
// transaction.
|
// transaction.
|
||||||
TxIndex uint32
|
TxIndex uint32
|
||||||
|
|
||||||
|
// Tx is the transaction for which the notification was requested for.
|
||||||
|
Tx *wire.MsgTx
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfirmationEvent encapsulates a confirmation notification. With this struct,
|
// ConfirmationEvent encapsulates a confirmation notification. With this struct,
|
||||||
|
@ -563,6 +563,7 @@ func (n *NeutrinoNotifier) historicalConfDetails(confRequest chainntnfs.ConfRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &chainntnfs.TxConfirmation{
|
return &chainntnfs.TxConfirmation{
|
||||||
|
Tx: tx.MsgTx(),
|
||||||
BlockHash: blockHash,
|
BlockHash: blockHash,
|
||||||
BlockHeight: scanHeight,
|
BlockHeight: scanHeight,
|
||||||
TxIndex: uint32(i),
|
TxIndex: uint32(i),
|
||||||
|
@ -1226,6 +1226,7 @@ func (n *TxNotifier) filterTx(tx *btcutil.Tx, blockHash *chainhash.Hash,
|
|||||||
blockHeight, blockHash)
|
blockHeight, blockHash)
|
||||||
|
|
||||||
details := &TxConfirmation{
|
details := &TxConfirmation{
|
||||||
|
Tx: tx.MsgTx(),
|
||||||
BlockHash: blockHash,
|
BlockHash: blockHash,
|
||||||
BlockHeight: blockHeight,
|
BlockHeight: blockHeight,
|
||||||
TxIndex: uint32(tx.Index()),
|
TxIndex: uint32(tx.Index()),
|
||||||
|
@ -256,6 +256,7 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) {
|
|||||||
BlockHash: block1.Hash(),
|
BlockHash: block1.Hash(),
|
||||||
BlockHeight: 11,
|
BlockHeight: 11,
|
||||||
TxIndex: 0,
|
TxIndex: 0,
|
||||||
|
Tx: &tx1,
|
||||||
}
|
}
|
||||||
assertConfDetails(t, txConf, &expectedConf)
|
assertConfDetails(t, txConf, &expectedConf)
|
||||||
default:
|
default:
|
||||||
@ -327,6 +328,7 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) {
|
|||||||
BlockHash: block1.Hash(),
|
BlockHash: block1.Hash(),
|
||||||
BlockHeight: 11,
|
BlockHeight: 11,
|
||||||
TxIndex: 1,
|
TxIndex: 1,
|
||||||
|
Tx: &tx2,
|
||||||
}
|
}
|
||||||
assertConfDetails(t, txConf, &expectedConf)
|
assertConfDetails(t, txConf, &expectedConf)
|
||||||
default:
|
default:
|
||||||
@ -386,6 +388,7 @@ func TestTxNotifierHistoricalConfDispatch(t *testing.T) {
|
|||||||
BlockHash: &chainntnfs.ZeroHash,
|
BlockHash: &chainntnfs.ZeroHash,
|
||||||
BlockHeight: 9,
|
BlockHeight: 9,
|
||||||
TxIndex: 1,
|
TxIndex: 1,
|
||||||
|
Tx: &tx1,
|
||||||
}
|
}
|
||||||
err := n.UpdateConfDetails(ntfn1.ConfRequest, &txConf1)
|
err := n.UpdateConfDetails(ntfn1.ConfRequest, &txConf1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -419,6 +422,7 @@ func TestTxNotifierHistoricalConfDispatch(t *testing.T) {
|
|||||||
BlockHash: &chainntnfs.ZeroHash,
|
BlockHash: &chainntnfs.ZeroHash,
|
||||||
BlockHeight: 9,
|
BlockHeight: 9,
|
||||||
TxIndex: 2,
|
TxIndex: 2,
|
||||||
|
Tx: &tx2,
|
||||||
}
|
}
|
||||||
err = n.UpdateConfDetails(ntfn2.ConfRequest, &txConf2)
|
err = n.UpdateConfDetails(ntfn2.ConfRequest, &txConf2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1344,6 +1348,7 @@ func TestTxNotifierConfReorg(t *testing.T) {
|
|||||||
BlockHash: block3.Hash(),
|
BlockHash: block3.Hash(),
|
||||||
BlockHeight: 12,
|
BlockHeight: 12,
|
||||||
TxIndex: 0,
|
TxIndex: 0,
|
||||||
|
Tx: &tx2,
|
||||||
}
|
}
|
||||||
assertConfDetails(t, txConf, &expectedConf)
|
assertConfDetails(t, txConf, &expectedConf)
|
||||||
default:
|
default:
|
||||||
@ -1374,6 +1379,7 @@ func TestTxNotifierConfReorg(t *testing.T) {
|
|||||||
BlockHash: block3.Hash(),
|
BlockHash: block3.Hash(),
|
||||||
BlockHeight: 12,
|
BlockHeight: 12,
|
||||||
TxIndex: 1,
|
TxIndex: 1,
|
||||||
|
Tx: &tx3,
|
||||||
}
|
}
|
||||||
assertConfDetails(t, txConf, &expectedConf)
|
assertConfDetails(t, txConf, &expectedConf)
|
||||||
default:
|
default:
|
||||||
@ -2106,6 +2112,10 @@ func assertConfDetails(t *testing.T, result, expected *chainntnfs.TxConfirmation
|
|||||||
t.Fatalf("Incorrect tx index in confirmation details: "+
|
t.Fatalf("Incorrect tx index in confirmation details: "+
|
||||||
"expected %d, got %d", expected.TxIndex, result.TxIndex)
|
"expected %d, got %d", expected.TxIndex, result.TxIndex)
|
||||||
}
|
}
|
||||||
|
if result.Tx.TxHash() != expected.Tx.TxHash() {
|
||||||
|
t.Fatalf("expected tx hash %v, got %v", expected.Tx.TxHash(),
|
||||||
|
result.Tx.TxHash())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertSpendDetails(t *testing.T, result, expected *chainntnfs.SpendDetail) {
|
func assertSpendDetails(t *testing.T, result, expected *chainntnfs.SpendDetail) {
|
||||||
|
Loading…
Reference in New Issue
Block a user