Skip to content

Commit

Permalink
Fix #1177 (#1180)
Browse files Browse the repository at this point in the history
* Fix #1177

* Use helper function and fix missing places

* Add comment to remove eventually

* Fix tx details popup
  • Loading branch information
ben-kaufman authored May 25, 2021
1 parent 90d9331 commit 662793d
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/cryptoadvance/specter/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import logging
from .helpers import is_testnet

logger = logging.getLogger()
logger = logging.getLogger(__name__)


class Device:
Expand Down
10 changes: 10 additions & 0 deletions src/cryptoadvance/specter/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,13 @@ def is_ip_private(ip):
or priv_16.match(ip)
)
return res is not None


def get_address_from_dict(data_dict):
# TODO: Remove this helper function in favor of simple ["address"]
# when support for Bitcoin Core version < 22 is dropped
return (
data_dict["addresses"][0]
if "addresses" in data_dict and data_dict["addresses"][0]
else data_dict["address"]
)
26 changes: 13 additions & 13 deletions src/cryptoadvance/specter/managers/wallet_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from embit.liquid.descriptor import LDescriptor
from embit.descriptor.checksum import add_checksum

logger = logging.getLogger()
logger = logging.getLogger(__name__)

purposes = OrderedDict(
{
Expand Down Expand Up @@ -129,7 +129,7 @@ def update(self, data_folder=None, rpc=None, chain=None):
self._update(data_folder, rpc, chain)
else:
self.is_loading = False
logging.info(
logger.info(
"Specter seems to be disconnected from Bitcoin Core. Skipping wallets update."
)

Expand All @@ -141,20 +141,20 @@ def _update(self, data_folder=None, rpc=None, chain=None):
try:
if self.wallets_update_list:
loaded_wallets = self.rpc.listwallets()
logger.debug("Getting loaded wallets list from Bitcoin Core")
logger.info("Getting loaded wallets list from Bitcoin Core")
for wallet in self.wallets_update_list:
wallet_alias = self.wallets_update_list[wallet]["alias"]
wallet_name = self.wallets_update_list[wallet]["name"]
if os.path.join(self.rpc_path, wallet_alias) not in loaded_wallets:
try:
logger.debug(
logger.info(
"Loading %s to Bitcoin Core"
% self.wallets_update_list[wallet]["alias"]
)
self.rpc.loadwallet(
os.path.join(self.rpc_path, wallet_alias)
)
logger.debug(
logger.info(
"Initializing %s Wallet object"
% self.wallets_update_list[wallet]["alias"]
)
Expand All @@ -166,13 +166,13 @@ def _update(self, data_folder=None, rpc=None, chain=None):
if not loaded_wallet:
raise Exception("Failed to load wallet")
# Lock UTXO of pending PSBTs
logger.debug(
logger.info(
"Re-locking UTXOs of wallet %s"
% self.wallets_update_list[wallet]["alias"]
)
if len(loaded_wallet.pending_psbts) > 0:
for psbt in loaded_wallet.pending_psbts:
logger.debug(
logger.info(
"lock %s " % wallet_alias,
loaded_wallet.pending_psbts[psbt]["tx"]["vin"],
)
Expand All @@ -197,7 +197,7 @@ def _update(self, data_folder=None, rpc=None, chain=None):
],
)
self.wallets[wallet_name] = loaded_wallet
logger.debug(
logger.info(
"Finished loading wallet into Bitcoin Core and Specter: %s"
% self.wallets_update_list[wallet]["alias"]
)
Expand Down Expand Up @@ -226,7 +226,7 @@ def _update(self, data_folder=None, rpc=None, chain=None):
# ok wallet is already there
# we only need to update
try:
logger.debug(
logger.info(
"Wallet already loaded in Bitcoin Core. Initializing %s Wallet object"
% self.wallets_update_list[wallet]["alias"]
)
Expand All @@ -237,7 +237,7 @@ def _update(self, data_folder=None, rpc=None, chain=None):
)
if loaded_wallet:
self.wallets[wallet_name] = loaded_wallet
logger.debug(
logger.info(
"Finished loading wallet into Specter: %s"
% self.wallets_update_list[wallet]["alias"]
)
Expand All @@ -256,20 +256,20 @@ def _update(self, data_folder=None, rpc=None, chain=None):
)
else:
# wallet is loaded and should stay
logger.debug(
logger.info(
"Wallet already in Specter, updating wallet: %s"
% self.wallets_update_list[wallet]["alias"]
)
self.wallets[wallet_name].update()
logger.debug(
logger.info(
"Finished updating wallet: %s"
% self.wallets_update_list[wallet]["alias"]
)
# TODO: check wallet file didn't change
# only ignore rpc errors
except RpcError as e:
logger.error(f"Failed updating wallet manager. RPC error: {e}")
logger.debug("Done updating wallet manager")
logger.info("Done updating wallet manager")
self.wallets_update_list = {}
self.is_loading = False

Expand Down
5 changes: 4 additions & 1 deletion src/cryptoadvance/specter/server_endpoints/wallets.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,10 @@ def send_new(wallet_alias):
# calculate new amount if we need to subtract
if subtract:
for v in psbt["tx"]["vout"]:
if addresses[0] in v["scriptPubKey"]["addresses"]:
if (
addresses[0] in v["scriptPubKey"]["addresses"]
or addresses[0] == v["scriptPubKey"]["address"]
):
amounts[0] = v["value"]
except Exception as e:
err = e
Expand Down
22 changes: 17 additions & 5 deletions src/cryptoadvance/specter/templates/includes/tx-data.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,15 @@ <h2>Transaction details</h2><br>
let jsonResponse = await fetchRawTx(self, rawtx.vin[i].txid);
if (jsonResponse !== null && jsonResponse.success) {
let spentOutput = jsonResponse.rawtx.vout[rawtx.vin[i].vout];
let address = ('addresses' in spentOutput && spentOutput.addresses.length == 1) ? spentOutput.addresses[0] : 'Unknown';
let address = (spentOutput.addresses && spentOutput.addresses.length == 1) ? spentOutput.addresses[0] : 'Unknown';
if (address == 'Unknown') {
address = ('addresses' in spentOutput.scriptPubKey && spentOutput.scriptPubKey.addresses.length == 1) ? spentOutput.scriptPubKey.addresses[0] : 'Unknown';
address = (spentOutput.scriptPubKey.addresses && spentOutput.scriptPubKey.addresses.length == 1) ? spentOutput.scriptPubKey.addresses[0] : 'Unknown';
}
if (address == 'Unknown') {
address = spentOutput.scriptPubKey.address ? spentOutput.scriptPubKey.address : 'Unknown';
}
if (address == 'Unknown') {
address = spentOutput.address ? spentOutput.address : 'Unknown';
}
let isMine = await fetchAddressIsMine(self, address);
if (isMine) {
Expand Down Expand Up @@ -182,11 +188,17 @@ <h2>Transaction details</h2><br>

rawtxHTML += `<h3>Outputs</h3>`;
for (let i in rawtx.vout) {
let address = ('addresses' in rawtx.vout[i] && rawtx.vout[i].addresses.length == 1) ? rawtx.vout[i].addresses[0] : 'Unknown';
let address = rawtx.vout[i].addresses && rawtx.vout[i].addresses.length == 1 ? rawtx.vout[i].addresses[0] : 'Unknown';
if (address == 'Unknown') {
address = ('addresses' in rawtx.vout[i].scriptPubKey && rawtx.vout[i].scriptPubKey.addresses.length == 1) ? rawtx.vout[i].scriptPubKey.addresses[0] : 'Unknown';
address = rawtx.vout[i].scriptPubKey.addresses && rawtx.vout[i].scriptPubKey.addresses.length == 1 ? rawtx.vout[i].scriptPubKey.addresses[0] : 'Unknown';

}
if (address == 'Unknown') {
address = rawtx.vout[i].scriptPubKey.address ? rawtx.vout[i].scriptPubKey.address : 'Unknown';
}
if (address == 'Unknown') {
address = rawtx.vout[i].address ? rawtx.vout[i].address : 'Unknown';
}

let value = "Confidential";
let price = '';
if (rawtx.vout[i].value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,17 @@
{% endfor %}
<h2 class="tx_details_header">Outputs ({{psbt['tx']['vout']|length}})</h2>
{% for output in psbt['tx']['vout'] if output['scriptPubKey']['type'] != 'fee' %}
{% set address = output['scriptPubKey']['addresses'][0] %}
{% set address = output['scriptPubKey']['addresses'][0] if "addresses" in output["scriptPubKey"] else output["scriptPubKey"]["address"] %}
{% set bg_color = '#154984' if wallet.is_address_mine(address) else '#131a24' %}
<p class="tx_info" style="text-align: left; background-color: {{ bg_color }};">
<b>Output #{{loop.index0}}</b> {% if output['scriptPubKey']['addresses'][0] not in psbt['address'] %}(Change){% endif %}<br><br>
{% set addr_label = wallet.getlabel(output['scriptPubKey']['addresses'][0]) %}
<b>Output #{{loop.index0}}</b> {% if address not in psbt['address'] %}(Change){% endif %}<br><br>
{% set addr_label = wallet.getlabel(address) %}
<b>Address:</b>
{{ output['scriptPubKey']['addresses'][0] }}
{{ address }}
<br>
{% if addr_label != output['scriptPubKey']['addresses'][0] %}
{% if addr_label != address %}
<b>Label:</b>
<address-label data-address="{{ output['scriptPubKey']['addresses'][0] }}" data-label="{{ addr_label }}" data-wallet="{{ wallet_alias }}"></address-label>
<address-label data-address="{{ address }}" data-label="{{ addr_label }}" data-wallet="{{ wallet_alias }}"></address-label>
<br>
{% endif %}
<b>Amount:</b> {{ output['value']|btcamount }} BTC {% if specter.price_check %}<span class="note">&nbsp;({{ output['value'] | altunit }})</span>{% endif %}
Expand Down
12 changes: 7 additions & 5 deletions src/cryptoadvance/specter/txlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
import os
from .persistence import write_csv, read_csv
from .helpers import get_address_from_dict
from embit.transaction import Transaction
from embit.networks import NETWORKS
import json
Expand Down Expand Up @@ -200,10 +201,11 @@ def add(self, txs):
break
if vin["txid"] in self:
try:
address = decoderawtransaction(
self[vin["txid"]]["hex"],
self.chain,
)["vout"][vin["vout"]]["addresses"][0]
address = get_address_from_dict(
decoderawtransaction(self[vin["txid"]]["hex"], self.chain,)[
"vout"
][vin["vout"]]
)
address_info = self._addresses.get(address, None)
if address_info and not address_info.is_external:
inputs_mine_count += 1
Expand All @@ -213,7 +215,7 @@ def add(self, txs):
outputs_mine_count = 0
for out in raw_tx["vout"]:
try:
address = out["addresses"][0]
address = get_address_from_dict(out)
except Exception:
# couldn't get address...
continue
Expand Down
2 changes: 1 addition & 1 deletion src/cryptoadvance/specter/util/tx.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def decoderawoutput(vout, chain):
},
}
try:
result["addresses"] = [vout.script_pubkey.address(NETWORKS[chain])]
result["address"] = vout.script_pubkey.address(NETWORKS[chain])
except:
pass
return result
Expand Down
47 changes: 29 additions & 18 deletions src/cryptoadvance/specter/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .device import Device
from .key import Key
from .util.merkleblock import is_valid_merkle_proof
from .helpers import der_to_bytes, is_liquid
from .helpers import der_to_bytes, is_liquid, get_address_from_dict
from embit import base58, bip32
from .util.descriptor import Descriptor, sort_descriptor, AddChecksum
from embit.liquid.descriptor import LDescriptor
Expand All @@ -22,7 +22,7 @@
from .addresslist import AddressList
from .txlist import TxList

logger = logging.getLogger()
logger = logging.getLogger(__name__)
LISTTRANSACTIONS_BATCH_SIZE = 1000


Expand Down Expand Up @@ -1435,8 +1435,8 @@ def get_rbf_utxo(self, rbf_tx_id):
"txid": utxo["txid"],
"vout": utxo["vout"],
"amount": utxo["details"]["value"],
"address": utxo["details"]["addresses"][0],
"label": self.getlabel(utxo["details"]["addresses"][0]),
"address": get_address_from_dict(utxo["details"]),
"label": self.getlabel(get_address_from_dict(utxo["details"])),
}
for utxo in rbf_utxo
]
Expand All @@ -1451,19 +1451,23 @@ def decode_tx(self, txid):
psbt = self.rpc.decodepsbt(raw_psbt)
return {
"addresses": [
vout["scriptPubKey"]["addresses"][0]
get_address_from_dict(vout["scriptPubKey"])
for i, vout in enumerate(psbt["tx"]["vout"])
if not self.get_address_info(vout["scriptPubKey"]["addresses"][0])
if not self.get_address_info(
get_address_from_dict(vout["scriptPubKey"])
)
or not self.get_address_info(
vout["scriptPubKey"]["addresses"][0]
get_address_from_dict(vout["scriptPubKey"])
).change
],
"amounts": [
vout["value"]
for i, vout in enumerate(psbt["tx"]["vout"])
if not self.get_address_info(vout["scriptPubKey"]["addresses"][0])
if not self.get_address_info(
get_address_from_dict(vout["scriptPubKey"])
)
or not self.get_address_info(
vout["scriptPubKey"]["addresses"][0]
get_address_from_dict(vout["scriptPubKey"])
).change
],
"used_utxo": [
Expand All @@ -1480,30 +1484,36 @@ def bumpfee(self, txid, fee_rate):

psbt = self.rpc.decodepsbt(raw_psbt)
psbt["changeAddress"] = [
vout["scriptPubKey"]["addresses"][0]
get_address_from_dict(vout["scriptPubKey"])
for i, vout in enumerate(psbt["tx"]["vout"])
if self.get_address_info(vout["scriptPubKey"]["addresses"][0])
and self.get_address_info(vout["scriptPubKey"]["addresses"][0]).change
if self.get_address_info(get_address_from_dict(vout["scriptPubKey"]))
and self.get_address_info(
get_address_from_dict(vout["scriptPubKey"])
).change
]
if psbt["changeAddress"]:
psbt["changeAddress"] = psbt["changeAddress"][0]
else:
raise Exception("Cannot RBF a transaction with no change output")
return self.createpsbt(
addresses=[
vout["scriptPubKey"]["addresses"][0]
get_address_from_dict(vout["scriptPubKey"])
for i, vout in enumerate(psbt["tx"]["vout"])
if not self.get_address_info(vout["scriptPubKey"]["addresses"][0])
if not self.get_address_info(
get_address_from_dict(vout["scriptPubKey"])
)
or not self.get_address_info(
vout["scriptPubKey"]["addresses"][0]
get_address_from_dict(vout["scriptPubKey"])
).change
],
amounts=[
vout["value"]
for i, vout in enumerate(psbt["tx"]["vout"])
if not self.get_address_info(vout["scriptPubKey"]["addresses"][0])
if not self.get_address_info(
get_address_from_dict(vout["scriptPubKey"])
)
or not self.get_address_info(
vout["scriptPubKey"]["addresses"][0]
get_address_from_dict(vout["scriptPubKey"])
).change
],
fee_rate=fee_rate,
Expand Down Expand Up @@ -1585,10 +1595,11 @@ def importpsbt(self, b64psbt):
if (
"addresses" not in out["scriptPubKey"]
or len(out["scriptPubKey"]["addresses"]) == 0
or "address" not in out["scriptPubKey"]
):
# TODO: we need to handle it somehow differently
raise SpecterError("Sending to raw scripts is not supported yet")
addr = out["scriptPubKey"]["addresses"][0]
addr = get_address_from_dict(out["scriptPubKey"])
info = self.get_address_info(addr)
# check if it's a change
if info and info.change:
Expand Down

0 comments on commit 662793d

Please sign in to comment.