tx: fix nLocktime functionality, uint64 parsing; add locktime tests
This commit is contained in:
parent
79f1bac97f
commit
72a93dfcb5
9 changed files with 65 additions and 23 deletions
|
|
@ -48,8 +48,6 @@ def DeserializeTX(proto,txhex):
|
|||
"""
|
||||
|
||||
def bytes2int(bytes_le):
|
||||
if bytes_le[-1] & 0x80: # sign bit is set
|
||||
die(3,"{}: Negative values not permitted in transaction!".format(bytes_le[::-1].hex()))
|
||||
return int(bytes_le[::-1].hex(),16)
|
||||
|
||||
def bytes2coin_amt(bytes_le):
|
||||
|
|
@ -95,6 +93,9 @@ def DeserializeTX(proto,txhex):
|
|||
|
||||
d = { 'version': bytes2int(bshift(4)) }
|
||||
|
||||
if d['version'] > 0x7fffffff: # version is signed integer
|
||||
die(3,f"{d['version']}: transaction version greater than maximum allowed value (int32_t)!")
|
||||
|
||||
has_witness = tx[idx] == 0
|
||||
if has_witness:
|
||||
u = bshift(2,skip=True).hex()
|
||||
|
|
|
|||
|
|
@ -128,7 +128,9 @@ class TxInfo(TxInfo):
|
|||
num = locktime or self.tx.locktime
|
||||
if num is None:
|
||||
return '(None)'
|
||||
elif num >= 5 * 10**6:
|
||||
elif num.bit_length() > 32:
|
||||
die(2,f'{num!r}: invalid nLockTime value (integer size greater than 4 bytes)!')
|
||||
elif num >= 500_000_000:
|
||||
import time
|
||||
return ' '.join(time.strftime('%c',time.gmtime(num)).split()[1:])
|
||||
elif num > 0:
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ class New(Base,TxBase.New):
|
|||
ret = await self.rpc.call( 'createrawtransaction', inputs_list, outputs_dict )
|
||||
|
||||
if locktime and not bump:
|
||||
msg(f'Setting nLockTime to {self.strfmt_locktime(locktime)}!')
|
||||
msg(f'Setting nLockTime to {self.info.strfmt_locktime(locktime)}!')
|
||||
assert isinstance(locktime,int), 'locktime value not an integer'
|
||||
self.locktime = locktime
|
||||
ret = ret[:-8] + bytes.fromhex(f'{locktime:08x}')[::-1].hex()
|
||||
|
|
|
|||
|
|
@ -57,9 +57,9 @@ class OnlineSigned(Signed,TxBase.OnlineSigned):
|
|||
m = (
|
||||
'The Aug. 1 2017 UAHF is not yet active on this chain.\n'
|
||||
'Re-run the script without the --coin=bch option.')
|
||||
elif errmsg.count('64: non-final'):
|
||||
m = "Transaction with nLockTime {!r} can't be included in this block!".format(
|
||||
self.strfmt_locktime(self.get_serialized_locktime()))
|
||||
elif errmsg.count('non-final'):
|
||||
m = "Transaction with nLockTime {!r} can’t be included in this block!".format(
|
||||
self.info.strfmt_locktime(self.get_serialized_locktime()))
|
||||
else:
|
||||
m,nl = ('','')
|
||||
msg(orange('\n'+errmsg))
|
||||
|
|
|
|||
|
|
@ -51,9 +51,6 @@ class Completed(Base,TxBase.Completed):
|
|||
def check_pubkey_scripts(self):
|
||||
pass
|
||||
|
||||
def strfmt_locktime(self,locktime=None,terse=False):
|
||||
pass
|
||||
|
||||
def get_serialized_locktime(self):
|
||||
return None # TODO
|
||||
|
||||
|
|
|
|||
|
|
@ -123,6 +123,11 @@ class Base(MMGenObject):
|
|||
def dcoin(self):
|
||||
return self.proto.dcoin
|
||||
|
||||
@property
|
||||
def info(self):
|
||||
from .info import init_info
|
||||
return init_info(self)
|
||||
|
||||
def check_correct_chain(self):
|
||||
if hasattr(self,'rpc'):
|
||||
if self.chain != self.rpc.chain:
|
||||
|
|
|
|||
|
|
@ -42,11 +42,6 @@ class Completed(Base):
|
|||
from ..util import die
|
||||
die(1,'Transaction is {}signed!'.format('not ' if self.signed else ''))
|
||||
|
||||
@property
|
||||
def info(self):
|
||||
from .info import init_info
|
||||
return init_info(self)
|
||||
|
||||
@property
|
||||
def file(self):
|
||||
from .file import MMGenTxFile
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
|
|||
('subgroup.msg', ['init_bob']),
|
||||
('subgroup.twexport', ['fund_users']),
|
||||
('subgroup.rescan', ['fund_users']),
|
||||
('subgroup.errors', ['fund_users']),
|
||||
('subgroup.main', ['fund_users']),
|
||||
('subgroup.twprune', ['main']),
|
||||
('subgroup.txhist', ['main']),
|
||||
|
|
@ -265,6 +266,12 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
|
|||
('bob_rescan_blockchain_one', 'rescanning the blockchain (single block)'),
|
||||
('bob_rescan_blockchain_ss', 'rescanning the blockchain (range of blocks)'),
|
||||
),
|
||||
'errors': (
|
||||
'various error conditions',
|
||||
('bob_bad_locktime1', 'broadcast of transaction with bad locktime (block)'),
|
||||
('bob_bad_locktime2', 'broadcast of transaction with bad locktime (integer size)'),
|
||||
('bob_bad_locktime3', 'broadcast of transaction with bad locktime (time)'),
|
||||
),
|
||||
'main': (
|
||||
'creating, signing, sending and bumping transactions',
|
||||
('bob_add_comment1', "adding an 80-screen-width label (lat+cyr+gr)"),
|
||||
|
|
@ -911,15 +918,16 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
|
|||
t.expect(exp2,regex=True)
|
||||
return t
|
||||
|
||||
def user_txdo(
|
||||
self,
|
||||
def user_txdo( self,
|
||||
user,
|
||||
fee,
|
||||
outputs_cl,
|
||||
outputs_list,
|
||||
extra_args = [],
|
||||
wf = None,
|
||||
bad_locktime = False,
|
||||
add_comment = tx_comment_jp,
|
||||
return_early = False,
|
||||
return_after_send = False,
|
||||
menu = ['M'],
|
||||
skip_passphrase = False,
|
||||
used_chg_addr_resp = None):
|
||||
|
|
@ -936,25 +944,29 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
|
|||
inputs = outputs_list,
|
||||
file_desc = 'Signed transaction',
|
||||
interactive_fee = (tx_fee,'')[bool(fee)],
|
||||
add_comment = tx_comment_jp,
|
||||
add_comment = add_comment,
|
||||
return_early = return_early,
|
||||
view = 't',
|
||||
save = True,
|
||||
used_chg_addr_resp = used_chg_addr_resp)
|
||||
|
||||
if return_early:
|
||||
return t
|
||||
|
||||
if not skip_passphrase:
|
||||
t.passphrase(dfl_wcls.desc,rt_pw)
|
||||
|
||||
t.written_to_file('Signed transaction')
|
||||
self._do_confirm_send(t)
|
||||
s,exit_val = (('Transaction sent',0),("can't be included",1))[bad_locktime]
|
||||
t.expect(s)
|
||||
t.req_exit_val = exit_val
|
||||
if return_after_send:
|
||||
return t
|
||||
t.expect('Transaction sent')
|
||||
return t
|
||||
|
||||
def bob_split1(self):
|
||||
sid = self._user_sid('bob')
|
||||
outputs_cl = [sid+':C:1,100', sid+':L:2,200',sid+':'+rtBobOp3]
|
||||
return self.user_txdo('bob',rtFee[0],outputs_cl,'1')
|
||||
return self.user_txdo('bob',rtFee[0],outputs_cl,'1',extra_args=['--locktime=500000001'])
|
||||
|
||||
def get_addr_from_addrlist(self,user,sid,mmtype,idx,addr_range='1-5'):
|
||||
id_str = { 'L':'', 'S':'-S', 'C':'-C', 'B':'-B' }[mmtype]
|
||||
|
|
@ -1427,6 +1439,31 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
|
|||
t.expect('Removed label.*in tracking wallet',regex=True)
|
||||
return t
|
||||
|
||||
def bob_bad_locktime1(self):
|
||||
return self._bob_bad_locktime(123456789, 'non-final', 2) # > current block height
|
||||
|
||||
def bob_bad_locktime2(self):
|
||||
return self._bob_bad_locktime(7_000_000_000, 'invalid', 2, return_early=True) # > 4 bytes
|
||||
|
||||
def bob_bad_locktime3(self):
|
||||
return self._bob_bad_locktime(0xffffffff, 'non-final', 2, return_early=False) # > cur time
|
||||
|
||||
def _bob_bad_locktime(self,locktime,expect,exit_val,return_early=False):
|
||||
sid = self._user_sid('bob')
|
||||
t = self.user_txdo(
|
||||
user = 'bob',
|
||||
fee = '20s',
|
||||
outputs_cl = [self.burn_addr+',0.1', sid+':C:5'],
|
||||
outputs_list = '1',
|
||||
extra_args = [f'--locktime={locktime}'],
|
||||
return_early = return_early,
|
||||
add_comment = False,
|
||||
return_after_send = True)
|
||||
t.req_exit_val = exit_val
|
||||
if expect:
|
||||
t.expect(expect)
|
||||
return t
|
||||
|
||||
def bob_add_comment1(self):
|
||||
sid = self._user_sid('bob')
|
||||
return self.user_add_comment('bob',sid+':C:1',tw_comment_lat_cyr_gr)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ class CmdTestShared:
|
|||
add_comment = '',
|
||||
view = 't',
|
||||
save = True,
|
||||
return_early = False,
|
||||
tweaks = [],
|
||||
used_chg_addr_resp = None,
|
||||
auto_chg_addr = None):
|
||||
|
|
@ -107,6 +108,10 @@ class CmdTestShared:
|
|||
t.expect('Continue? (Y/n)','\n')
|
||||
|
||||
t.do_comment(add_comment)
|
||||
|
||||
if return_early:
|
||||
return t
|
||||
|
||||
t.view_tx(view)
|
||||
if not txdo:
|
||||
t.expect('(y/N): ',('n','y')[save])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue