Browse Source

add malicious-yg to yg test runner

master
Adam Gibson 8 years ago
parent
commit
810242c460
No known key found for this signature in database
GPG Key ID: B3AE09F1E9A3197A
  1. 36
      docs/TESTING.md
  2. 44
      test/ygrunner.py

36
docs/TESTING.md

@ -21,3 +21,39 @@ Running the test suite should be done like:
(you'll first want to copy bitcoin.conf in the test/ directory to a place you choose, and (you'll first want to copy bitcoin.conf in the test/ directory to a place you choose, and
copy the regtest_joinmarket.cfg file from the test/ directory to the root directory, copy the regtest_joinmarket.cfg file from the test/ directory to the root directory,
both files will need minor edits for your btc configuration). both files will need minor edits for your btc configuration).
### Running tests of sendpayment and tumbler (including with malicious makers)
The file `test/ygrunner.py` provides the ability to spin up a set of yieldgenerator
bots against the local IRC instance with the local regtest blockchain. It can be
started with
py.test --btcroot=/path/to/bitcoin/bin/ --btcpwd=123456abcdef --btcconf=/path/to/bitcoin.conf --nirc=2 test/ygrunner.py -s
Here the `-s` flag is useful because it prints log output to the console. If you
keep the logging level at the default `INFO` only a minimum amount will come out, if
you want more then enter this into the `joinmarket.cfg` in the root directory:
[LOGGING]
console_log_level = DEBUG
It will print out a hex seed for a wallet you can use for tumble/sendpayment. Next,
go into the `scripts/` directory and make sure you have copied the `regtest_joinmarket.cfg`
file into that directory also, make any changes needed (like the LOGGING one above),
and run either sendpayment or tumbler with whatever parameters you choose.
To change the parameters of the yieldgenerators you can edit the parametrization of
the function `test_start_ygs` in [this file](https://github.com/AdamISZ/joinmarket-clientserver/blob/master/test/ygrunner.py).
There are two changes that may be of special interest:
* to change the number of yg
bots from e.g. 3 to 4, edit the first number in the parameter list entry to 3 and the
third entry to 4 (4 means three ygs plus one taker bot).
* More advanced case: To make the yg bots selectively (randomly) malicious, edit the last entry from 0 to some non-zero
integer representing a percentage chance of rejection, both at the receive-auth
stage and the receive-tx stage. So if you set this to 20, it means there will be
a 20% chance of *each* yg bot rejecting the auth message and the tx message (both
20%). If you are running tumbler in adversarial conditions like that, consider
changing things like the taker_utxo_retries or adding external commitments with
the add-utxo tool so external commitments usage can be tested.

44
test/ygrunner.py

@ -1,5 +1,5 @@
#! /usr/bin/env python #! /usr/bin/env python
from __future__ import absolute_import from __future__ import absolute_import, print_function
'''Creates wallets and yield generators in regtest. '''Creates wallets and yield generators in regtest.
Provides seed for joinmarket-qt test. Provides seed for joinmarket-qt test.
This should be run via pytest, even though This should be run via pytest, even though
@ -17,17 +17,42 @@ import os
import pytest import pytest
import sys import sys
import time import time
import random
from jmclient import (YieldGeneratorBasic, ygmain, load_program_config, from jmclient import (YieldGeneratorBasic, ygmain, load_program_config,
jm_single, sync_wallet, JMClientProtocolFactory, jm_single, sync_wallet, JMClientProtocolFactory,
start_reactor) start_reactor)
class MaliciousYieldGenerator(YieldGeneratorBasic):
"""Overrides, randomly, some maker functions
to prevent taker continuing successfully (unless
they can complete-with-subset).
"""
def set_maliciousness(self, frac):
self.mfrac = frac
def on_auth_received(self, nick, offer, commitment, cr, amount, kphex):
if random.randint(1, 100) < self.mfrac:
print("Counterparty commitment rejected maliciously")
return (False,)
return super(MaliciousYieldGenerator, self).on_auth_received(nick,
offer, commitment, cr, amount, kphex)
def on_tx_received(self, nick, txhex, offerinfo):
if random.randint(1, 100) < self.mfrac:
print("Counterparty tx rejected maliciously")
return (False, "malicious tx rejection")
return super(MaliciousYieldGenerator, self).on_tx_received(nick, txhex,
offerinfo)
@pytest.mark.parametrize( @pytest.mark.parametrize(
"num_ygs, wallet_structures, mean_amt", "num_ygs, wallet_structures, mean_amt, malicious",
[ [
# 1sp 3yg, 2 mixdepths, sweep from depth1 # 1sp 3yg, honest makers
(3, [[1, 3, 0, 0, 0]] * 4, 2), (3, [[1, 3, 0, 0, 0]] * 4, 2, 0),
# 1sp 3yg, malicious makers reject on auth and on tx 30% of time
#(4, [[1, 3, 0, 0, 0]] * 5, 2, 30),
]) ])
def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt): def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt,
malicious):
"""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
@ -37,20 +62,23 @@ def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt):
mean_amt=mean_amt) mean_amt=mean_amt)
#the sendpayment bot uses the last wallet in the list #the sendpayment bot uses the last wallet in the list
wallet = wallets[num_ygs]['wallet'] wallet = wallets[num_ygs]['wallet']
print "Seed : " + wallets[num_ygs]['seed'] print("Seed : " + wallets[num_ygs]['seed'])
#useful to see the utxos on screen sometimes #useful to see the utxos on screen sometimes
sync_wallet(wallet) sync_wallet(wallet)
print wallet.unspent print(wallet.unspent)
txfee = 1000 txfee = 1000
cjfee_a = 4200 cjfee_a = 4200
cjfee_r = '0.001' cjfee_r = '0.001'
ordertype = 'swreloffer' ordertype = 'swreloffer'
minsize = 100000 minsize = 100000
ygclass = MaliciousYieldGenerator if malicious else YieldGeneratorBasic
for i in range(num_ygs): for i in range(num_ygs):
cfg = [txfee, cjfee_a, cjfee_r, ordertype, minsize] cfg = [txfee, cjfee_a, cjfee_r, ordertype, minsize]
sync_wallet(wallets[i]["wallet"]) sync_wallet(wallets[i]["wallet"])
yg = YieldGeneratorBasic(wallets[i]["wallet"], cfg) yg = ygclass(wallets[i]["wallet"], cfg)
if malicious:
yg.set_maliciousness(malicious)
clientfactory = JMClientProtocolFactory(yg, proto_type="MAKER") clientfactory = JMClientProtocolFactory(yg, proto_type="MAKER")
nodaemon = jm_single().config.getint("DAEMON", "no_daemon") nodaemon = jm_single().config.getint("DAEMON", "no_daemon")
daemon = True if nodaemon == 1 else False daemon = True if nodaemon == 1 else False

Loading…
Cancel
Save