mirror of
https://github.com/JoinMarket-Org/joinmarket-clientserver.git
synced 2026-08-13 12:33:40 +02:00
Add merkle proof functions to BitcoinCoreInterface
This commit is contained in:
parent
2271ce05d7
commit
255d15562d
2 changed files with 65 additions and 0 deletions
|
|
@ -4,6 +4,7 @@ import random
|
|||
import sys
|
||||
import time
|
||||
from decimal import Decimal
|
||||
import binascii
|
||||
from twisted.internet import reactor, task
|
||||
|
||||
import jmbitcoin as btc
|
||||
|
|
@ -406,6 +407,30 @@ class BitcoinCoreInterface(BlockchainInterface):
|
|||
except JsonRpcError:
|
||||
return self.rpc('getblock', [blockhash])['time']
|
||||
|
||||
def get_tx_merkle_branch(self, txid, blockhash=None):
|
||||
if not blockhash:
|
||||
tx = self.rpc("gettransaction", [txid])
|
||||
if tx["confirmations"] < 1:
|
||||
raise ValueError("Transaction not in block")
|
||||
blockhash = tx["blockhash"]
|
||||
try:
|
||||
core_proof = self.rpc("gettxoutproof", [[txid], blockhash])
|
||||
except JsonRpcError:
|
||||
raise ValueError("Block containing transaction is pruned")
|
||||
return self.core_proof_to_merkle_branch(core_proof)
|
||||
|
||||
def core_proof_to_merkle_branch(self, core_proof):
|
||||
core_proof = binascii.unhexlify(core_proof)
|
||||
#first 80 bytes of a proof given by core are just a block header
|
||||
#so we can save space by replacing it with a 4-byte block height
|
||||
return core_proof[80:]
|
||||
|
||||
def verify_tx_merkle_branch(self, txid, block_height, merkle_branch):
|
||||
block_hash = self.rpc("getblockhash", [block_height])
|
||||
core_proof = self.rpc("getblockheader", [block_hash, False]) + \
|
||||
binascii.hexlify(merkle_branch).decode()
|
||||
ret = self.rpc("verifytxoutproof", [core_proof])
|
||||
return len(ret) == 1 and ret[0] == txid
|
||||
|
||||
class RegtestBitcoinCoreMixin():
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -537,6 +537,46 @@ class WalletService(Service):
|
|||
jmprint(restart_msg, "important")
|
||||
sys.exit(EXIT_SUCCESS)
|
||||
|
||||
def sync_burner_outputs(self, burner_txes):
|
||||
mixdepth = FidelityBondMixin.FIDELITY_BOND_MIXDEPTH
|
||||
address_type = FidelityBondMixin.BIP32_BURN_ID
|
||||
self.wallet.set_next_index(mixdepth, address_type, self.wallet.gap_limit,
|
||||
force=True)
|
||||
highest_used_index = 0
|
||||
|
||||
known_burner_outputs = self.wallet.get_burner_outputs()
|
||||
for index in range(self.wallet.gap_limit):
|
||||
path = self.wallet.get_path(mixdepth, address_type, index)
|
||||
path_privkey, engine = self.wallet._get_priv_from_path(path)
|
||||
path_pubkey = engine.privkey_to_pubkey(path_privkey)
|
||||
path_pubkeyhash = btc.bin_hash160(path_pubkey)
|
||||
|
||||
for burner_tx in burner_txes:
|
||||
burner_pubkeyhash, gettx = burner_tx
|
||||
if burner_pubkeyhash != path_pubkeyhash:
|
||||
continue
|
||||
highest_used_index = index
|
||||
path_repr = self.wallet.get_path_repr(path)
|
||||
if path_repr.encode() in known_burner_outputs:
|
||||
continue
|
||||
txid = gettx["txid"]
|
||||
jlog.info("Found a burner transaction txid=" + txid + " path = "
|
||||
+ path_repr)
|
||||
try:
|
||||
merkle_branch = self.bci.get_tx_merkle_branch(txid, gettx["blockhash"])
|
||||
except ValueError as e:
|
||||
jlog.warning(repr(e))
|
||||
jlog.warning("Merkle branch likely not available, use "
|
||||
+ "wallet-tool `addtxoutproof`")
|
||||
merkle_branch = None
|
||||
block_height = self.bci.rpc("getblockheader", [gettx["blockhash"]])["height"]
|
||||
if merkle_branch:
|
||||
assert self.bci.verify_tx_merkle_branch(txid, block_height, merkle_branch)
|
||||
self.wallet.add_burner_output(path_repr, gettx["hex"], block_height,
|
||||
merkle_branch, gettx["blockindex"])
|
||||
|
||||
self.wallet.set_next_index(mixdepth, address_type, highest_used_index + 1)
|
||||
|
||||
def sync_addresses(self):
|
||||
""" Triggered by use of --recoversync option in scripts,
|
||||
attempts a full scan of the blockchain without assuming
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue