From d74d4abefc72aeb66f3063a074889100e7cfa155 Mon Sep 17 00:00:00 2001 From: Leon Costa Date: Thu, 4 Jul 2024 18:50:17 +0200 Subject: [PATCH 1/3] Fix wallet load error on incomplete gettransaction The error happens when the wallet has some locked outputs in `listlockunspent` and the corresponding `gettransaction` doesn't contain the details of this particular output. It may be related to https://github.com/bitcoin/bitcoin/issues/28555. It is at least the same symptom. The locked outputs were locked by creating a transaction in Specter. This has happened to me multiple times. The UI says it failed to load the wallet with the following error: Failed to load utxos, IndexError: list index out of range The raw transaction does contain the missing output so we use that instead. Here's an example that generates the error: listlockunspent: [ { "txid": "", "vout": 0 } ] gettransaction : { "amount": , "fee": , "confirmations": , "blockhash": "", "blockheight": , "blockindex": , "blocktime": , "txid": "", "wtxid": "", "walletconflicts": [ ], "time": , "timereceived": , "bip125-replaceable": "no", "details": [ { "address": "", "category": "send", "amount": , "label": "", "vout": 1, "fee": , "abandoned": false } ], "hex": "", "lastprocessedblock": { "hash": "", "height": } } decoderawtransaction : { "txid": "", "hash": "", "version": 2, "size": , "vsize": , "weight": , "locktime": , "vin": [ { "txid": "", "vout": 0, "scriptSig": { "asm": "", "hex": "" }, "txinwitness": [ "", "" ], "sequence": } ], "vout": [ { "value": , "n": 0, "scriptPubKey": { "asm": "", "desc": "", "hex": "", "address": "", "type": "" } }, { "value": , "n": 1, "scriptPubKey": { "asm": "", "desc": "", "hex": "", "address": "", "type": "" } } ] } --- src/cryptoadvance/specter/wallet/wallet.py | 23 ++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/cryptoadvance/specter/wallet/wallet.py b/src/cryptoadvance/specter/wallet/wallet.py index 4340b3d8f..6b6d1ca94 100644 --- a/src/cryptoadvance/specter/wallet/wallet.py +++ b/src/cryptoadvance/specter/wallet/wallet.py @@ -718,13 +718,28 @@ def check_utxo(self): else: tx_from_core = self.rpc.gettransaction(tx_copy["txid"]) # in the case of locked amounts, the stupid listlockunspent call does not contain reasonable utxo-data - searched_vout = [ + searched_vouts = [ _tx for _tx in tx_from_core["details"] if _tx["vout"] == utxo_vout - ][0] - tx_copy["amount"] = searched_vout["amount"] - tx_copy["address"] = searched_vout["address"] + ] + if len(searched_vouts) > 0: + searched_vout = searched_vouts[0] + tx_copy["amount"] = searched_vout["amount"] + tx_copy["address"] = searched_vout["address"] + else: + # Sometimes gettransaction doesn't return the complete list of outputs. + # It may be related to https://github.com/bitcoin/bitcoin/issues/28555 + # In this case we decode the raw transaction to get the data we want. + raw_transaction_hex = tx_from_core["hex"] + raw_transaction = self.rpc.decoderawtransaction(raw_transaction_hex) + searched_raw_vout = [ + _output + for _output in raw_transaction["vout"] + if _output["n"] == utxo_vout + ][0] + tx_copy["amount"] = searched_raw_vout["value"] + tx_copy["address"] = searched_raw_vout["scriptPubKey"]["address"] # Append the copy to the _full_utxo list _full_utxo.append(tx_copy) From ec5e1b2cde85f2669328ce07c4d856da9b319506 Mon Sep 17 00:00:00 2001 From: Leon Costa Date: Thu, 1 Aug 2024 10:50:58 +0200 Subject: [PATCH 2/3] Apply black formatting --- src/cryptoadvance/specter/wallet/wallet.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cryptoadvance/specter/wallet/wallet.py b/src/cryptoadvance/specter/wallet/wallet.py index 6b6d1ca94..ab0f375e0 100644 --- a/src/cryptoadvance/specter/wallet/wallet.py +++ b/src/cryptoadvance/specter/wallet/wallet.py @@ -732,14 +732,17 @@ def check_utxo(self): # It may be related to https://github.com/bitcoin/bitcoin/issues/28555 # In this case we decode the raw transaction to get the data we want. raw_transaction_hex = tx_from_core["hex"] - raw_transaction = self.rpc.decoderawtransaction(raw_transaction_hex) + raw_transaction = self.rpc.decoderawtransaction( + raw_transaction_hex + ) searched_raw_vout = [ _output for _output in raw_transaction["vout"] if _output["n"] == utxo_vout ][0] tx_copy["amount"] = searched_raw_vout["value"] - tx_copy["address"] = searched_raw_vout["scriptPubKey"]["address"] + script_pubkey = searched_raw_vout["scriptPubKey"] + tx_copy["address"] = script_pubkey["address"] # Append the copy to the _full_utxo list _full_utxo.append(tx_copy) From 2efd56ced56d817ba79f889ffcb9ff389f811b73 Mon Sep 17 00:00:00 2001 From: Leon Costa Date: Thu, 22 Aug 2024 18:46:15 +0200 Subject: [PATCH 3/3] Use embit to decode the raw transaction Because the decoderawtransaction RPC is not available in Spectrum and the tools to decode the raw transaction are already there. --- src/cryptoadvance/specter/wallet/wallet.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/cryptoadvance/specter/wallet/wallet.py b/src/cryptoadvance/specter/wallet/wallet.py index ab0f375e0..82a820678 100644 --- a/src/cryptoadvance/specter/wallet/wallet.py +++ b/src/cryptoadvance/specter/wallet/wallet.py @@ -732,17 +732,10 @@ def check_utxo(self): # It may be related to https://github.com/bitcoin/bitcoin/issues/28555 # In this case we decode the raw transaction to get the data we want. raw_transaction_hex = tx_from_core["hex"] - raw_transaction = self.rpc.decoderawtransaction( - raw_transaction_hex - ) - searched_raw_vout = [ - _output - for _output in raw_transaction["vout"] - if _output["n"] == utxo_vout - ][0] - tx_copy["amount"] = searched_raw_vout["value"] - script_pubkey = searched_raw_vout["scriptPubKey"] - tx_copy["address"] = script_pubkey["address"] + parsed_transaction = self.TxCls.from_string(raw_transaction_hex) + out = parsed_transaction.vout[utxo_vout] + tx_copy["amount"] = round(out.value * 1e-8, 8) + tx_copy["address"] = out.script_pubkey.address(self.network) # Append the copy to the _full_utxo list _full_utxo.append(tx_copy)