Browse Source

Update ygrunner to use fidelity bonds

master
Adam Gibson 5 years ago committed by chris-belcher
parent
commit
81bade7334
No known key found for this signature in database
GPG Key ID: EF734EA677F31129
  1. 2
      jmdaemon/test/test_orderbookwatch.py
  2. 19
      test/common.py
  3. 69
      test/ygrunner.py

2
jmdaemon/test/test_orderbookwatch.py

@ -7,7 +7,7 @@ from jmdaemon import IRCMessageChannel, fidelity_bond_cmd_list
from jmclient import get_irc_mchannels, load_test_config from jmclient import get_irc_mchannels, load_test_config
from jmdaemon.protocol import JM_VERSION, ORDER_KEYS from jmdaemon.protocol import JM_VERSION, ORDER_KEYS
from jmbase.support import hextobin from jmbase.support import hextobin
from jmbitcoin.fidelity_bond import FidelityBondProof from jmclient.fidelity_bond import FidelityBondProof
class DummyDaemon(object): class DummyDaemon(object):
def request_signature_verify(self, a, b, c, d, e, def request_signature_verify(self, a, b, c, d, e,

19
test/common.py

@ -12,7 +12,8 @@ sys.path.insert(0, os.path.join(data_dir))
from jmbase import get_log from jmbase import get_log
from jmclient import open_test_wallet_maybe, BIP32Wallet, SegwitWallet, \ from jmclient import open_test_wallet_maybe, BIP32Wallet, SegwitWallet, \
estimate_tx_fee, jm_single, WalletService, BaseWallet estimate_tx_fee, jm_single, WalletService, BaseWallet, WALLET_IMPLEMENTATIONS
from jmclient.wallet_utils import get_configured_wallet_type
import jmbitcoin as btc import jmbitcoin as btc
from jmbase import chunks from jmbase import chunks
@ -65,13 +66,18 @@ def make_wallets(n,
test_wallet=False, test_wallet=False,
passwords=None, passwords=None,
walletclass=SegwitWallet, walletclass=SegwitWallet,
mixdepths=5): mixdepths=5,
fb_indices=[]):
'''n: number of wallets to be created '''n: number of wallets to be created
wallet_structure: array of n arrays , each subarray wallet_structure: array of n arrays , each subarray
specifying the number of addresses to be populated with coins specifying the number of addresses to be populated with coins
at each depth (for now, this will only populate coins into 'receive' addresses) at each depth (for now, this will only populate coins into 'receive' addresses)
mean_amt: the number of coins (in btc units) in each address as above mean_amt: the number of coins (in btc units) in each address as above
sdev_amt: if randomness in amouts is desired, specify here. sdev_amt: if randomness in amouts is desired, specify here.
fb_indices: a list of integers in range(n), and for each of those we will
use the fidelity bond wallet type (note: to actually *use* the FB feature
the calling code will have to create the FB utxo, itself). Only supported
if walletclass=SegwitWallet.
Returns: a dict of dicts of form {0:{'seed':seed,'wallet':Wallet object},1:..,} Returns: a dict of dicts of form {0:{'seed':seed,'wallet':Wallet object},1:..,}
Default Wallet constructor is joinmarket.Wallet, else use TestWallet, Default Wallet constructor is joinmarket.Wallet, else use TestWallet,
which takes a password parameter as in the list passwords. which takes a password parameter as in the list passwords.
@ -93,9 +99,14 @@ def make_wallets(n,
pwd = passwords[i] pwd = passwords[i]
else: else:
pwd = None pwd = None
if i in fb_indices:
assert walletclass == SegwitWallet, "Cannot use FB except for native segwit."
wc = WALLET_IMPLEMENTATIONS[get_configured_wallet_type(True)]
print("for index: {}, we got wallet type: {}".format(i, wc))
else:
wc = walletclass
w = open_test_wallet_maybe(seeds[i], seeds[i], mixdepths - 1, w = open_test_wallet_maybe(seeds[i], seeds[i], mixdepths - 1,
test_wallet_cls=walletclass) test_wallet_cls=wc)
wallet_service = WalletService(w) wallet_service = WalletService(w)
wallets[i + start_index] = {'seed': seeds[i].decode('ascii'), wallets[i + start_index] = {'seed': seeds[i].decode('ascii'),

69
test/ygrunner.py

@ -11,14 +11,25 @@
--btcpwd=123456abcdef --btcconf=/blah/bitcoin.conf \ --btcpwd=123456abcdef --btcconf=/blah/bitcoin.conf \
--nirc=2 -s test/ygrunner.py --nirc=2 -s test/ygrunner.py
''' '''
from twisted.internet import task, reactor
from common import make_wallets from common import make_wallets
import pytest import pytest
import random import random
from datetime import datetime
from jmbase import jmprint from jmbase import jmprint
from jmclient import YieldGeneratorBasic, load_test_config, jm_single,\ from jmclient import YieldGeneratorBasic, load_test_config, jm_single,\
JMClientProtocolFactory, start_reactor, SegwitWallet,\ JMClientProtocolFactory, start_reactor, SegwitWallet, WalletService,\
SegwitLegacyWallet, cryptoengine, SNICKERClientProtocolFactory, SNICKERReceiver SegwitLegacyWallet, cryptoengine, SNICKERClientProtocolFactory, SNICKERReceiver
from jmclient.wallet_utils import wallet_gettimelockaddress
# For quicker testing, restrict the range of timelock
# addresses to avoid slow load of multiple bots.
# Note: no need to revert this change as ygrunner runs
# in isolation.
from jmclient import FidelityBondMixin
FidelityBondMixin.TIMELOCK_ERA_YEARS = 2
FidelityBondMixin.TIMELOCK_EPOCH_YEAR = datetime.now().year
FidelityBondMixin.TIMENUMBERS_PER_PUBKEY = 12
class MaliciousYieldGenerator(YieldGeneratorBasic): class MaliciousYieldGenerator(YieldGeneratorBasic):
"""Overrides, randomly, some maker functions """Overrides, randomly, some maker functions
@ -80,18 +91,19 @@ class DeterministicMaliciousYieldGenerator(YieldGeneratorBasic):
return (False, "malicious tx rejection") return (False, "malicious tx rejection")
return super().on_tx_received(nick, txhex, offerinfo) return super().on_tx_received(nick, txhex, offerinfo)
@pytest.mark.parametrize( @pytest.mark.parametrize(
"num_ygs, wallet_structures, mean_amt, malicious, deterministic", "num_ygs, wallet_structures, fb_indices, mean_amt, malicious, deterministic",
[ [
# 1sp 3yg, honest makers # 1sp 3yg, honest makers, one maker has FB:
(3, [[1, 3, 0, 0, 0]] * 4, 2, 0, False), (3, [[1, 3, 0, 0, 0]] * 4, [1, 2], 2, 0, False),
# 1sp 3yg, malicious makers reject on auth and on tx 30% of time # 1sp 3yg, malicious makers reject on auth and on tx 30% of time
#(3, [[1, 3, 0, 0, 0]] * 4, 2, 30, False), #(3, [[1, 3, 0, 0, 0]] * 4, 2, 30, False),
# 1 sp 9 ygs, deterministically malicious 50% of time # 1 sp 9 ygs, deterministically malicious 50% of time
#(9, [[1, 3, 0, 0, 0]] * 10, 2, 50, True), #(9, [[1, 3, 0, 0, 0]] * 10, 2, 50, True),
]) ])
def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt, def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, fb_indices,
malicious, deterministic): mean_amt, malicious, deterministic):
"""Set up some wallets, for the ygs and 1 sp. """Set up some wallets, for the ygs and 1 sp.
Then start the ygs in background and publish Then start the ygs in background and publish
the seed of the sp wallet for easy import into -qt the seed of the sp wallet for easy import into -qt
@ -105,7 +117,8 @@ def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt,
wallet_services = make_wallets(num_ygs + 1, wallet_services = make_wallets(num_ygs + 1,
wallet_structures=wallet_structures, wallet_structures=wallet_structures,
mean_amt=mean_amt, mean_amt=mean_amt,
walletclass=walletclass) walletclass=walletclass,
fb_indices=fb_indices)
#the sendpayment bot uses the last wallet in the list #the sendpayment bot uses the last wallet in the list
wallet_service = wallet_services[num_ygs]['wallet'] wallet_service = wallet_services[num_ygs]['wallet']
jmprint("\n\nTaker wallet seed : " + wallet_services[num_ygs]['seed']) jmprint("\n\nTaker wallet seed : " + wallet_services[num_ygs]['seed'])
@ -160,12 +173,19 @@ def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt,
else: else:
ygclass = MaliciousYieldGenerator ygclass = MaliciousYieldGenerator
for i in range(num_ygs): for i in range(num_ygs):
cfg = [txfee, cjfee_a, cjfee_r, ordertype, minsize, txfee_factor, cfg = [txfee, cjfee_a, cjfee_r, ordertype, minsize, txfee_factor,
cjfee_factor, size_factor] cjfee_factor, size_factor]
wallet_service_yg = wallet_services[i]["wallet"] wallet_service_yg = wallet_services[i]["wallet"]
wallet_service_yg.startService() wallet_service_yg.startService()
yg = ygclass(wallet_service_yg, cfg) yg = ygclass(wallet_service_yg, cfg)
if i in fb_indices:
# create a timelocked address and fund it;
# must be done after sync, so deferred:
wallet_service_yg.timelock_funded = False
sync_wait_loop = task.LoopingCall(get_addr_and_fund, yg)
sync_wait_loop.start(1.0, now=False)
if malicious: if malicious:
yg.set_maliciousness(malicious, mtype="tx") yg.set_maliciousness(malicious, mtype="tx")
clientfactory = JMClientProtocolFactory(yg, proto_type="MAKER") clientfactory = JMClientProtocolFactory(yg, proto_type="MAKER")
@ -183,6 +203,39 @@ def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt,
clientfactory, snickerfactory=snicker_factory, clientfactory, snickerfactory=snicker_factory,
daemon=daemon, rs=rs) daemon=daemon, rs=rs)
def get_addr_and_fund(yg):
""" This function allows us to create
and publish a fidelity bond for a particular
yield generator object after the wallet has reached
a synced state and is therefore ready to serve up
timelock addresses. We create the TL address, fund it,
refresh the wallet and then republish our offers, which
will also publish the new FB.
"""
if not yg.wallet_service.synced:
return
if yg.wallet_service.timelock_funded:
return
addr = wallet_gettimelockaddress(yg.wallet_service.wallet, "2021-11")
print("Got timelockaddress: {}".format(addr))
# pay into it; amount is randomized for now.
# Note that grab_coins already mines 1 block.
fb_amt = random.randint(1, 5)
jm_single().bc_interface.grab_coins(addr, fb_amt)
# we no longer have to run this loop (TODO kill with nonlocal)
yg.wallet_service.timelock_funded = True
# force wallet to check for the new coins so the new
# yg offers will include them:
yg.wallet_service.transaction_monitor()
# publish a new offer:
yg.offerlist = yg.create_my_orders()
yg.fidelity_bond = yg.get_fidelity_bond_template()
jmprint('updated offerlist={}'.format(yg.offerlist))
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def setup_ygrunner(): def setup_ygrunner():
load_test_config() load_test_config()

Loading…
Cancel
Save