tx: new Sent class; tx.send() clean up error handling

This commit is contained in:
The MMGen Project 2024-02-22 12:48:14 +00:00
commit 8d6f9f598b
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
11 changed files with 72 additions and 55 deletions

View file

@ -175,8 +175,8 @@ async def main():
if tx3:
tx4 = await OnlineSignedTX(cfg=cfg,data=tx3.__dict__)
tx4.file.write(ask_write=False)
await tx4.send(exit_on_fail=True)
tx4.file.write(ask_write=False)
if await tx4.send():
tx4.file.write(ask_write=False)
else:
die(2,'Transaction could not be signed')
else:

View file

@ -124,7 +124,7 @@ FMT CODES:
cfg = Config(opts_data=opts_data)
from .tx import NewTX,OnlineSignedTX
from .tx import NewTX, SentTX
from .tx.sign import txsign,get_seed_files,get_keyaddrlist,get_keylist
seed_files = get_seed_files(cfg,cfg._args)
@ -147,11 +147,11 @@ async def main():
tx3 = await txsign(cfg,tx2,seed_files,kl,kal)
if tx3:
tx4 = await OnlineSignedTX(cfg=cfg,data=tx3.__dict__)
tx4.file.write(ask_write=False)
await tx4.send(exit_on_fail=True)
tx4.file.write(ask_overwrite=False,ask_write=False)
tx4.print_contract_addr()
tx3.file.write(ask_write=False)
tx4 = await SentTX(cfg=cfg, data=tx3.__dict__)
if await tx4.send():
tx4.file.write(ask_overwrite=False,ask_write=False)
tx4.print_contract_addr()
else:
die(2,'Transaction could not be signed')

View file

@ -56,7 +56,7 @@ if not cfg.status:
async def main():
from .tx import OnlineSignedTX
from .tx import OnlineSignedTX, SentTX
tx = await OnlineSignedTX(
cfg = cfg,
@ -79,10 +79,11 @@ async def main():
if tx.add_comment(): # edits an existing comment, returns true if changed
tx.file.write(ask_write_default_yes=True)
await tx.send(exit_on_fail=True)
tx.file.write(
ask_overwrite = False,
ask_write = False)
tx.print_contract_addr()
if await tx.send():
tx2 = await SentTX(cfg=cfg, data=tx.__dict__)
tx2.file.write(
ask_overwrite = False,
ask_write = False)
tx2.print_contract_addr()
async_run(main())

View file

@ -12,15 +12,14 @@
proto.btc.tx.online: Bitcoin online signed transaction class
"""
import sys
from ....tx import online as TxBase
from ....util import msg,ymsg,rmsg,die
from ....util import msg,die
from ....color import orange
from .signed import Signed
class OnlineSigned(Signed,TxBase.OnlineSigned):
async def send(self,prompt_user=True,exit_on_fail=False):
async def send(self,prompt_user=True):
self.check_correct_chain()
@ -49,6 +48,7 @@ class OnlineSigned(Signed,TxBase.OnlineSigned):
ret = await self.rpc.call('sendrawtransaction',self.serialized)
except Exception as e:
errmsg = str(e)
nl = '\n'
if errmsg.count('Signature must use SIGHASH_FORKID'):
m = (
'The Aug. 1 2017 UAHF has activated on this chain.\n'
@ -61,20 +61,19 @@ class OnlineSigned(Signed,TxBase.OnlineSigned):
m = "Transaction with nLockTime {!r} can't be included in this block!".format(
self.strfmt_locktime(self.get_serialized_locktime()))
else:
m = errmsg
ymsg(m)
rmsg(f'Send of MMGen transaction {self.txid} failed')
if exit_on_fail:
sys.exit(1)
return False
m,nl = ('','')
msg(orange('\n'+errmsg))
die(2, f'{m}{nl}Send of MMGen transaction {self.txid} failed')
else:
assert ret == self.coin_txid, 'txid mismatch (after sending)'
msg(m.format(self.coin_txid.hl()))
self.add_timestamp()
self.add_sent_timestamp()
self.add_blockcount()
self.desc = 'sent transaction'
return True
def print_contract_addr(self):
pass
class Sent(TxBase.Sent, OnlineSigned):
pass

View file

@ -12,14 +12,15 @@
proto.eth.tx.online: Ethereum online signed transaction class
"""
from ....util import msg,rmsg,die
from ....util import msg,die
from ....color import orange
from ....tx import online as TxBase
from .. import erigon_sleep
from .signed import Signed,TokenSigned
class OnlineSigned(Signed,TxBase.OnlineSigned):
async def send(self,prompt_user=True,exit_on_fail=False):
async def send(self,prompt_user=True):
self.check_correct_chain()
@ -36,32 +37,22 @@ class OnlineSigned(Signed,TxBase.OnlineSigned):
self.confirm_send()
if self.cfg.bogus_send:
ret = None
m = 'BOGUS transaction NOT sent: {}'
else:
try:
ret = await self.rpc.call('eth_sendRawTransaction','0x'+self.serialized)
except:
raise # TODO: raises immediately
ret = False # TODO: unreachable code
except Exception as e:
msg(orange('\n'+str(e)))
die(2, f'Send of MMGen transaction {self.txid} failed')
m = 'Transaction sent: {}'
assert ret == '0x'+self.coin_txid,'txid mismatch (after sending)'
await erigon_sleep(self)
if ret is False: # TODO: unreachable code
rmsg(f'Send of MMGen transaction {self.txid} failed')
if exit_on_fail:
import sys
sys.exit(1)
return False
else:
if self.cfg.bogus_send:
m = 'BOGUS transaction NOT sent: {}'
else:
m = 'Transaction sent: {}'
assert ret == '0x'+self.coin_txid,'txid mismatch (after sending)'
await erigon_sleep(self)
self.desc = 'sent transaction'
msg(m.format(self.coin_txid.hl()))
self.add_timestamp()
self.add_blockcount()
return True
msg(m.format(self.coin_txid.hl()))
self.add_sent_timestamp()
self.add_blockcount()
return True
def print_contract_addr(self):
if 'token_addr' in self.txobj:
@ -80,3 +71,9 @@ class TokenOnlineSigned(TokenSigned,OnlineSigned):
t = Token(self.cfg,self.proto,o['token_addr'],o['decimals'])
o['amt'] = t.transferdata2amt(o['data'])
o['token_to'] = t.transferdata2sendaddr(o['data'])
class Sent(TxBase.Sent, OnlineSigned):
pass
class TokenSent(TxBase.Sent, TokenOnlineSigned):
pass

View file

@ -73,7 +73,8 @@ async def _get_obj_async( _clsname, _modname, *args, **kwargs ):
# signing.
if proto and proto.tokensym and clsname in (
'New',
'OnlineSigned'):
'OnlineSigned',
'Sent'):
from ..tw.ctl import TwCtl
kwargs['twctl'] = await TwCtl(cfg,proto)
@ -92,4 +93,5 @@ NewTX = _get_async('New', 'new')
CompletedTX = _get_async('Completed', 'completed')
SignedTX = _get_async('Signed', 'signed')
OnlineSignedTX = _get_async('OnlineSigned', 'online')
SentTX = _get_async('Sent', 'online')
BumpTX = _get_async('Bump', 'bump')

