Browse Source
master2bfe080add teardown code in test_coinjoin for clean reactor (undeath)4524293add basic test for coinjoins (undeath)
1 changed files with 152 additions and 0 deletions
@ -0,0 +1,152 @@
|
||||
from __future__ import print_function, absolute_import, division, unicode_literals |
||||
|
||||
""" |
||||
Test doing full coinjoins, bypassing IRC |
||||
""" |
||||
|
||||
import os |
||||
import sys |
||||
import pytest |
||||
from twisted.internet import reactor |
||||
|
||||
from jmclient import load_program_config, jm_single, get_log,\ |
||||
YieldGeneratorBasic, Taker, sync_wallet |
||||
from jmclient.podle import set_commitment_file |
||||
from commontest import make_wallets |
||||
from test_taker import dummy_filter_orderbook |
||||
|
||||
testdir = os.path.dirname(os.path.realpath(__file__)) |
||||
log = get_log() |
||||
|
||||
|
||||
def make_wallets_to_list(make_wallets_data): |
||||
wallets = [None for x in range(len(make_wallets_data))] |
||||
for i in make_wallets_data: |
||||
wallets[i] = make_wallets_data[i]['wallet'] |
||||
assert all(wallets) |
||||
return wallets |
||||
|
||||
|
||||
def sync_wallets(wallets): |
||||
for w in wallets: |
||||
w.gap_limit = 0 |
||||
jm_single().bc_interface.wallet_synced = False |
||||
for x in range(20): |
||||
if jm_single().bc_interface.wallet_synced: |
||||
break |
||||
sync_wallet(w) |
||||
else: |
||||
assert False, "Failed to sync wallet" |
||||
|
||||
|
||||
def create_orderbook(makers): |
||||
orderbook = [] |
||||
for i in range(len(makers)): |
||||
m = makers[i] |
||||
assert len(m.offerlist) == 1 |
||||
m.offerlist[0]['counterparty'] = str(i) |
||||
orderbook.extend(m.offerlist) |
||||
return orderbook |
||||
|
||||
|
||||
def create_taker(wallet, schedule, monkeypatch): |
||||
def on_finished_callback(*args, **kwargs): |
||||
on_finished_callback.called = True |
||||
on_finished_callback.called = False |
||||
taker = Taker(wallet, schedule, callbacks=(dummy_filter_orderbook, None, |
||||
on_finished_callback)) |
||||
|
||||
# we have skipped irc key setup and key exchange, handled by jmdaemon |
||||
monkeypatch.setattr(taker, 'auth_counterparty', lambda *args: True) |
||||
return taker |
||||
|
||||
|
||||
def init_coinjoin(taker, makers, orderbook, cj_amount): |
||||
init_data = taker.initialize(orderbook) |
||||
assert init_data[0], "taker.initialize error" |
||||
active_orders = init_data[4] |
||||
maker_data = {} |
||||
for mid in init_data[4]: |
||||
m = makers[int(mid)] |
||||
# note: '00' is kphex, usually set up by jmdaemon |
||||
response = m.on_auth_received( |
||||
'TAKER', init_data[4][mid], init_data[2][1:], |
||||
init_data[3], init_data[1], '00') |
||||
assert response[0], "maker.on_auth_received error" |
||||
|
||||
ioauth_data = list(response[1:]) |
||||
ioauth_data[0] = list(ioauth_data[0].keys()) |
||||
# maker_pk which is set up by jmdaemon |
||||
ioauth_data.append(None) |
||||
maker_data[mid] = ioauth_data |
||||
|
||||
# this is handled by jmdaemon |
||||
active_orders[mid]['utxos'] = response[1] |
||||
active_orders[mid]['cjaddr'] = ioauth_data[2] |
||||
active_orders[mid]['changeaddr'] = ioauth_data[3] |
||||
active_orders[mid]['offer'] = m.offerlist[0] |
||||
active_orders[mid]['amount'] = cj_amount |
||||
return active_orders, maker_data |
||||
|
||||
|
||||
def do_tx_signing(taker, makers, active_orders, txdata): |
||||
taker_final_result = 'not called' |
||||
maker_signatures = {} # left here for easier debugging |
||||
for mid in txdata[1]: |
||||
m = makers[int(mid)] |
||||
result = m.on_tx_received('TAKER', txdata[2], active_orders[mid]) |
||||
assert result[0], "maker.on_tx_received error" |
||||
maker_signatures[mid] = result[1] |
||||
for sig in result[1]: |
||||
taker_final_result = taker.on_sig(mid, sig) |
||||
|
||||
assert taker_final_result != 'not called' |
||||
return taker_final_result |
||||
|
||||
|
||||
def test_simple_coinjoin(monkeypatch, tmpdir, setup_cj): |
||||
def raise_exit(i): |
||||
raise Exception("sys.exit called") |
||||
monkeypatch.setattr(sys, 'exit', raise_exit) |
||||
set_commitment_file(str(tmpdir.join('commitments.json'))) |
||||
|
||||
MAKER_NUM = 3 |
||||
wallets = make_wallets_to_list(make_wallets( |
||||
MAKER_NUM + 1, wallet_structures=[[4, 0, 0, 0, 0]] * (MAKER_NUM + 1), |
||||
mean_amt=1)) |
||||
|
||||
jm_single().bc_interface.tickchain() |
||||
sync_wallets(wallets) |
||||
|
||||
makers = [YieldGeneratorBasic( |
||||
wallets[i], |
||||
[0, 2000, 0, 'swabsoffer', 10**7]) for i in range(MAKER_NUM)] |
||||
|
||||
orderbook = create_orderbook(makers) |
||||
assert len(orderbook) == MAKER_NUM |
||||
|
||||
cj_amount = int(1.1 * 10**8) |
||||
# mixdepth, amount, counterparties, dest_addr, waittime |
||||
schedule = [(0, cj_amount, MAKER_NUM, 'INTERNAL', 0)] |
||||
taker = create_taker(wallets[-1], schedule, monkeypatch) |
||||
|
||||
active_orders, maker_data = init_coinjoin(taker, makers, |
||||
orderbook, cj_amount) |
||||
|
||||
txdata = taker.receive_utxos(maker_data) |
||||
assert txdata[0], "taker.receive_utxos error" |
||||
|
||||
taker_final_result = do_tx_signing(taker, makers, active_orders, txdata) |
||||
assert taker_final_result is not False |
||||
|
||||
|
||||
@pytest.fixture(scope='module') |
||||
def setup_cj(): |
||||
load_program_config() |
||||
jm_single().config.set('POLICY', 'tx_broadcast', 'self') |
||||
jm_single().bc_interface.tick_forward_chain_interval = 5 |
||||
jm_single().bc_interface.simulate_blocks() |
||||
yield None |
||||
# teardown |
||||
for dc in reactor.getDelayedCalls(): |
||||
dc.cancel() |
||||
Loading…
Reference in new issue