From 13fb8665749e03e79b8324ccf740b235c36c09f7 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 26 Feb 2018 13:37:58 -0500 Subject: [PATCH 1/2] chainntnfs: remove txindex requirement when registering notfications Before this commit, we relied on the need of full nodes to enable the transaction index. This allowed us to fetch historical details about transactions in order to register and dispatch confirmation and spend notifications. This commit allows us to drop that requirement by providing a fallback method to use when the transaction index is not enabled. This fallback method relies on manually scanning blocks for the transactions requested, starting from the earliest height the transactions could have been included in, to the current height in the chain. --- chainntnfs/bitcoindnotify/bitcoind.go | 216 +++++++++++++++++++------- chainntnfs/btcdnotify/btcd.go | 211 ++++++++++++++++++------- 2 files changed, 317 insertions(+), 110 deletions(-) diff --git a/chainntnfs/bitcoindnotify/bitcoind.go b/chainntnfs/bitcoindnotify/bitcoind.go index 9c3c9818..a729d044 100644 --- a/chainntnfs/bitcoindnotify/bitcoind.go +++ b/chainntnfs/bitcoindnotify/bitcoind.go @@ -46,7 +46,9 @@ type chainUpdate struct { } // TODO(roasbeef): generalize struct below: -// * move chans to config, allow outside callers to handle send conditions +// * move chans to config +// * extract common code +// * allow outside callers to handle send conditions // BitcoindNotifier implements the ChainNotifier interface using a bitcoind // chain client. Multiple concurrent clients are supported. All notifications @@ -235,17 +237,25 @@ out: } b.spendNotifications[op][msg.spendID] = msg b.chainConn.NotifySpent([]*wire.OutPoint{&op}) - case *confirmationsNotification: - chainntnfs.Log.Infof("New confirmations "+ + case *confirmationNotification: + chainntnfs.Log.Infof("New confirmation "+ "subscription: txid=%v, numconfs=%v", msg.TxID, msg.NumConfirmations) - // Lookup whether the transaction is already included in the - // active chain. - txConf, err := b.historicalConfDetails(msg.TxID) + _, currentHeight, err := b.chainConn.GetBestBlock() if err != nil { chainntnfs.Log.Error(err) } + + // Lookup whether the transaction is already included in the + // active chain. + txConf, err := b.historicalConfDetails( + msg.TxID, msg.heightHint, uint32(currentHeight), + ) + if err != nil { + chainntnfs.Log.Error(err) + } + err = b.txConfNotifier.Register(&msg.ConfNtfn, txConf) if err != nil { chainntnfs.Log.Error(err) @@ -367,23 +377,50 @@ func (b *BitcoindNotifier) handleRelevantTx(tx chain.RelevantTx, bestHeight int3 // historicalConfDetails looks up whether a transaction is already included in a // block in the active chain and, if so, returns details about the confirmation. func (b *BitcoindNotifier) historicalConfDetails(txid *chainhash.Hash, + heightHint, currentHeight uint32) (*chainntnfs.TxConfirmation, error) { + + // First, we'll attempt to retrieve the transaction details using the + // backend node's transaction index. + txConf, err := b.confDetailsFromTxIndex(txid) + if err != nil { + return nil, err + } + + if txConf != nil { + return txConf, nil + } + + // If the backend node's transaction index is not enabled, then we'll + // fall back to manually scanning the chain's blocks, looking for the + // block where the transaction was included in. + return b.confDetailsManually(txid, heightHint, currentHeight) +} + +// confDetailsFromTxIndex looks up whether a transaction is already included +// in a block in the active chain by using the backend node's transaction index. +// If the transaction is found, its confirmation details are returned. +// Otherwise, nil is returned. +func (b *BitcoindNotifier) confDetailsFromTxIndex(txid *chainhash.Hash, ) (*chainntnfs.TxConfirmation, error) { - // If the transaction already has some or all of the confirmations, + // If the transaction has some or all of its confirmations required, // then we may be able to dispatch it immediately. - // TODO: fall back to scanning blocks if txindex isn't on. tx, err := b.chainConn.GetRawTransactionVerbose(txid) - if err != nil || tx == nil || tx.BlockHash == "" { - if err == nil { - return nil, nil + if err != nil { + // Avoid returning an error if the transaction index is not + // enabled to proceed with fallback methods. + jsonErr, ok := err.(*btcjson.RPCError) + if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo { + return nil, fmt.Errorf("unable to query for txid "+ + "%v: %v", txid, err) } - // Do not return an error if the transaction was not found. - if jsonErr, ok := err.(*btcjson.RPCError); ok { - if jsonErr.Code == btcjson.ErrRPCNoTxInfo { - return nil, nil - } - } - return nil, fmt.Errorf("unable to query for txid(%v): %v", txid, err) + } + + // Make sure we actually retrieved a transaction that is included in a + // block. Without this, we won't be able to retrieve its confirmation + // details. + if tx == nil || tx.BlockHash == "" { + return nil, nil } // As we need to fully populate the returned TxConfirmation struct, @@ -391,36 +428,76 @@ func (b *BitcoindNotifier) historicalConfDetails(txid *chainhash.Hash, // locate its exact index within the block. blockHash, err := chainhash.NewHashFromStr(tx.BlockHash) if err != nil { - return nil, fmt.Errorf("unable to get block hash %v for historical "+ - "dispatch: %v", tx.BlockHash, err) - } - block, err := b.chainConn.GetBlockVerbose(blockHash) - if err != nil { - return nil, fmt.Errorf("unable to get block hash: %v", err) + return nil, fmt.Errorf("unable to get block hash %v for "+ + "historical dispatch: %v", tx.BlockHash, err) } - // If the block obtained, locate the transaction's index within the + block, err := b.chainConn.GetBlockVerbose(blockHash) + if err != nil { + return nil, fmt.Errorf("unable to get block with hash %v for "+ + "historical dispatch: %v", blockHash, err) + } + + // If the block was obtained, locate the transaction's index within the // block so we can give the subscriber full confirmation details. - txIndex := -1 targetTxidStr := txid.String() - for i, txHash := range block.Tx { + for txIndex, txHash := range block.Tx { if txHash == targetTxidStr { - txIndex = i - break + return &chainntnfs.TxConfirmation{ + BlockHash: blockHash, + BlockHeight: uint32(block.Height), + TxIndex: uint32(txIndex), + }, nil } } - if txIndex == -1 { - return nil, fmt.Errorf("unable to locate tx %v in block %v", - txid, blockHash) + // We return an error because we should have found the transaction + // within the block, but didn't. + return nil, fmt.Errorf("unable to locate tx %v in block %v", txid, + blockHash) +} + +// confDetailsManually looks up whether a transaction is already included in a +// block in the active chain by scanning the chain's blocks, starting from the +// earliest height the transaction could have been included in, to the current +// height in the chain. If the transaction is found, its confirmation details +// are returned. Otherwise, nil is returned. +func (b *BitcoindNotifier) confDetailsManually(txid *chainhash.Hash, + heightHint, currentHeight uint32) (*chainntnfs.TxConfirmation, error) { + + targetTxidStr := txid.String() + + // Begin scanning blocks at every height to determine where the + // transaction was included in. + for height := heightHint; height <= currentHeight; height++ { + blockHash, err := b.chainConn.GetBlockHash(int64(height)) + if err != nil { + return nil, fmt.Errorf("unable to get hash from block "+ + "with height %d", height) + } + + block, err := b.chainConn.GetBlockVerbose(blockHash) + if err != nil { + return nil, fmt.Errorf("unable to get block with hash "+ + "%v: %v", blockHash, err) + } + + for txIndex, txHash := range block.Tx { + // If we're able to find the transaction in this block, + // return its confirmation details. + if txHash == targetTxidStr { + return &chainntnfs.TxConfirmation{ + BlockHash: blockHash, + BlockHeight: height, + TxIndex: uint32(txIndex), + }, nil + } + } } - txConf := chainntnfs.TxConfirmation{ - BlockHash: blockHash, - BlockHeight: uint32(block.Height), - TxIndex: uint32(txIndex), - } - return &txConf, nil + // If we reach here, then we were not able to find the transaction + // within a block, so we avoid returning an error. + return nil, nil } // notifyBlockEpochs notifies all registered block epoch clients of the newly @@ -451,6 +528,8 @@ type spendNotification struct { spendChan chan *chainntnfs.SpendDetail spendID uint64 + + heightHint uint32 } // spendCancel is a message sent to the BitcoindNotifier when a client wishes @@ -466,9 +545,10 @@ type spendCancel struct { // RegisterSpendNtfn registers an intent to be notified once the target // outpoint has been spent by a transaction on-chain. Once a spend of the target // outpoint has been detected, the details of the spending event will be sent -// across the 'Spend' channel. +// across the 'Spend' channel. The heightHint should represent the earliest +// height in the chain where the transaction could have been spent in. func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, - _ uint32, _ bool) (*chainntnfs.SpendEvent, error) { + heightHint uint32, _ bool) (*chainntnfs.SpendEvent, error) { ntfn := &spendNotification{ targetOutpoint: outpoint, @@ -486,21 +566,46 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, return nil, err } - // The following conditional checks to ensure that when a spend notification - // is registered, the output hasn't already been spent. If the output - // is no longer in the UTXO set, the chain will be rescanned from the point - // where the output was added. The rescan will dispatch the notification. - txout, err := b.chainConn.GetTxOut(&outpoint.Hash, outpoint.Index, true) + // The following conditional checks to ensure that when a spend + // notification is registered, the output hasn't already been spent. If + // the output is no longer in the UTXO set, the chain will be rescanned + // from the point where the output was added. The rescan will dispatch + // the notification. + txOut, err := b.chainConn.GetTxOut(&outpoint.Hash, outpoint.Index, true) if err != nil { return nil, err } - if txout == nil { - // TODO: fall back to scanning blocks if txindex isn't on. - transaction, err := b.chainConn.GetRawTransactionVerbose(&outpoint.Hash) + if txOut == nil { + // First, we'll attempt to retrieve the transaction's block hash + // using the backend's transaction index. + tx, err := b.chainConn.GetRawTransactionVerbose(&outpoint.Hash) if err != nil { + // Avoid returning an error if the transaction was not + // found to proceed with fallback methods. jsonErr, ok := err.(*btcjson.RPCError) if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo { + return nil, fmt.Errorf("unable to query for "+ + "txid %v: %v", outpoint.Hash, err) + } + } + + var blockHash *chainhash.Hash + if tx != nil && tx.BlockHash != "" { + // If we're able to retrieve a valid block hash from the + // transaction, then we'll use it as our rescan starting + // point. + blockHash, err = chainhash.NewHashFromStr(tx.BlockHash) + if err != nil { + return nil, err + } + } else { + // Otherwise, we'll attempt to retrieve the hash for the + // block at the heightHint. + blockHash, err = b.chainConn.GetBlockHash( + int64(heightHint), + ) + if err != nil { return nil, err } } @@ -510,8 +615,8 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // error when scanning for blocks. This can happens in the case // of a race condition, wherein the output itself is unspent, // and only arrives in the mempool after the getxout call. - if transaction != nil && transaction.BlockHash != "" { - startHash, err := chainhash.NewHashFromStr(transaction.BlockHash) + if blockHash != nil { + startHash, err := chainhash.NewHashFromStr(tx.BlockHash) if err != nil { return nil, err } @@ -564,7 +669,6 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, } } } - } } @@ -599,22 +703,24 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // confirmationNotification represents a client's intent to receive a // notification once the target txid reaches numConfirmations confirmations. -type confirmationsNotification struct { +type confirmationNotification struct { chainntnfs.ConfNtfn + heightHint uint32 } // RegisterConfirmationsNtfn registers a notification with BitcoindNotifier // which will be triggered once the txid reaches numConfs number of // confirmations. func (b *BitcoindNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash, - numConfs, _ uint32) (*chainntnfs.ConfirmationEvent, error) { + numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, error) { - ntfn := &confirmationsNotification{ - chainntnfs.ConfNtfn{ + ntfn := &confirmationNotification{ + ConfNtfn: chainntnfs.ConfNtfn{ TxID: txid, NumConfirmations: numConfs, Event: chainntnfs.NewConfirmationEvent(numConfs), }, + heightHint: heightHint, } select { diff --git a/chainntnfs/btcdnotify/btcd.go b/chainntnfs/btcdnotify/btcd.go index 554ef041..2163fc5d 100644 --- a/chainntnfs/btcdnotify/btcd.go +++ b/chainntnfs/btcdnotify/btcd.go @@ -298,17 +298,20 @@ out: b.spendNotifications[op] = make(map[uint64]*spendNotification) } b.spendNotifications[op][msg.spendID] = msg - case *confirmationsNotification: - chainntnfs.Log.Infof("New confirmations "+ + case *confirmationNotification: + chainntnfs.Log.Infof("New confirmation "+ "subscription: txid=%v, numconfs=%v", msg.TxID, msg.NumConfirmations) // Lookup whether the transaction is already included in the // active chain. - txConf, err := b.historicalConfDetails(msg.TxID) + txConf, err := b.historicalConfDetails( + msg.TxID, msg.heightHint, uint32(currentHeight), + ) if err != nil { chainntnfs.Log.Error(err) } + err = b.txConfNotifier.Register(&msg.ConfNtfn, txConf) if err != nil { chainntnfs.Log.Error(err) @@ -458,22 +461,50 @@ out: // historicalConfDetails looks up whether a transaction is already included in a // block in the active chain and, if so, returns details about the confirmation. func (b *BtcdNotifier) historicalConfDetails(txid *chainhash.Hash, + heightHint, currentHeight uint32) (*chainntnfs.TxConfirmation, error) { + + // First, we'll attempt to retrieve the transaction details using the + // backend node's transaction index. + txConf, err := b.confDetailsFromTxIndex(txid) + if err != nil { + return nil, err + } + + if txConf != nil { + return txConf, nil + } + + // If the backend node's transaction index is not enabled, then we'll + // fall back to manually scanning the chain's blocks, looking for the + // block where the transaction was included in. + return b.confDetailsManually(txid, heightHint, currentHeight) +} + +// confDetailsFromTxIndex looks up whether a transaction is already included +// in a block in the active chain by using the backend node's transaction index. +// If the transaction is found, its confirmation details are returned. +// Otherwise, nil is returned. +func (b *BtcdNotifier) confDetailsFromTxIndex(txid *chainhash.Hash, ) (*chainntnfs.TxConfirmation, error) { - // If the transaction already has some or all of the confirmations, + // If the transaction has some or all of its confirmations required, // then we may be able to dispatch it immediately. tx, err := b.chainConn.GetRawTransactionVerbose(txid) - if err != nil || tx == nil || tx.BlockHash == "" { - if err == nil { - return nil, nil + if err != nil { + // Avoid returning an error if the transaction index is not + // enabled to proceed with fallback methods. + jsonErr, ok := err.(*btcjson.RPCError) + if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo { + return nil, fmt.Errorf("unable to query for txid "+ + "%v: %v", txid, err) } - // Do not return an error if the transaction was not found. - if jsonErr, ok := err.(*btcjson.RPCError); ok { - if jsonErr.Code == btcjson.ErrRPCNoTxInfo { - return nil, nil - } - } - return nil, fmt.Errorf("unable to query for txid(%v): %v", txid, err) + } + + // Make sure we actually retrieved a transaction that is included in a + // block. Without this, we won't be able to retrieve its confirmation + // details. + if tx == nil || tx.BlockHash == "" { + return nil, nil } // As we need to fully populate the returned TxConfirmation struct, @@ -481,36 +512,77 @@ func (b *BtcdNotifier) historicalConfDetails(txid *chainhash.Hash, // locate its exact index within the block. blockHash, err := chainhash.NewHashFromStr(tx.BlockHash) if err != nil { - return nil, fmt.Errorf("unable to get block hash %v for historical "+ - "dispatch: %v", tx.BlockHash, err) - } - block, err := b.chainConn.GetBlockVerbose(blockHash) - if err != nil { - return nil, fmt.Errorf("unable to get block hash: %v", err) + return nil, fmt.Errorf("unable to get block hash %v for "+ + "historical dispatch: %v", tx.BlockHash, err) } - // If the block obtained, locate the transaction's index within the + block, err := b.chainConn.GetBlockVerbose(blockHash) + if err != nil { + return nil, fmt.Errorf("unable to get block with hash %v for "+ + "historical dispatch: %v", blockHash, err) + } + + // If the block was obtained, locate the transaction's index within the // block so we can give the subscriber full confirmation details. - txIndex := -1 targetTxidStr := txid.String() - for i, txHash := range block.Tx { + for txIndex, txHash := range block.Tx { if txHash == targetTxidStr { - txIndex = i - break + return &chainntnfs.TxConfirmation{ + BlockHash: blockHash, + BlockHeight: uint32(block.Height), + TxIndex: uint32(txIndex), + }, nil } } - if txIndex == -1 { - return nil, fmt.Errorf("unable to locate tx %v in block %v", - txid, blockHash) + // We return an error because we should have found the transaction + // within the block, but didn't. + return nil, fmt.Errorf("unable to locate tx %v in block %v", txid, + blockHash) +} + +// confDetailsManually looks up whether a transaction is already included in a +// block in the active chain by scanning the chain's blocks, starting from the +// earliest height the transaction could have been included in, to the current +// height in the chain. If the transaction is found, its confirmation details +// are returned. Otherwise, nil is returned. +func (b *BtcdNotifier) confDetailsManually(txid *chainhash.Hash, + heightHint, currentHeight uint32) (*chainntnfs.TxConfirmation, error) { + + targetTxidStr := txid.String() + + // Begin scanning blocks at every height to determine where the + // transaction was included in. + for height := heightHint; height <= currentHeight; height++ { + blockHash, err := b.chainConn.GetBlockHash(int64(height)) + if err != nil { + return nil, fmt.Errorf("unable to get hash from block "+ + "with height %d", height) + } + + // TODO: fetch the neutrino filters instead. + block, err := b.chainConn.GetBlockVerbose(blockHash) + if err != nil { + return nil, fmt.Errorf("unable to get block with hash "+ + "%v: %v", blockHash, err) + } + + for txIndex, txHash := range block.Tx { + // If we're able to find the transaction in this block, + // return its confirmation details. + if txHash == targetTxidStr { + return &chainntnfs.TxConfirmation{ + BlockHash: blockHash, + BlockHeight: height, + TxIndex: uint32(txIndex), + }, nil + } + } } - txConf := chainntnfs.TxConfirmation{ - BlockHash: blockHash, - BlockHeight: uint32(block.Height), - TxIndex: uint32(txIndex), - } - return &txConf, nil + // If we reach here, then we were not able to find the transaction + // within a block, so we avoid returning an error. + return nil, nil } // handleBlocksConnected applies a chain update for a new block. Any watched @@ -600,7 +672,10 @@ type spendNotification struct { spendChan chan *chainntnfs.SpendDetail spendID uint64 + mempool bool + + heightHint uint32 } // spendCancel is a message sent to the BtcdNotifier when a client wishes to @@ -616,14 +691,16 @@ type spendCancel struct { // RegisterSpendNtfn registers an intent to be notified once the target // outpoint has been spent by a transaction on-chain. Once a spend of the target // outpoint has been detected, the details of the spending event will be sent -// across the 'Spend' channel. +// across the 'Spend' channel. The heightHint should represent the earliest +// height in the chain where the transaction could have been spent in. func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, - _ uint32, mempool bool) (*chainntnfs.SpendEvent, error) { + heightHint uint32, mempool bool) (*chainntnfs.SpendEvent, error) { ntfn := &spendNotification{ targetOutpoint: outpoint, spendChan: make(chan *chainntnfs.SpendDetail, 1), spendID: atomic.AddUint64(&b.spendClientCounter, 1), + heightHint: heightHint, mempool: mempool, } @@ -637,37 +714,59 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, return nil, err } - // The following conditional checks to ensure that when a spend notification - // is registered, the output hasn't already been spent. If the output - // is no longer in the UTXO set, the chain will be rescanned from the point - // where the output was added. The rescan will dispatch the notification. - txout, err := b.chainConn.GetTxOut(&outpoint.Hash, outpoint.Index, true) + // The following conditional checks to ensure that when a spend + // notification is registered, the output hasn't already been spent. If + // the output is no longer in the UTXO set, the chain will be rescanned + // from the point where the output was added. The rescan will dispatch + // the notification. + txOut, err := b.chainConn.GetTxOut(&outpoint.Hash, outpoint.Index, true) if err != nil { return nil, err } - if txout == nil { - transaction, err := b.chainConn.GetRawTransactionVerbose(&outpoint.Hash) + if txOut == nil { + // First, we'll attempt to retrieve the transaction's block hash + // using the backend's transaction index. + tx, err := b.chainConn.GetRawTransactionVerbose(&outpoint.Hash) if err != nil { + // Avoid returning an error if the transaction was not + // found to proceed with fallback methods. jsonErr, ok := err.(*btcjson.RPCError) if !ok || jsonErr.Code != btcjson.ErrRPCNoTxInfo { + return nil, fmt.Errorf("unable to query for "+ + "txid %v: %v", outpoint.Hash, err) + } + } + + var blockHash *chainhash.Hash + if tx != nil && tx.BlockHash != "" { + // If we're able to retrieve a valid block hash from the + // transaction, then we'll use it as our rescan starting + // point. + blockHash, err = chainhash.NewHashFromStr(tx.BlockHash) + if err != nil { + return nil, err + } + } else { + // Otherwise, we'll attempt to retrieve the hash for the + // block at the heightHint. + blockHash, err = b.chainConn.GetBlockHash( + int64(heightHint), + ) + if err != nil { return nil, err } } // We'll only request a rescan if the transaction has actually // been included within a block. Otherwise, we'll encounter an - // error when scanning for blocks. This can happens in the case + // error when scanning for blocks. This can happen in the case // of a race condition, wherein the output itself is unspent, // and only arrives in the mempool after the getxout call. - if transaction != nil && transaction.BlockHash != "" { - blockhash, err := chainhash.NewHashFromStr(transaction.BlockHash) - if err != nil { - return nil, err - } - + if blockHash != nil { ops := []*wire.OutPoint{outpoint} - if err := b.chainConn.Rescan(blockhash, nil, ops); err != nil { + err = b.chainConn.Rescan(blockHash, nil, ops) + if err != nil { chainntnfs.Log.Errorf("Rescan for spend "+ "notification txout failed: %v", err) return nil, err @@ -706,22 +805,24 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, // confirmationNotification represents a client's intent to receive a // notification once the target txid reaches numConfirmations confirmations. -type confirmationsNotification struct { +type confirmationNotification struct { chainntnfs.ConfNtfn + heightHint uint32 } // RegisterConfirmationsNtfn registers a notification with BtcdNotifier // which will be triggered once the txid reaches numConfs number of // confirmations. func (b *BtcdNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash, - numConfs, _ uint32) (*chainntnfs.ConfirmationEvent, error) { + numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, error) { - ntfn := &confirmationsNotification{ - chainntnfs.ConfNtfn{ + ntfn := &confirmationNotification{ + ConfNtfn: chainntnfs.ConfNtfn{ TxID: txid, NumConfirmations: numConfs, Event: chainntnfs.NewConfirmationEvent(numConfs), }, + heightHint: heightHint, } select { From ead9555d40782b8d60846ac5bf86b591ba594db2 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 9 Feb 2018 19:57:45 -0500 Subject: [PATCH 2/2] chainregistry: remove txindex requirement for btcd and bitcoind Now that we have a fallback method for when the transaction index is not enabled, its requirement to be enabled for a full node is no longer needed, so we can safely remove this check. --- chainregistry.go | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/chainregistry.go b/chainregistry.go index 7d402051..a9bed51d 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -163,7 +163,6 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, var ( err error cleanUp func() - btcdConn *chain.RPCClient bitcoindConn *chain.BitcoindClient ) @@ -446,7 +445,6 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, } walletConfig.ChainSource = chainRPC - btcdConn = chainRPC // If we're not in simnet or regtest mode, then we'll attempt // to use a proper fee estimator for testnet. @@ -522,41 +520,6 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, cc.wallet = wallet - // As a final check, if we're using the RPC backend, we'll ensure that - // the btcd node has the txindex set. Atm, this is required in order to - // properly perform historical confirmation+spend dispatches. - if homeChainConfig.Node != "neutrino" { - // In order to check to see if we have the txindex up to date - // and active, we'll try to fetch the first transaction in the - // latest block via the index. If this doesn't succeed, then we - // know it isn't active (or just not yet up to date). - bestHash, _, err := cc.chainIO.GetBestBlock() - if err != nil { - return nil, nil, fmt.Errorf("unable to get current "+ - "best hash: %v", err) - } - bestBlock, err := cc.chainIO.GetBlock(bestHash) - if err != nil { - return nil, nil, fmt.Errorf("unable to get current "+ - "block hash: %v", err) - } - - firstTxHash := bestBlock.Transactions[0].TxHash() - switch homeChainConfig.Node { - case "btcd": - _, err = btcdConn.GetRawTransaction(&firstTxHash) - case "bitcoind": - _, err = bitcoindConn.GetRawTransactionVerbose(&firstTxHash) - } - if err != nil { - // If the node doesn't have the txindex set, then we'll - // halt startup, as we can't proceed in this state. - return nil, nil, fmt.Errorf("%s detected to not "+ - "have --txindex active, cannot proceed", - homeChainConfig.Node) - } - } - return cc, cleanUp, nil }