Skip to content

Commit

Permalink
Create native segwit v0 order type
Browse files Browse the repository at this point in the history
Note: The defaults for the fake offer and yg-privacyenhanced remain
on nested segwit
  • Loading branch information
Jules Comte committed Nov 6, 2020
1 parent 2ae348b commit ab87db2
Show file tree
Hide file tree
Showing 23 changed files with 88 additions and 69 deletions.
8 changes: 4 additions & 4 deletions docs/YIELDGENERATOR.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ Open one of the two built-in yield generators: `yield-generator-basic.py` or `yg
txfee = 1000
cjfee_a = 2000
cjfee_r = '0.0002' # 0.02% fee
ordertype = 'swreloffer'
ordertype = 'sw0reloffer'
minsize = int(1.2 * txfee / float(cjfee)) #minimum size is such that you always net profit at least 20% of the miner fee

Meaning of fields:
+ txfee. The yield generators contribution to the miner fee.
+ ordertype. One of 'swreloffer' or 'swabsoffer'.
+ cjfee_r. Your offered coinjoin fee as a fraction of the coinjoin amount (for 'swreloffer'). Takers pay this to you.
+ cjfee_a. Your offered coinjoin fee as an absolute number of satoshis (for 'swabsoffer')
+ ordertype. One of 'swreloffer', 'swabsoffer', 'sw0reloffer', 'sw0absoffer'.
+ cjfee_r. Your offered coinjoin fee as a fraction of the coinjoin amount (for 'swreloffer', 'sw0reloffer'). Takers pay this to you.
+ cjfee_a. Your offered coinjoin fee as an absolute number of satoshis (for 'swabsoffer', 'sw0absoffer')

## Keeping Track of Returns

Expand Down
9 changes: 5 additions & 4 deletions jmclient/jmclient/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,11 @@ def jm_single():
# Only set to false for old wallets, Joinmarket is now segwit only.
segwit = true
# Use native segwit (bech32) wallet. This is NOT
# currently supported in Joinmarket coinjoins. Only set to "true"
# if specifically advised to do so.
native = false
# Use native segwit (bech32) wallet. If set to false, p2sh-p2wkh
# will be used when generating the addresses for this wallet.
# Notes: 1. The default joinmarket pit is native segwit.
# 2. You cannot change the type of a pre-existing wallet.
native = true
# for dust sweeping, try merge_algorithm = gradual
# for more rapid dust sweeping, try merge_algorithm = greedy
Expand Down
12 changes: 6 additions & 6 deletions jmclient/jmclient/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ def select_one_utxo(unspent, value):


def calc_cj_fee(ordertype, cjfee, cj_amount):
if ordertype in ['swabsoffer', 'absoffer']:
if ordertype in ['sw0absoffer', 'swabsoffer', 'absoffer']:
real_cjfee = int(cjfee)
elif ordertype in ['swreloffer', 'reloffer']:
elif ordertype in ['sw0reloffer', 'swreloffer', 'reloffer']:
real_cjfee = int((Decimal(cjfee) * Decimal(cj_amount)).quantize(Decimal(
1)))
else:
Expand Down Expand Up @@ -235,7 +235,7 @@ def check_max_fee(fee):


def choose_orders(offers, cj_amount, n, chooseOrdersBy, ignored_makers=None,
pick=False, allowed_types=["swreloffer", "swabsoffer"],
pick=False, allowed_types=["sw0reloffer", "sw0absoffer"],
max_cj_fee=(1, float('inf'))):
is_within_max_limits = _get_is_within_max_limits(
max_cj_fee[0], max_cj_fee[1], cj_amount)
Expand Down Expand Up @@ -301,7 +301,7 @@ def choose_sweep_orders(offers,
n,
chooseOrdersBy,
ignored_makers=None,
allowed_types=['swreloffer', 'swabsoffer'],
allowed_types=['sw0reloffer', 'sw0absoffer'],
max_cj_fee=(1, float('inf'))):
"""
choose an order given that we want to be left with no change
Expand All @@ -325,9 +325,9 @@ def calc_zero_change_cj_amount(ordercombo):
sumtxfee_contribution = 0
for order in ordercombo:
sumtxfee_contribution += order['txfee']
if order['ordertype'] in ['swabsoffer', 'absoffer']:
if order['ordertype'] in ['sw0absoffer', 'swabsoffer', 'absoffer']:
sumabsfee += int(order['cjfee'])
elif order['ordertype'] in ['swreloffer', 'reloffer']:
elif order['ordertype'] in ['sw0reloffer', 'swreloffer', 'reloffer']:
sumrelfee += Decimal(order['cjfee'])
#this is unreachable since calc_cj_fee must already have been called
else: #pragma: no cover
Expand Down
16 changes: 12 additions & 4 deletions jmclient/jmclient/taker.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,12 @@ def filter_orderbook(self, orderbook, sweep=False):
if sweep:
self.orderbook = orderbook #offers choosing deferred to next step
else:
allowed_types = ["reloffer", "absoffer"] if jm_single().config.get(
"POLICY", "segwit") == "false" else ["swreloffer", "swabsoffer"]
if jm_single().config.get("POLICY", "segwit") == "false":
allowed_types = ["reloffer", "absoffer"]
elif jm_single().config.get("POLICY", "native") == "false":
allowed_types = ["swreloffer", "swabsoffer"]
else:
allowed_types = ["sw0reloffer", "sw0absoffer"]
self.orderbook, self.total_cj_fee = choose_orders(
orderbook, self.cjamount, self.n_counterparties, self.order_chooser,
self.ignored_makers, allowed_types=allowed_types,
Expand Down Expand Up @@ -320,8 +324,12 @@ def prepare_my_bitcoin_data(self):
txtype=self.wallet_service.get_txtype())
jlog.debug("We have a fee estimate: "+str(self.total_txfee))
total_value = sum([va['value'] for va in self.input_utxos.values()])
allowed_types = ["reloffer", "absoffer"] if jm_single().config.get(
"POLICY", "segwit") == "false" else ["swreloffer", "swabsoffer"]
if jm_single().config.get("POLICY", "segwit") == "false":
allowed_types = ["reloffer", "absoffer"]
elif jm_single().config.get("POLICY", "native") == "false":
allowed_types = ["swreloffer", "swabsoffer"]
else:
allowed_types = ["sw0reloffer", "sw0absoffer"]
self.orderbook, self.cjamount, self.total_cj_fee = choose_sweep_orders(
self.orderbook, total_value, self.total_txfee,
self.n_counterparties, self.order_chooser,
Expand Down
8 changes: 4 additions & 4 deletions jmclient/jmclient/wallet_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ def wallet_importprivkey(wallet, mixdepth, key_type):
"word mnemonic phrase. Make sure you have backups.", "warning")
jmprint("WARNING: Make sure that the type of the public address previously "
"derived from this private key matches the wallet type you are "
"currently using.")
"currently using.", "warning")
jmprint("WARNING: Handling of raw ECDSA bitcoin private keys can lead to "
"non-intuitive behaviour and loss of funds.\n Recommended instead "
"is to use the \'sweep\' feature of sendpayment.py.", "warning")
Expand Down Expand Up @@ -1263,7 +1263,7 @@ def create_wallet(path, password, max_mixdepth, wallet_cls, **kwargs):


def open_test_wallet_maybe(path, seed, max_mixdepth,
test_wallet_cls=SegwitLegacyWallet, wallet_password_stdin=False, **kwargs):
test_wallet_cls=SegwitWallet, wallet_password_stdin=False, **kwargs):
"""
Create a volatile test wallet if path is a hex-encoded string of length 64,
otherwise run open_wallet().
Expand All @@ -1279,8 +1279,8 @@ def open_test_wallet_maybe(path, seed, max_mixdepth,
"""
# If the native flag is set in the config, it overrides the argument
# test_wallet_cls
if jm_single().config.get("POLICY", "native") == "true":
test_wallet_cls = SegwitWallet
if jm_single().config.get("POLICY", "native") == "false":
test_wallet_cls = SegwitLegacyWallet
if len(seed) == test_wallet_cls.ENTROPY_BYTES * 2:
try:
seed = binascii.unhexlify(seed)
Expand Down
13 changes: 7 additions & 6 deletions jmclient/jmclient/yieldgenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ def create_my_orders(self):

max_mix = max(mix_balance, key=mix_balance.get)
f = '0'
if self.ordertype in ('reloffer', 'swreloffer'):
if self.ordertype in ('reloffer', 'swreloffer', 'sw0reloffer'):
f = self.cjfee_r
#minimum size bumped if necessary such that you always profit
#least 50% of the miner fee
self.minsize = max(int(1.5 * self.txfee / float(self.cjfee_r)),
self.minsize)
elif self.ordertype in ('absoffer', 'swabsoffer'):
elif self.ordertype in ('absoffer', 'swabsoffer', 'sw0absoffer'):
f = str(self.txfee + self.cjfee_a)
order = {'oid': 0,
'ordertype': self.ordertype,
Expand Down Expand Up @@ -188,7 +188,7 @@ def select_output_address(self, input_mixdepth, offer, amount):
return self.wallet_service.get_internal_addr(cjoutmix)


def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='swreloffer',
def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='sw0reloffer',
nickserv_password='', minsize=100000, gaplimit=6):
import sys

Expand Down Expand Up @@ -222,19 +222,20 @@ def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='swreloffe
wallet_name = args[0]
ordertype = options.ordertype
txfee = options.txfee
if ordertype in ('reloffer', 'swreloffer'):
if ordertype in ('reloffer', 'swreloffer', 'sw0reloffer'):
if options.cjfee != '':
cjfee_r = options.cjfee
# minimum size is such that you always net profit at least 20%
#of the miner fee
minsize = max(int(1.2 * txfee / float(cjfee_r)), options.minsize)
elif ordertype in ('absoffer', 'swabsoffer'):
elif ordertype in ('absoffer', 'swabsoffer', 'sw0absoffer'):
if options.cjfee != '':
cjfee_a = int(options.cjfee)
minsize = options.minsize
else:
parser.error('You specified an incorrect offer type which ' +\
'can be either swreloffer or swabsoffer')
'can be either swreloffer, sw0reloffer, ' +\
'swabsoffer, or sw0absoffer')
sys.exit(EXIT_ARGERROR)
nickserv_password = options.password

Expand Down
4 changes: 2 additions & 2 deletions jmclient/test/commontest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from jmclient import (
jm_single, open_test_wallet_maybe, estimate_tx_fee,
BlockchainInterface, BIP32Wallet,
SegwitLegacyWallet, WalletService, BTC_P2SH_P2WPKH)
SegwitWallet, WalletService, BTC_P2SH_P2WPKH)
from jmbase.support import chunks
import jmbitcoin as btc

Expand Down Expand Up @@ -177,7 +177,7 @@ def make_wallets(n,
sdev_amt=0,
start_index=0,
fixed_seeds=None,
wallet_cls=SegwitLegacyWallet,
wallet_cls=SegwitWallet,
mixdepths=5,
populate_internal=False):
'''n: number of wallets to be created
Expand Down
18 changes: 9 additions & 9 deletions jmclient/test/taker_test_data.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#orderbook
t_orderbook = [{u'counterparty': u'J6FA1Gj7Ln4vSGne', u'ordertype': u'swreloffer', u'oid': 0,
t_orderbook = [{u'counterparty': u'J6FA1Gj7Ln4vSGne', u'ordertype': u'sw0reloffer', u'oid': 0,
u'minsize': 7500000, u'txfee': 1000, u'maxsize': 599972700, u'cjfee': u'0.0002'},
{u'counterparty': u'J6CFffuuewjG44UJ', u'ordertype': u'swreloffer', u'oid': 0,
{u'counterparty': u'J6CFffuuewjG44UJ', u'ordertype': u'sw0reloffer', u'oid': 0,
u'minsize': 7500000, u'txfee': 1000, u'maxsize': 599972700, u'cjfee': u'0.0002'},
{u'counterparty': u'J65z23xdjxJjC7er', u'ordertype': u'swreloffer', u'oid': 0,
{u'counterparty': u'J65z23xdjxJjC7er', u'ordertype': u'sw0reloffer', u'oid': 0,
u'minsize': 7500000, u'txfee': 1000, u'maxsize': 599972700, u'cjfee': u'0.0002'},
{u'counterparty': u'J64Ghp5PXCdY9H3t', u'ordertype': u'swreloffer', u'oid': 0,
{u'counterparty': u'J64Ghp5PXCdY9H3t', u'ordertype': u'sw0reloffer', u'oid': 0,
u'minsize': 7500000, u'txfee': 1000, u'maxsize': 599972700, u'cjfee': u'0.0002'},
{u'counterparty': u'J659UPUSLLjHJpaB', u'ordertype': u'swreloffer', u'oid': 0,
{u'counterparty': u'J659UPUSLLjHJpaB', u'ordertype': u'sw0reloffer', u'oid': 0,
u'minsize': 7500000, u'txfee': 1000, u'maxsize': 599972700, u'cjfee': u'0.0002'},
{u'counterparty': u'J6cBx1FwUVh9zzoO', u'ordertype': u'swreloffer', u'oid': 0,
{u'counterparty': u'J6cBx1FwUVh9zzoO', u'ordertype': u'sw0reloffer', u'oid': 0,
u'minsize': 7500000, u'txfee': 1000, u'maxsize': 599972700, u'cjfee': u'0.0002'}]

t_dest_addr = "mvw1NazKDRbeNufFANqpYNAANafsMC2zVU"
Expand All @@ -19,21 +19,21 @@
u'maxsize': 599972700,
u'minsize': 7500000,
u'oid': 0,
u'ordertype': u'swreloffer',
u'ordertype': u'sw0reloffer',
u'txfee': 1000},
u'J65z23xdjxJjC7er': {u'cjfee': u'0.0002',
u'counterparty': u'J65z23xdjxJjC7er',
u'maxsize': 599972700,
u'minsize': 7500000,
u'oid': 0,
u'ordertype': u'swreloffer',
u'ordertype': u'sw0reloffer',
u'txfee': 1000},
u'J6CFffuuewjG44UJ': {u'cjfee': u'0.0002',
u'counterparty': u'J6CFffuuewjG44UJ',
u'maxsize': 599972700,
u'minsize': 7500000,
u'oid': 0,
u'ordertype': u'swreloffer',
u'ordertype': u'sw0reloffer',
u'txfee': 1000}}

"""
Expand Down
2 changes: 1 addition & 1 deletion jmclient/test/test_client_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def create_my_orders(self):
'maxsize': 100000000,
'minsize': 75000,
'oid': 0,
'ordertype': 'swreloffer',
'ordertype': 'sw0reloffer',
'txfee': 0
}]

Expand Down
2 changes: 1 addition & 1 deletion jmclient/test/test_maker.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def get_address_generator(script_pre, script_post, p2sh=False):


def create_tx_and_offerlist(cj_addr, cj_change_addr, other_output_addrs,
offertype='swreloffer'):
offertype='sw0reloffer'):
assert len(other_output_addrs) % 2 == 0, "bug in test"

cj_value = 100000000
Expand Down
7 changes: 5 additions & 2 deletions jmclient/test/test_snicker.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import jmbitcoin as btc
from jmbase import get_log, bintohex
from jmclient import (load_test_config, estimate_tx_fee, SNICKERReceiver,
direct_send)
direct_send, SegwitLegacyWallet)

TEST_PROPOSALS_FILE = "test_proposals.txt"
log = get_log()
Expand All @@ -31,7 +31,10 @@ def test_snicker_e2e(setup_snicker, nw, wallet_structures,
LoopingCall) and processes them.
5. Check for valid final transaction with broadcast.
"""
wallets = make_wallets(nw, wallet_structures, mean_amt, sdev_amt)

# TODO: Make this test work with native segwit wallets
wallets = make_wallets(nw, wallet_structures, mean_amt, sdev_amt,
wallet_cls=SegwitLegacyWallet)
for w in wallets.values():
w['wallet'].sync_wallet(fast=True)
print(wallets)
Expand Down
6 changes: 4 additions & 2 deletions jmclient/test/test_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ def test_random_funcs():
def test_calc_cjfee():
assert calc_cj_fee("swabsoffer", 3000, 200000000) == 3000
assert calc_cj_fee("swreloffer", "0.01", 100000000) == 1000000
assert calc_cj_fee("sw0absoffer", 3000, 200000000) == 3000
assert calc_cj_fee("sw0reloffer", "0.01", 100000000) == 1000000
with pytest.raises(RuntimeError) as e_info:
calc_cj_fee("dummyoffer", 2, 3)

Expand Down Expand Up @@ -100,7 +102,7 @@ def test_choose_orders():
#(b) add an unrecognized ordertype (does not raise, ignores)
#(c) put an order with wrong minsize
orderbook.append({u'counterparty': u'fake',
u'ordertype': u'swabsoffer', u'oid': 0,
u'ordertype': u'sw0absoffer', u'oid': 0,
u'minsize': 7500000, u'txfee': 1000,
u'maxsize': 599972700, u'cjfee': 9000})
result, cjamount, total_fee = choose_sweep_orders(orderbook, 50000000,
Expand Down Expand Up @@ -132,4 +134,4 @@ def test_choose_orders():
None)
assert result == None
assert cjamount == 0
assert total_fee == 0
assert total_fee == 0
2 changes: 1 addition & 1 deletion jmclient/test/test_tx_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def test_verify_tx_input(setup_tx_creation):
scriptSig = tx.vin[0].scriptSig
tx2 = bitcoin.mktx(ins, outs)
res = bitcoin.verify_tx_input(tx2, 0, scriptSig,
bitcoin.pubkey_to_p2sh_p2wpkh_script(pub),
bitcoin.pubkey_to_p2wpkh_script(pub),
amount = bitcoin.coins_to_satoshi(1),
witness = bitcoin.CScriptWitness([sig, pub]))
assert res
Expand Down
4 changes: 2 additions & 2 deletions jmclient/test/test_yieldgenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ def test_abs_fee(self):
def test_rel_fee(self):
jm_single().DUST_THRESHOLD = 10
yg = create_yg_basic([0, 2000000, 1000000], txfee=1000, cjfee_r=0.1,
ordertype='swreloffer', minsize=10)
ordertype='sw0reloffer', minsize=10)
self.assertEqual(yg.create_my_orders(), [
{'oid': 0,
'ordertype': 'swreloffer',
'ordertype': 'sw0reloffer',
'minsize': 15000,
'maxsize': 1999000,
'txfee': 1000,
Expand Down
4 changes: 4 additions & 0 deletions jmdaemon/jmdaemon/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"swreloffer": [(int, "oid"), (int, "minsize"), (int, "maxsize"),
(int, "txfee"), (float, "cjfee")],
"swabsoffer": [(int, "oid"), (int, "minsize"), (int, "maxsize"),
(int, "txfee"), (int, "cjfee")],
"sw0reloffer": [(int, "oid"), (int, "minsize"), (int, "maxsize"),
(int, "txfee"), (float, "cjfee")],
"sw0absoffer": [(int, "oid"), (int, "minsize"), (int, "maxsize"),
(int, "txfee"), (int, "cjfee")]}

offername_list = list(offertypes.keys())
Expand Down
4 changes: 2 additions & 2 deletions scripts/joinmarket-qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -892,10 +892,10 @@ def checkOffers(self, offers_fee, cjamount):
mbinfo.append("Counterparties chosen:")
mbinfo.append('Name, Order id, Coinjoin fee (sat.)')
for k, o in iteritems(offers):
if o['ordertype'] in ['swreloffer', 'reloffer']:
if o['ordertype'] in ['sw0reloffer', 'swreloffer', 'reloffer']:
display_fee = int(self.taker.cjamount *
float(o['cjfee'])) - int(o['txfee'])
elif o['ordertype'] in ['swabsoffer', 'absoffer']:
elif o['ordertype'] in ['sw0absoffer', 'swabsoffer', 'absoffer']:
display_fee = int(o['cjfee']) - int(o['txfee'])
else:
log.debug("Unsupported order type: " + str(o['ordertype']) +
Expand Down
7 changes: 4 additions & 3 deletions scripts/obwatch/ob-watcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,16 @@ def do_nothing(arg, order, btc_unit, rel_unit):


def ordertype_display(ordertype, order, btc_unit, rel_unit):
ordertypes = {'swabsoffer': 'SW Absolute Fee', 'swreloffer': 'SW Relative Fee',
ordertypes = {'sw0absoffer': 'Native SW Absolute Fee', 'sw0reloffer': 'Native SW Relative Fee',
'swabsoffer': 'SW Absolute Fee', 'swreloffer': 'SW Relative Fee',
'absoffer': 'Absolute Fee', 'reloffer': 'Relative Fee'}
return ordertypes[ordertype]


def cjfee_display(cjfee, order, btc_unit, rel_unit):
if order['ordertype'] in ['absoffer', 'swabsoffer']:
if order['ordertype'] in ['absoffer', 'swabsoffer', 'sw0absoffer']:
return satoshi_to_unit(cjfee, order, btc_unit, rel_unit)
elif order['ordertype'] in ['reloffer', 'swreloffer']:
elif order['ordertype'] in ['reloffer', 'swreloffer', 'sw0reloffer']:
return str(Decimal(cjfee) * rel_unit_to_factor[rel_unit]) + rel_unit


Expand Down
Loading

0 comments on commit ab87db2

Please sign in to comment.