mirror of
https://github.com/JoinMarket-Org/joinmarket-clientserver.git
synced 2026-08-13 12:33:40 +02:00
remove usages of wallet.unspent
This commit is contained in:
parent
89b5cd4280
commit
705d41d299
5 changed files with 84 additions and 63 deletions
|
|
@ -51,7 +51,7 @@ class BlockchainInterface(object):
|
|||
|
||||
@staticmethod
|
||||
def get_wallet_name(wallet):
|
||||
return 'joinmarket-wallet-' + btc.dbl_sha256(wallet.keys[0][0])[:6]
|
||||
return 'joinmarket-wallet-' + wallet.get_wallet_id()
|
||||
|
||||
@abc.abstractmethod
|
||||
def sync_addresses(self, wallet):
|
||||
|
|
@ -60,8 +60,7 @@ class BlockchainInterface(object):
|
|||
|
||||
@abc.abstractmethod
|
||||
def sync_unspent(self, wallet):
|
||||
"""Finds the unspent transaction outputs belonging to this wallet,
|
||||
sets wallet.unspent """
|
||||
"""Finds the unspent transaction outputs belonging to this wallet"""
|
||||
|
||||
def add_tx_notify(self, txd, unconfirmfun, confirmfun, notifyaddr,
|
||||
wallet_name=None, timeoutfun=None, spentfun=None, txid_flag=True,
|
||||
|
|
@ -642,7 +641,7 @@ class BitcoinCoreInterface(BlockchainInterface):
|
|||
def sync_unspent(self, wallet):
|
||||
st = time.time()
|
||||
wallet_name = self.get_wallet_name(wallet)
|
||||
wallet.unspent = {}
|
||||
wallet.reset_utxos()
|
||||
|
||||
listunspent_args = []
|
||||
if 'listunspent_args' in jm_single().config.options('POLICY'):
|
||||
|
|
@ -655,16 +654,29 @@ class BitcoinCoreInterface(BlockchainInterface):
|
|||
continue
|
||||
if u['account'] != wallet_name:
|
||||
continue
|
||||
# TODO
|
||||
if u['address'] not in wallet.addr_cache:
|
||||
continue
|
||||
wallet.unspent[u['txid'] + ':' + str(u['vout'])] = {
|
||||
'address': u['address'],
|
||||
'value': int(Decimal(str(u['amount'])) * Decimal('1e8'))
|
||||
}
|
||||
self._add_unspent_utxo(wallet, u)
|
||||
et = time.time()
|
||||
log.debug('bitcoind sync_unspent took ' + str((et - st)) + 'sec')
|
||||
self.wallet_synced = True
|
||||
|
||||
@staticmethod
|
||||
def _add_unspent_utxo(wallet, utxo):
|
||||
"""
|
||||
Add a UTXO as returned by rpc's listunspent call to the wallet.
|
||||
|
||||
params:
|
||||
wallet: wallet
|
||||
utxo: single utxo dict as returned by listunspent
|
||||
"""
|
||||
txid = binascii.unhexlify(utxo['txid'])
|
||||
script = binascii.unhexlify(utxo['scriptPubKey'])
|
||||
value = int(Decimal(str(utxo['amount'])) * Decimal('1e8'))
|
||||
|
||||
wallet.add_utxo(txid, int(utxo['vout']), script, value)
|
||||
|
||||
def get_deser_from_gettransaction(self, rpcretval):
|
||||
"""Get full transaction deserialization from a call
|
||||
to `gettransaction`
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@ import pprint
|
|||
import random
|
||||
import socket
|
||||
import threading
|
||||
import time
|
||||
import sys
|
||||
import ssl
|
||||
from twisted.python.log import startLogging
|
||||
from twisted.internet.protocol import ClientFactory, Protocol
|
||||
import binascii
|
||||
from twisted.internet.protocol import ClientFactory
|
||||
from twisted.internet.ssl import ClientContextFactory
|
||||
from twisted.protocols.basic import LineReceiver
|
||||
from twisted.internet import reactor, task, defer
|
||||
|
|
@ -328,10 +326,10 @@ class ElectrumInterface(BlockchainInterface):
|
|||
|
||||
def sync_unspent(self, wallet):
|
||||
# finds utxos in the wallet
|
||||
wallet.unspent = {}
|
||||
wallet.reset_utxos()
|
||||
#Prepare list of all used addresses
|
||||
addrs = []
|
||||
for m in range(wallet.max_mix_depth):
|
||||
addrs = set()
|
||||
for m in range(wallet.max_mixdepth):
|
||||
for fc in [0, 1]:
|
||||
branch_list = []
|
||||
for k, v in self.temp_addr_history[m][fc].iteritems():
|
||||
|
|
@ -339,7 +337,7 @@ class ElectrumInterface(BlockchainInterface):
|
|||
continue
|
||||
if v["used"]:
|
||||
branch_list.append(v["addr"])
|
||||
addrs.extend(branch_list)
|
||||
addrs.update(branch_list)
|
||||
if len(addrs) == 0:
|
||||
log.debug('no tx used')
|
||||
self.wallet_synced = True
|
||||
|
|
@ -348,21 +346,28 @@ class ElectrumInterface(BlockchainInterface):
|
|||
return
|
||||
#make sure to add any addresses during the run (a subset of those
|
||||
#added to the address cache)
|
||||
addrs = list(set(self.wallet.addr_cache.keys()).union(set(addrs)))
|
||||
self.listunspent_calls = 0
|
||||
for a in addrs:
|
||||
d = self.get_from_electrum('blockchain.address.listunspent', a)
|
||||
d.addCallback(self.process_listunspent_data, wallet, a, len(addrs))
|
||||
for md in range(wallet.max_mixdepth):
|
||||
for internal in (True, False):
|
||||
for index in range(wallet.get_next_unused_index(md, internal)):
|
||||
addrs.add(wallet.get_addr(md, internal, index))
|
||||
for path in wallet.get_imported_paths(md):
|
||||
addrs.add(wallet.get_addr_path(path))
|
||||
|
||||
def process_listunspent_data(self, unspent_info, wallet, address, n):
|
||||
self.listunspent_calls += 1
|
||||
self.listunspent_calls = len(addrs)
|
||||
for a in addrs:
|
||||
# FIXME: update to protocol version 1.1 and use scripthash instead
|
||||
script = wallet.address_to_script(a)
|
||||
d = self.get_from_electrum('blockchain.address.listunspent', a)
|
||||
d.addCallback(self.process_listunspent_data, wallet, script)
|
||||
|
||||
def process_listunspent_data(self, unspent_info, wallet, script):
|
||||
res = unspent_info['result']
|
||||
for u in res:
|
||||
wallet.unspent[str(u['tx_hash']) + ':' + str(
|
||||
u['tx_pos'])] = {'address': address, 'value': int(u['value'])}
|
||||
if self.listunspent_calls == n:
|
||||
for u in wallet.spent_utxos:
|
||||
wallet.unspent.pop(u, None)
|
||||
txid = binascii.unhexlify(u['tx_hash'])
|
||||
wallet.add_utxo(txid, int(u['tx_pos']), script, int(u['value']))
|
||||
|
||||
self.listunspent_calls -= 1
|
||||
if self.listunspent_calls == 0:
|
||||
self.wallet_synced = True
|
||||
if self.synctype == "sync-only":
|
||||
reactor.stop()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ the anti-snooping feature employed by makers.
|
|||
import sys
|
||||
import os
|
||||
import json
|
||||
import binascii
|
||||
from pprint import pformat
|
||||
|
||||
from optparse import OptionParser
|
||||
|
|
@ -173,20 +174,16 @@ def main():
|
|||
#Three options (-w, -r, -R) for loading utxo and privkey pairs from a wallet,
|
||||
#csv file or json file.
|
||||
if options.loadwallet:
|
||||
# TODO: new wallet has no unspent attribute
|
||||
raise NotImplementedError("This is not yet implemented.")
|
||||
wallet_path = get_wallet_path(options.loadwallet, None)
|
||||
wallet = open_wallet(wallet_path, gap_limit=options.gaplimit)
|
||||
sync_wallet(wallet, fast=options.fastsync)
|
||||
unsp = {}
|
||||
for u, av in wallet.unspent.iteritems():
|
||||
addr = av['address']
|
||||
key = wallet.get_key_from_addr(addr)
|
||||
wifkey = btc.wif_compressed_privkey(key, vbyte=get_p2pk_vbyte())
|
||||
unsp[u] = {'address': av['address'],
|
||||
'value': av['value'], 'privkey': wifkey}
|
||||
for u, pva in unsp.iteritems():
|
||||
utxo_data.append((u, pva['privkey']))
|
||||
|
||||
for md, utxos in wallet.get_utxos_by_mixdepth_().items():
|
||||
for (txid, index), utxo in utxos.items():
|
||||
txhex = binascii.hexlify(txid) + ':' + str(index)
|
||||
wif = wallet.get_wif_path(utxo['path'])
|
||||
utxo_data.append((txhex, wif))
|
||||
|
||||
elif options.in_file:
|
||||
with open(options.in_file, "rb") as f:
|
||||
utxo_info = f.readlines()
|
||||
|
|
|
|||
|
|
@ -103,18 +103,24 @@ def serialize_derivation(roc, i):
|
|||
return x
|
||||
#=======================================================
|
||||
|
||||
def get_privkey_amount_from_utxo(wallet, utxo):
|
||||
|
||||
def get_script_amount_from_utxo(wallet, utxo):
|
||||
"""Given a JM wallet and a utxo string, find
|
||||
the corresponding private key and amount controlled
|
||||
in satoshis.
|
||||
"""
|
||||
for k, v in wallet.unspent.iteritems():
|
||||
if k == utxo:
|
||||
print("Found utxo, its value is: ", v['value'])
|
||||
return wallet.get_key_from_addr(v['address']), v['value']
|
||||
return (None, None)
|
||||
for md, utxos in wallet.get_utxos_by_mixdepth_().items():
|
||||
for (txid, index), utxo in utxos.items():
|
||||
txhex = binascii.hexlify(txid) + ':' + str(index)
|
||||
if txhex != utxo:
|
||||
continue
|
||||
script = wallet.get_script_path(utxo['path'])
|
||||
print("Found utxo, its value is: {}".format(utxo['value']))
|
||||
return script, utxo['value']
|
||||
return None, None
|
||||
|
||||
def create_single_acp_pair(utxo_in, priv, addr_out, amount, bump, segwit=False):
|
||||
|
||||
def create_single_acp_pair(wallet, utxo_in, script, addr_out, amount, bump, segwit=False):
|
||||
"""Given a utxo and a signing key for it, and its amout in satoshis,
|
||||
sign a "transaction" consisting of only 1 input and one output, signed
|
||||
with single|acp sighash flags so it can be grafted into a bigger
|
||||
|
|
@ -129,10 +135,9 @@ def create_single_acp_pair(utxo_in, priv, addr_out, amount, bump, segwit=False):
|
|||
assert bump >= 0, "Output of single|acp pair must be bigger than input for safety."
|
||||
out = {"address": addr_out, "value": amount + bump}
|
||||
tx = btc.mktx([utxo_in], [out])
|
||||
amt = amount if segwit else None
|
||||
return btc.sign(tx, 0, priv,
|
||||
hashcode=btc.SIGHASH_SINGLE|btc.SIGHASH_ANYONECANPAY,
|
||||
amount=amt)
|
||||
return wallet.sign_tx(tx, {0: (script, amount)},
|
||||
hashcode=btc.SIGHASH_SINGLE|btc.SIGHASH_ANYONECANPAY)
|
||||
|
||||
|
||||
def graft_onto_single_acp(wallet, txhex, amount, destaddr):
|
||||
"""Given a serialized txhex which is checked to be of
|
||||
|
|
@ -187,13 +192,15 @@ def graft_onto_single_acp(wallet, txhex, amount, destaddr):
|
|||
df['ins'][0]['script'] = d['ins'][0]['script']
|
||||
if 'txinwitness' in d['ins'][0]:
|
||||
df['ins'][0]['txinwitness'] = d['ins'][0]['txinwitness']
|
||||
fulltx = btc.serialize(df)
|
||||
|
||||
for i, iu in enumerate(input_utxos):
|
||||
priv, inamt = get_privkey_amount_from_utxo(wallet, iu)
|
||||
print("Signing index: ", i+1, " with privkey: ", priv, " and amount: ", inamt, " for utxo: ", iu)
|
||||
fulltx = btc.sign(fulltx, i+1, priv, amount=inamt)
|
||||
return (True, fulltx)
|
||||
|
||||
script, inamt = get_script_amount_from_utxo(wallet, iu)
|
||||
print("Signing index: ", i+1, " with script: ", script, " and amount: ", inamt, " for utxo: ", iu)
|
||||
fulltx = wallet.sign_tx(df, {i: (script, inamt)})
|
||||
|
||||
return True, btc.serialize(fulltx)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = get_parser()
|
||||
(options, args) = parser.parse_args()
|
||||
|
|
@ -214,22 +221,22 @@ if __name__ == "__main__":
|
|||
"Use wallet-tool.py method 'showutxos' to select one")
|
||||
exit(0)
|
||||
utxo_in = args[2]
|
||||
priv, amount = get_privkey_amount_from_utxo(wallet, utxo_in)
|
||||
if not priv:
|
||||
script, amount = get_script_amount_from_utxo(wallet, utxo_in)
|
||||
if not script:
|
||||
print("Failed to find the utxo's private key from the wallet; check "
|
||||
"if this utxo is actually contained in the wallet using "
|
||||
"wallet-tool.py showutxos")
|
||||
exit(0)
|
||||
#destination sourced from wallet
|
||||
addr_out = wallet.get_new_addr((options.mixdepth+1)%options.amtmixdepths, 1)
|
||||
serialized_single_acp = create_single_acp_pair(utxo_in, priv, addr_out, amount,
|
||||
options.bump, segwit=True)
|
||||
single_acp = create_single_acp_pair(wallet, utxo_in, script, addr_out, amount,
|
||||
options.bump, segwit=True)
|
||||
print("Created the following one-in, one-out transaction, which will not "
|
||||
"be valid to broadcast itself (negative fee). Pass it to your "
|
||||
"counterparty:")
|
||||
print(pformat(btc.deserialize(serialized_single_acp)))
|
||||
print(pformat(single_acp))
|
||||
print("Pass the following raw hex to your counterparty:")
|
||||
print(serialized_single_acp)
|
||||
print(btc.serialize(single_acp))
|
||||
exit(0)
|
||||
elif args[1] == "take":
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt,
|
|||
print("Seed : " + wallets[num_ygs]['seed'])
|
||||
#useful to see the utxos on screen sometimes
|
||||
sync_wallet(wallet, fast=True)
|
||||
print(wallet.unspent)
|
||||
print(wallet.get_utxos_by_mixdepth())
|
||||
txfee = 1000
|
||||
cjfee_a = 4200
|
||||
cjfee_r = '0.001'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue