From f8711659e6f30e357abb82d7f289d4c61f008c8d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 26 Dec 2016 21:45:01 -0600 Subject: [PATCH] chainntnfs/btcdnotify: populate full conf details for historical dispatch This commit modifies the historical dispatch workflow slightly to also obtain the full block in which the transaction was confirmed we we can fully populate the full TxConfirmations struct which was recently added as part of the confirmation subscription API. With this change, confirmation triggers that a reached while the demon is down, will now be deliver exactly as if the trigger was reached while the daemon was up. --- chainntnfs/btcdnotify/btcd.go | 46 ++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/chainntnfs/btcdnotify/btcd.go b/chainntnfs/btcdnotify/btcd.go index 91221234..b6ef34ad 100644 --- a/chainntnfs/btcdnotify/btcd.go +++ b/chainntnfs/btcdnotify/btcd.go @@ -344,27 +344,61 @@ out: } // attemptHistoricalDispatch tries to use historical information to decide if a -// notificaiton ca be disptahced immediately, or is partially confirmed so it +// notification ca be dispatched immediately, or is partially confirmed so it // can skip straight to the confirmations heap. func (b *BtcdNotifier) attemptHistoricalDispatch(msg *confirmationsNotification, currentHeight int32) bool { + chainntnfs.Log.Infof("Attempting to trigger dispatch for %v from "+ + "historical chain", msg.txid) + // If the transaction already has some or all of the confirmations, - // then we may be able to - // dispatch it immediately. + // then we may be able to dispatch it immediately. tx, err := b.chainConn.GetRawTransactionVerbose(msg.txid) - if err != nil { + if err != nil || tx == nil { return false } - // TODO(roasbeef): need to obtain proper hash+index info + // As we need to fully populate the returned TxConfirmation struct, + // grab the block in which the transaction was confirmed so we can + // locate its exact index within the block. + blockHash, err := wire.NewShaHashFromStr(tx.BlockHash) + if err != nil { + chainntnfs.Log.Errorf("unable to get block hash %v for "+ + "historical dispatch: %v", tx.BlockHash, err) + return false + } + block, err := b.chainConn.GetBlock(blockHash) + if err != nil { + chainntnfs.Log.Errorf("unable to get block hash: %v", err) + return false + } + + txHash, err := wire.NewShaHashFromStr(tx.Hash) + if err != nil { + chainntnfs.Log.Errorf("unable to convert to hash: %v", err) + return false + } + + // If the block obtained, locate the transaction's index within the + // block so we can give the subscriber full confirmation details. + var txIndex uint32 + for i, t := range block.Transactions { + h := t.TxSha() + if txHash.IsEqual(&h) { + txIndex = uint32(i) + } + } + confDetails := &chainntnfs.TxConfirmation{ + BlockHash: blockHash, BlockHeight: uint32(currentHeight) - uint32(tx.Confirmations), + TxIndex: txIndex, } // If the transaction has more that enough confirmations, then we can // dispatch it immediately after obtaining for information w.r.t - // exaclty *when* if got all its confirmations. + // exactly *when* if got all its confirmations. if uint32(tx.Confirmations) >= msg.numConfirmations { msg.finConf <- confDetails return true