Browse Source

remove wallet.sign()

master
undeath 8 years ago
parent
commit
703ae04dcc
  1. 36
      jmclient/jmclient/maker.py
  2. 53
      jmclient/jmclient/taker.py
  3. 27
      jmclient/jmclient/taker_utils.py
  4. 11
      jmclient/test/test_maker.py
  5. 27
      jmclient/test/test_taker.py

36
jmclient/jmclient/maker.py

@ -3,16 +3,13 @@ from __future__ import print_function
import base64
import pprint
import random
import sys
import time
import copy
from binascii import unhexlify
import btc
from jmclient.configure import jm_single, get_p2pk_vbyte, get_p2sh_vbyte
from jmbase.support import get_log
from jmclient.support import (calc_cj_fee)
from jmclient.wallet import estimate_tx_fee
from jmclient.podle import (generate_podle, get_podle_commitments, verify_podle,
PoDLE, PoDLEError, generate_podle_error_string)
from twisted.internet import task
@ -75,7 +72,11 @@ class Maker(object):
if res[0]['value'] < reqd_amt:
reason = "commitment utxo too small: " + str(res[0]['value'])
return reject(reason)
if res[0]['address'] != self.wallet.pubkey_to_address(cr_dict['P']):
# FIXME: This only works if taker's commitment address is of same type
# as our wallet.
if res[0]['address'] != \
self.wallet.pubkey_to_addr(unhexlify(cr_dict['P'])):
reason = "Invalid podle pubkey: " + str(cr_dict['P'])
return reject(reason)
@ -114,22 +115,25 @@ class Maker(object):
jlog.info('goodtx')
sigs = []
utxos = offerinfo["utxos"]
our_inputs = {}
for index, ins in enumerate(tx['ins']):
utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
if utxo not in utxos.keys():
if utxo not in utxos:
continue
addr = utxos[utxo]['address']
amount = utxos[utxo]["value"]
txs = self.wallet.sign(txhex, index,
self.wallet.get_key_from_addr(addr),
amount=amount)
sigmsg = btc.deserialize(txs)["ins"][index]["script"].decode("hex")
if "txinwitness" in btc.deserialize(txs)["ins"][index].keys():
script = self.wallet.addr_to_script(utxos[utxo]['address'])
amount = utxos[utxo]['value']
our_inputs[index] = (script, amount)
txs = self.wallet.sign_tx(btc.deserialize(unhexlify(txhex)), our_inputs)
for index in our_inputs:
sigmsg = txs['ins'][index]['script']
if 'txinwitness' in txs['ins'][index]:
#We prepend the witness data since we want (sig, pub, scriptCode);
#also, the items in witness are not serialize_script-ed.
sigmsg = "".join([btc.serialize_script_unit(
x.decode("hex")) for x in btc.deserialize(
txs)["ins"][index]["txinwitness"]]) + sigmsg
sigmsg = b''.join(btc.serialize_script_unit(x)
for x in txs['ins'][index]['txinwitness']) + sigmsg
sigs.append(base64.b64encode(sigmsg))
return (True, sigs)

53
jmclient/jmclient/taker.py