View file

@ -77,6 +77,7 @@ class Base(MMGenObject):
txid = None
coin_txid = None
timestamp = None
sent_timestamp = None
blockcount = None
locktime = None
chain = None
@ -162,6 +163,9 @@ class Base(MMGenObject):
def add_timestamp(self):
self.timestamp = make_timestamp()
def add_sent_timestamp(self):
self.sent_timestamp = make_timestamp()
def add_blockcount(self):
self.blockcount = self.rpc.blockcount

View file

@ -58,8 +58,10 @@ class Completed(Base):
see twctl:import_token()
"""
from .unsigned import Unsigned
if ext == Unsigned.ext:
return Unsigned
from .online import Sent
for cls in (Unsigned, Sent):
if ext == getattr(cls, 'ext'):
return cls
if proto.tokensym:
from .online import OnlineSigned as Signed

View file

@ -72,6 +72,11 @@ class MMGenTxFile(MMGenObject):
self.chksum = HexStr(tx_data.pop(0))
assert self.chksum == make_chksum_6(' '.join(tx_data)),'file data does not match checksum'
if len(tx_data) == 7:
desc = 'sent timestamp'
(_, tx.sent_timestamp) = tx_data.pop(-1).split()
assert _ == 'Sent', 'invalid sent timestamp line'
if len(tx_data) == 6:
assert len(tx_data[-1]) == 64,'invalid coin TxID length'
desc = 'coin TxID'
@ -186,6 +191,9 @@ class MMGenTxFile(MMGenObject):
lines.append('-') # keep old tx files backwards compatible
lines.append(tx.coin_txid)
if tx.sent_timestamp:
lines.append(f'Sent {tx.sent_timestamp}')
self.chksum = make_chksum_6(' '.join(lines))
fmt_data = '\n'.join([self.chksum] + lines) + '\n'
if len(fmt_data) > tx.cfg.max_tx_file_size:

View file

@ -56,7 +56,7 @@ class TxInfo:
orange(self.strfmt_locktime(terse=True)) if tx.locktime else
green('None') ))
for attr,label in [('timestamp','Created:')]:
for attr,label in [('timestamp','Created:'),('sent_timestamp','Sent:')]:
if (val := getattr(tx,attr)) is not None:
_ = decode_timestamp(val)
yield f'{label:8} {make_timestr(_)} ({format_elapsed_hr(_)})\n'

View file

@ -30,3 +30,7 @@ class OnlineSigned(Signed):
action = f'broadcast this transaction to the {self.proto.coin} {self.proto.network.upper()} network',
expect = 'YES' if self.cfg.quiet or self.cfg.yes else 'YES, I REALLY WANT TO DO THIS' )
msg('Sending transaction')
class Sent(OnlineSigned):
desc = 'sent transaction'
ext = 'subtx'