memoless swaps: set trade limit and destination address from registered memo
Revises ffe488ff (THORChain memoless swaps)
For memoless swaps, it is now forbidden to specify a trade limit or destination
address in the swap transaction invocation (second pass), as these are already
set in the reference memo registered on the THORChain network, so duplicating
them on the command line only leads to confusion.
If a trade limit was specified in the registration transaction, it’s up to the
user to ensure that the swap transaction spend amount is appropriate for the
trade limit. Increasing the spend amount is possible, but any significant
increase effectively nullifies the protection the trade limit provides.
This commit is contained in:
parent
e93aec5a19
commit
ff35b01c45
7 changed files with 28 additions and 30 deletions
|
|
@ -1 +1 @@
|
|||
16.3.0dev17
|
||||
16.3.0dev18
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ opts_data = {
|
|||
('yes', True, 'quiet', True),
|
||||
('refnum', bool, 'memoless', True),
|
||||
('no_refreq_tx', True, 'memoless', True)],
|
||||
'requires': [('coin', 'XMR', 'autosign', True)],
|
||||
'requires': [
|
||||
('coin', 'XMR', 'autosign', True),
|
||||
('refnum', bool, 'trade_limit', False)],
|
||||
'text': {
|
||||
'desc': {
|
||||
'tx': f'Create a transaction with outputs to specified coin or {gc.proj_name} addresses',
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ tx.base_swap: base swap transaction mixin class
|
|||
"""
|
||||
|
||||
from ..util import ymsg, die, cached_property
|
||||
from ..addr import CoinAddr
|
||||
|
||||
class BaseSwapMethods:
|
||||
|
||||
|
|
@ -85,7 +84,7 @@ class BaseSwapMethods:
|
|||
if rpc.data_for_coin(data, asset.coin)[key]:
|
||||
die(2, f'Trading is {state} on the {self.swap_proto_mod.name} network')
|
||||
|
||||
async def parse_network_memo(self, *, data, recv_asset_spec, recv_twmmid, chk_only=False):
|
||||
async def parse_network_memo(self, *, data, recv_asset_spec, recv_twmmid=None):
|
||||
from ..swap.util import init_swap_proto
|
||||
from ..tw.ctl import TwCtl
|
||||
pm = self.swap_proto_mod.Memo.parse(data['memo'])
|
||||
|
|
@ -100,6 +99,4 @@ class BaseSwapMethods:
|
|||
ymsg(
|
||||
f'Warning: address from registered memo ({ra.twmmid!r}) '
|
||||
f'does not match our destination address ({recv_twmmid!r})')
|
||||
return None if chk_only else (
|
||||
self._output(pm.asset.coin, self.cfg.network, CoinAddr(pm_proto, pm.address), ra.twmmid),
|
||||
pm)
|
||||
return (pm, ra)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ tx.new_swap: new swap transaction class
|
|||
import sys, time
|
||||
from collections import namedtuple
|
||||
|
||||
from ..addr import CoinAddr
|
||||
from ..amt import UniAmt
|
||||
from ..util import msg, ymsg, is_int, die
|
||||
from ..swap.util import get_swap_asset, init_swap_proto
|
||||
|
|
@ -60,7 +61,8 @@ class NewSwap(BaseSwapMethods, New):
|
|||
|
||||
full_desc = f'{desc} address on the {proto.coin} {proto.network} network'
|
||||
res = await self.get_autochg_addr(proto, arg, exclude=[], desc=full_desc)
|
||||
self.confirm_autoselected_addr(res.twmmid, res.comment, full_desc)
|
||||
if not (self.refnum and desc == 'destination'):
|
||||
self.confirm_autoselected_addr(res.twmmid, res.comment, full_desc)
|
||||
return self._output(proto.coin, proto.network, res.addr, res.twmmid)
|
||||
|
||||
async def get_chg_output(self, arg, addrfiles):
|
||||
|
|
@ -70,17 +72,6 @@ class NewSwap(BaseSwapMethods, New):
|
|||
message = 'Change address is not an MMGen wallet address!')
|
||||
return chg_output
|
||||
|
||||
def check_ref_memo(self, cls, memo, pm_ref):
|
||||
pm = cls.parse(str(memo))
|
||||
if cls.digest(pm) != cls.digest(pm_ref):
|
||||
if pm.trade_limit != pm_ref.trade_limit:
|
||||
ymsg(
|
||||
f'Trade limit has changed! {pm.trade_limit} != {pm_ref.trade_limit}\n'
|
||||
'Cannot create this transaction!')
|
||||
die(2,
|
||||
'Newly-created memo does not match registered memo:'
|
||||
f'\n new: {cls.digest(pm)}\n registered: {cls.digest(pm_ref)}')
|
||||
|
||||
async def process_swap_cmdline_args(self, cmd_args, addrfiles):
|
||||
|
||||
class CmdlineArgs: # listed in command-line order
|
||||
|
|
@ -129,6 +120,8 @@ class NewSwap(BaseSwapMethods, New):
|
|||
|
||||
# arg 5: recv_spec (receive address spec)
|
||||
if args_in:
|
||||
if self.refnum:
|
||||
die(1, 'destination address must be omitted with --refnum')
|
||||
args.recv_spec = get_arg()
|
||||
|
||||
if args_in: # done parsing, all args consumed
|
||||
|
|
@ -165,10 +158,16 @@ class NewSwap(BaseSwapMethods, New):
|
|||
chg_output = await self.get_chg_output(None, addrfiles)
|
||||
|
||||
if self.refnum:
|
||||
recv_output, parsed_ref_memo = await self.parse_network_memo(
|
||||
pm, resolved_addr = await self.parse_network_memo(
|
||||
data = self.swap_proto_rpc.validate_refnum(self.proto.coin, self.refnum),
|
||||
recv_asset_spec = self.swap_recv_asset_spec,
|
||||
recv_twmmid = args.recv_spec)
|
||||
recv_asset_spec = self.swap_recv_asset_spec)
|
||||
if pm.trade_limit:
|
||||
self.swap_cfg.trade_limit = UniAmt(pm.trade_limit, from_unit='satoshi')
|
||||
recv_output = self._output(
|
||||
self.recv_proto.coin,
|
||||
self.recv_proto.network,
|
||||
CoinAddr(self.recv_proto, pm.address),
|
||||
resolved_addr.twmmid)
|
||||
else:
|
||||
recv_output = await self.get_swap_output(
|
||||
self.recv_proto,
|
||||
|
|
@ -193,9 +192,6 @@ class NewSwap(BaseSwapMethods, New):
|
|||
self.swap_cfg.trade_limit if isinstance(self.swap_cfg.trade_limit, UniAmt)
|
||||
else None))
|
||||
|
||||
if self.refnum:
|
||||
self.check_ref_memo(sp.Memo, memo, parsed_ref_memo)
|
||||
|
||||
if self.is_memoless:
|
||||
self.memoless_memo = str(memo)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ class OnlineSigned(Signed):
|
|||
await self.parse_network_memo(
|
||||
data = data,
|
||||
recv_asset_spec = self.swap_recv_asset_spec,
|
||||
recv_twmmid = self.swap_recv_addr_mmid,
|
||||
chk_only = True)
|
||||
recv_twmmid = self.swap_recv_addr_mmid)
|
||||
|
||||
def check_swap_expiry(self):
|
||||
from ..util2 import format_elapsed_hr
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class ThornodeRPCServer(ThornodeServer):
|
|||
'0c7454c0': { # 0c7454c06d3fc0e520d34283e6f491ce7afe5abb3f569bbdfea1732e04b716ec
|
||||
'reference': '13579',
|
||||
'asset': 'LTC.LTC',
|
||||
'memo': '=:c:qq6myf0qd6q5tln96ntl37hq0u7940w2xvs9jsuqv0:0/3/0',
|
||||
'memo': '=:c:qq6myf0qd6q5tln96ntl37hq0u7940w2xvs9jsuqv0:7967e4/3/0',
|
||||
'height': '12345678'}}
|
||||
|
||||
inbounds_info = get_inbounds_info()
|
||||
|
|
|
|||
|
|
@ -372,6 +372,7 @@ class CmdTestSwap(
|
|||
('swaptxcreate_bad8', 'creating a swap transaction (bad, non-MMGen change address)'),
|
||||
('swaptxcreate_bad9', 'creating a swap transaction (bad, invalid addrtype)'),
|
||||
('swaptxcreate_bad10', 'creating a swap transaction (bad, --quote with no amount)'),
|
||||
('swaptxcreate_bad11', 'creating a swap transaction (bad, --refnum with --trade-limit)'),
|
||||
),
|
||||
'create_neterror': (
|
||||
'Swap TX create operations: network error handling',
|
||||
|
|
@ -656,6 +657,9 @@ class CmdTestSwap(
|
|||
def swaptxcreate_bad10(self):
|
||||
return self._swaptxcreate_bad(['BCH', 'LTC'], add_opts=['--quote'], exit_val=1, expect1='send amount')
|
||||
|
||||
def swaptxcreate_bad11(self):
|
||||
return self._swaptxcreate_bad(['BCH', 'LTC'], add_opts=['--refnum=123', '--trade-limit=1%'], exit_val=1, expect1='requires option')
|
||||
|
||||
def swaptxcreate_neterror1(self):
|
||||
return self._swaptxcreate_neterror('ltc_global_paused', 'Trading is paused on the')
|
||||
|
||||
|
|
@ -868,7 +872,7 @@ class CmdTestSwap(
|
|||
self.get_file_with_ext('rawtx', delete_all=True)
|
||||
return self._memoless_swaptxcreate(
|
||||
['LTC', '2.345', f'{self.subsid}:B:1', 'BCH', f'{self.sid}:C:2'],
|
||||
opts = ['--memoless'],
|
||||
opts = ['--memoless', '--trade-limit=2.5%'],
|
||||
refreq = True)
|
||||
|
||||
refreq_swaptxsign = rune_txsign_refreq
|
||||
|
|
@ -887,7 +891,7 @@ class CmdTestSwap(
|
|||
refnum = True)
|
||||
|
||||
def refnum_swaptxcreate1(self):
|
||||
return self._refnum_swaptxcreate(['LTC', '2.345', f'{self.subsid}:B:1', 'BCH', f'{self.sid}:C:2'])
|
||||
return self._refnum_swaptxcreate(['LTC', '2.345', f'{self.subsid}:B:1', 'BCH'])
|
||||
|
||||
def refnum_swaptxsign1(self):
|
||||
return self._swaptxsign()
|
||||
|
|
|
|||
Loading…
Reference in a new issue