@ -4,6 +4,7 @@ from __future__ import print_function
import base64
import pprint
import random
from binascii import hexlify, unhexlify
import btc
from jmclient.configure import jm_single, get_p2pk_vbyte, get_p2sh_vbyte
@ -25,7 +26,6 @@ class Taker(object):
wallet,
schedule,
order_chooser=weighted_order_choose,
sign_method=None,
callbacks=None,
tdestaddrs=None,
ignored_makers=None):
@ -98,9 +98,6 @@ class Taker(object):
self.schedule_index = -1
self.utxos = {}
self.tdestaddrs = [] if not tdestaddrs else tdestaddrs
#allow custom wallet-based clients to use their own signing code;
#currently only setting "wallet" is allowed, calls wallet.sign_tx(tx)
self.sign_method = sign_method
self.filter_orders_callback = callbacks[0]
self.taker_info_callback = callbacks[1]
if not self.taker_info_callback:
@ -367,7 +364,9 @@ class Taker(object):
#Construct the Bitcoin address for the auth_pub field
#Ensure that at least one address from utxos corresponds.
input_addresses = [d['address'] for d in utxo_data]
auth_address = self.wallet.pubkey_to_address(auth_pub)
# FIXME: This only works if taker's commitment address is of same type
# as our wallet.
auth_address = self.wallet.pubkey_to_addr(unhexlify(auth_pub))
if not auth_address in input_addresses:
jlog.warn("ERROR maker's (" + nick + ")"
" authorising pubkey is not included "
@ -710,37 +709,23 @@ class Taker(object):
#Note: donation code removed (possibly temporarily)
raise NotImplementedError
def sign_tx(self, tx, i, priv, amount):
if self.my_cj_addr:
return self.wallet.sign(tx, i, priv, amount)
else:
#Note: donation code removed (possibly temporarily)
raise NotImplementedError
def self_sign(self):
# now sign it ourselves
tx = btc.serialize(self.latest_tx)
if self.sign_method == "wallet":
#Currently passes addresses of to-be-signed inputs
#to backend wallet; this is correct for Electrum, may need
#different info for other backends.
addrs = {}
for index, ins in enumerate(self.latest_tx['ins']):
utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
if utxo not in self.input_utxos.keys():
continue
addrs[index] = self.input_utxos[utxo]['address']
tx = self.wallet.sign_tx(tx, addrs)
else:
for index, ins in enumerate(self.latest_tx['ins']):
utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
if utxo not in self.input_utxos.keys():
continue
addr = self.input_utxos[utxo]['address']
amount = self.input_utxos[utxo]["value"]
tx = self.sign_tx(tx, index, self.wallet.get_key_from_addr(addr),
amount)
self.latest_tx = btc.deserialize(tx)
our_inputs = {}
for index, ins in enumerate(self.latest_tx['ins']):
utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
if utxo not in self.input_utxos.keys():
continue
script = self.wallet.addr_to_script(self.input_utxos[utxo]['address'])
amount = self.input_utxos[utxo]['value']
our_inputs[index] = (script, amount)
# FIXME: ugly hack
tx_bin = btc.deserialize(unhexlify(btc.serialize(self.latest_tx)))
self.wallet.sign_tx(tx_bin, our_inputs)
self.latest_tx = btc.deserialize(hexlify(btc.serialize(tx_bin)))
def push(self):
tx = btc.serialize(self.latest_tx)

27
jmclient/jmclient/taker_utils.py

@ -5,10 +5,11 @@ import pprint
import os
import time
import numbers
from binascii import hexlify, unhexlify
from .configure import get_log, jm_single, validate_address
from .schedule import human_readable_schedule_entry, tweak_tumble_schedule
from .wallet import BaseWallet, estimate_tx_fee
from jmclient import mktx, deserialize, sign, txhash
from .btc import mktx, serialize, deserialize, sign, txhash
log = get_log()
"""
@ -74,14 +75,7 @@ def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False,
log.info("Using a fee of : " + str(fee_est) + " satoshis.")
if amount != 0:
log.info("Using a change value of: " + str(changeval) + " satoshis.")
tx = mktx(utxos.keys(), outs)
stx = deserialize(tx)
for index, ins in enumerate(stx['ins']):
utxo = ins['outpoint']['hash'] + ':' + str(
ins['outpoint']['index'])
addr = utxos[utxo]['address']
amount = utxos[utxo]['value']
tx = sign(tx, index, wallet.get_key_from_addr(addr), amount=amount)
tx = sign_tx(wallet, mktx(utxos.keys(), outs), utxos)
txsigned = deserialize(tx)
log.info("Got signed transaction:\n")
log.info(tx + "\n")
@ -106,6 +100,21 @@ def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False,
return txid
def sign_tx(wallet, tx, utxos):
stx = deserialize(tx)
our_inputs = {}
for index, ins in enumerate(stx['ins']):
utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
script = wallet.addr_to_script(utxos[utxo]['address'])
amount = utxos[utxo]['value']
our_inputs[index] = (script, amount)
# FIXME: ugly hack
tx_bin = deserialize(unhexlify(serialize(stx)))
wallet.sign_tx(tx_bin, our_inputs)
return hexlify(serialize(tx_bin))
def import_new_addresses(wallet, addr_list):
# FIXME: same code as in maker.py and taker.py
bci = jm_single().bc_interface

11
jmclient/test/test_maker.py

@ -2,10 +2,11 @@
from __future__ import print_function
from jmclient import AbstractWallet, Maker, btc, get_p2sh_vbyte, get_p2pk_vbyte, \
from jmclient import Maker, btc, get_p2sh_vbyte, get_p2pk_vbyte, \
load_program_config, jm_single
import jmclient
from commontest import DummyBlockchainInterface
from test_taker import DummyWallet
import struct
import binascii
@ -13,10 +14,6 @@ from itertools import chain
import pytest
class MockWallet(AbstractWallet):
pass
class OfflineMaker(Maker):
def try_to_create_my_orders(self):
self.sync_wait_loop.stop()
@ -116,7 +113,7 @@ def test_verify_unsigned_tx_sw_valid(setup_env_nodeps):
p2sh_gen = address_p2sh_generator()
p2pkh_gen = address_p2pkh_generator()
wallet = MockWallet()
wallet = DummyWallet()
maker = OfflineMaker(wallet)
cj_addr, cj_script = next(p2sh_gen)
@ -149,7 +146,7 @@ def test_verify_unsigned_tx_nonsw_valid(setup_env_nodeps):
p2sh_gen = address_p2sh_generator()
p2pkh_gen = address_p2pkh_generator()
wallet = MockWallet()
wallet = DummyWallet()
maker = OfflineMaker(wallet)
cj_addr, cj_script = next(p2pkh_gen)

27
jmclient/test/test_taker.py

@ -11,12 +11,12 @@ import json
from base64 import b64encode
from jmclient import (
load_program_config, jm_single, set_commitment_file, get_commitment_file,
LegacyWallet, Taker, VolatileStorage, get_p2sh_vbyte, get_network)
SegwitLegacyWallet, Taker, VolatileStorage, get_p2sh_vbyte, get_network)
from taker_test_data import (t_utxos_by_mixdepth, t_selected_utxos, t_orderbook,
t_maker_response, t_chosen_orders, t_dummy_ext)
class DummyWallet(LegacyWallet):
class DummyWallet(SegwitLegacyWallet):
def __init__(self):
storage = VolatileStorage()
super(DummyWallet, self).initialize(storage, get_network(),
@ -79,10 +79,6 @@ class DummyWallet(LegacyWallet):
"""
return 'p2sh-p2wpkh'
@classmethod
def pubkey_to_address(cls, pubkey):
return SegwitWallet.pubkey_to_address(pubkey)
def get_key_from_addr(self, addr):
"""usable addresses: privkey all 1s, 2s, 3s, ... :"""
privs = [x*32 + "\x01" for x in [chr(y) for y in range(1,6)]]
@ -111,7 +107,7 @@ def dummy_filter_orderbook(orders_fees, cjamount):
print("calling dummy filter orderbook")
return True
def get_taker(schedule=None, schedule_len=0, sign_method=None, on_finished=None,
def get_taker(schedule=None, schedule_len=0, on_finished=None,
filter_orders=None):
if not schedule:
#note, for taker.initalize() this will result in junk
@ -120,8 +116,7 @@ def get_taker(schedule=None, schedule_len=0, sign_method=None, on_finished=None,
on_finished_callback = on_finished if on_finished else taker_finished
filter_orders_callback = filter_orders if filter_orders else dummy_filter_orderbook
return Taker(DummyWallet(), schedule,
callbacks=[filter_orders_callback, None, on_finished_callback],
sign_method=sign_method)
callbacks=[filter_orders_callback, None, on_finished_callback])
def test_filter_rejection(createcmtdata):
def filter_orders_reject(orders_feesl, cjamount):
@ -340,8 +335,6 @@ def test_taker_init(createcmtdata, schedule, highfee, toomuchcoins, minmakers,
taker.my_cj_addr = None
with pytest.raises(NotImplementedError) as e_info:
taker.prepare_my_bitcoin_data()
with pytest.raises(NotImplementedError) as e_info:
taker.sign_tx("a", "b", "c", "d")
with pytest.raises(NotImplementedError) as e_info:
a = taker.coinjoin_address()
taker.wallet.inject_addr_get_failure = True
@ -377,14 +370,12 @@ def test_unconfirm_confirm(schedule_len):
assert not test_unconfirm_confirm.txflag
@pytest.mark.parametrize(
"dummyaddr, signmethod, schedule",
"dummyaddr, schedule",
[
("mrcNu71ztWjAQA6ww9kHiW3zBWSQidHXTQ", None,
[(0, 20000000, 3, "mnsquzxrHXpFsZeL42qwbKdCP2y1esN3qw", 0)]),
("mrcNu71ztWjAQA6ww9kHiW3zBWSQidHXTQ", "wallet",
[(0, 20000000, 3, "mnsquzxrHXpFsZeL42qwbKdCP2y1esN3qw", 0)]),
("mrcNu71ztWjAQA6ww9kHiW3zBWSQidHXTQ",
[(0, 20000000, 3, "mnsquzxrHXpFsZeL42qwbKdCP2y1esN3qw", 0)])
])
def test_on_sig(createcmtdata, dummyaddr, signmethod, schedule):
def test_on_sig(createcmtdata, dummyaddr, schedule):
#plan: create a new transaction with known inputs and dummy outputs;
#then, create a signature with various inputs, pass in in b64 to on_sig.
#in order for it to verify, the DummyBlockchainInterface will have to
@ -410,7 +401,7 @@ def test_on_sig(createcmtdata, dummyaddr, signmethod, schedule):
de_tx = bitcoin.deserialize(tx)
#prepare the Taker with the right intermediate data
taker = get_taker(schedule=schedule, sign_method=signmethod)
taker = get_taker(schedule=schedule)
taker.nonrespondants=["cp1", "cp2", "cp3"]
taker.latest_tx = de_tx
#my inputs are the first 2 utxos

Loading…
Cancel
Save