From 2c97f61ea490b409bc1bb5c7e981b78c161fd175 Mon Sep 17 00:00:00 2001 From: MMGen Date: Thu, 31 May 2018 19:02:00 +0000 Subject: [PATCH] Ethereum autosigning --- mmgen/main_autosign.py | 8 ++++++-- mmgen/protocol.py | 2 ++ mmgen/tx.py | 13 ++++++++----- test/ref/ethereum/BC79AB-ETH[0.123].rawtx | 5 +++++ test/test.py | 8 +++++--- 5 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 test/ref/ethereum/BC79AB-ETH[0.123].rawtx diff --git a/mmgen/main_autosign.py b/mmgen/main_autosign.py index ca459ac4..22b22e5d 100755 --- a/mmgen/main_autosign.py +++ b/mmgen/main_autosign.py @@ -29,6 +29,8 @@ part_label = u'MMGEN_TX' wallet_dir = u'/dev/shm/autosign' key_fn = u'autosign.key' +no_daemon_coins = ('ETH',) + from mmgen.common import * prog_name = os.path.basename(sys.argv[0]) opts_data = lambda: { @@ -119,6 +121,7 @@ def check_daemons_running(): coins = ['BTC'] for coin in coins: + if coin in no_daemon_coins: continue g.proto = CoinProtocol(coin,g.testnet) vmsg('Checking {} daemon'.format(coin)) try: @@ -153,10 +156,11 @@ def do_umount(): def sign_tx_file(txfile): try: - init_coin(mmgen.tx.MMGenTX(txfile,md_only=True).coin) + init_coin(mmgen.tx.MMGenTX(txfile,coin_sym_only=True).coin) reload(sys.modules['mmgen.tx']) tx = mmgen.tx.MMGenTX(txfile) - rpc_init(reinit=True) + if tx.coin not in no_daemon_coins: + rpc_init(reinit=True) txsign(tx,wfs,None,None) tx.write_to_file(ask_write=False) return True diff --git a/mmgen/protocol.py b/mmgen/protocol.py index 633e8e23..f0f9c91b 100755 --- a/mmgen/protocol.py +++ b/mmgen/protocol.py @@ -90,6 +90,7 @@ class BitcoinProtocol(MMGenObject): witness_vernum_hex = '00' witness_vernum = int(witness_vernum_hex,16) bech32_hrp = 'bc' + chain_aliases = {} @classmethod def is_testnet(cls): @@ -303,6 +304,7 @@ class EthereumProtocol(DummyWIF,BitcoinProtocolAddrgen): rpc_port = 8545 mmcaps = ('key','addr','rpc') coin_amt = ETHAmt + chain_aliases = {'mainnet':['foundation'],'testnet':['kovan']} @classmethod diff --git a/mmgen/tx.py b/mmgen/tx.py index 54f536c9..e40273c0 100755 --- a/mmgen/tx.py +++ b/mmgen/tx.py @@ -275,7 +275,7 @@ class MMGenTX(MMGenObject): cls = EthereumMMGenTX return MMGenObject.__new__(cls,*args,**kwargs) - def __init__(self,filename=None,md_only=False,caller=None,silent_open=False): + def __init__(self,filename=None,coin_sym_only=False,caller=None,silent_open=False): self.inputs = self.MMGenTxInputList() self.outputs = self.MMGenTxOutputList() self.send_amt = g.proto.coin_amt('0') # total amt minus change @@ -295,8 +295,8 @@ class MMGenTX(MMGenObject): self.locktime = None if filename: - self.parse_tx_file(filename,md_only=md_only,silent_open=silent_open) - if md_only: return + self.parse_tx_file(filename,coin_sym_only=coin_sym_only,silent_open=silent_open) + if coin_sym_only: return self.check_sigs() # marks the tx as signed # repeat with sign and send, because coin daemon could be restarted @@ -306,6 +306,8 @@ class MMGenTX(MMGenObject): assert on_fail in ('return','die'),"'{}': invalid value for 'on_fail'".format(on_fail) m = 'Transaction is for {}, but current chain is {}!'.format(self.chain,g.chain) bad = self.chain and g.chain and self.chain != g.chain + if bad and g.chain in g.proto.chain_aliases: + bad = self.chain not in g.proto.chain_aliases[g.chain] if bad: msg(m) if on_fail == 'return' else die(2,m) return not bad @@ -1089,7 +1091,7 @@ class MMGenTX(MMGenObject): def check_tx_hex_data(self): self.hex = HexStr(self.hex,on_fail='raise') - def parse_tx_file(self,infile,md_only=False,silent_open=False): + def parse_tx_file(self,infile,coin_sym_only=False,silent_open=False): def eval_io_data(raw_data,desc): from ast import literal_eval @@ -1147,6 +1149,7 @@ class MMGenTX(MMGenObject): self.locktime = int(metadata.pop()[3:]) self.coin = metadata.pop(0) if len(metadata) == 6 else 'BTC' + if coin_sym_only: return if len(metadata) == 5: t = metadata.pop(0) @@ -1161,7 +1164,7 @@ class MMGenTX(MMGenObject): self.blockcount = int(blockcount) desc = 'transaction hex data' self.check_tx_hex_data() - if md_only: return # the following ops will all fail if g.coin doesn't match self.coin + # the following ops will all fail if g.coin doesn't match self.coin desc = 'coin type in metadata' assert self.coin == g.coin,'invalid coin type' desc = 'inputs data' diff --git a/test/ref/ethereum/BC79AB-ETH[0.123].rawtx b/test/ref/ethereum/BC79AB-ETH[0.123].rawtx new file mode 100644 index 00000000..c7720585 --- /dev/null +++ b/test/ref/ethereum/BC79AB-ETH[0.123].rawtx @@ -0,0 +1,5 @@ +59b070 +ETH FOUNDATION BC79AB 0.123 20180530_125230 7513928 +{"nonce": "0", "chainId": "0x1", "from": "e704b6cfd9f0edb2e6cfbd0c913438d37ede7b35", "to": "62ff8e4dbd251b98102e3fb5e4b14119e24cadde", "amt": "0.123", "gasPrice": "0.000000050"} +[{'confs': 0, 'addr': 'e704b6cfd9f0edb2e6cfbd0c913438d37ede7b35', 'vout': 0, 'txid': '0000000000000000000000000000000000000000000000000000000000000000', 'label': u'', 'amt': '1.234567', 'mmid': '98831F3A:E:1'}] +[{'mmid': '98831F3A:E:31', 'amt': '0.123', 'addr': '62ff8e4dbd251b98102e3fb5e4b14119e24cadde'}] diff --git a/test/test.py b/test/test.py index 274920d7..7d1583db 100755 --- a/test/test.py +++ b/test/test.py @@ -166,6 +166,7 @@ tn_ext = ('','.testnet')[g.testnet] coin_sel = g.coin.lower() # if g.coin == 'B2X': coin_sel = 'btc' +if g.coin == 'ETH': coin_sel = 'btc' # TODO fork = {'bch':'btc','btc':'btc','ltc':'ltc'}[coin_sel] tx_fee = {'btc':'0.0001','bch':'0.001','ltc':'0.01'}[coin_sel] @@ -550,6 +551,7 @@ cfgs = { 'bch': '99BE60-BCH[106.6789]{}.rawtx', 'b2x': '6A52BC-B2X[106.6789,tl=1320969600]{}.rawtx', 'ltc': '75F455-LTC[106.6789]{}.rawtx', + 'eth': 'BC79AB-ETH[0.123]{}.rawtx', }, 'ic_wallet': u'98831F3A-5482381C-18460FB1[256,1].mmincog', 'ic_wallet_hex': u'98831F3A-1630A9F2-870376A9[256,1].mmincox', @@ -2117,7 +2119,7 @@ class MMGenTestSuite(object): # Miscellaneous tests def autosign(self,name): # tests everything except device detection, mount/unmount if skip_for_win(): return - fdata = (('btc',''),('bch',''),('ltc','litecoin')) + fdata = (('btc',''),('bch',''),('ltc','litecoin'),('eth','ethereum')) tfns = [cfgs['8']['ref_tx_file'][c].format('') for c,d in fdata] tfs = [os.path.join(ref_dir,d[1],fn) for d,fn in zip(fdata,tfns)] try: os.mkdir(os.path.join(cfg['tmpdir'],'tx')) @@ -2127,7 +2129,7 @@ class MMGenTestSuite(object): # make a bad tx file with open(os.path.join(cfg['tmpdir'],'tx','bad.rawtx'),'w') as f: f.write('bad tx data') - opts = ['--mountpoint='+cfg['tmpdir'],'--coins=btc,bch,ltc'] + opts = ['--mountpoint='+cfg['tmpdir'],'--coins=btc,bch,ltc,eth'] mn_fn = os.path.join(ref_dir,cfgs['8']['seed_id']+'.mmwords') mn = read_from_file(mn_fn).strip().split() @@ -2144,7 +2146,7 @@ class MMGenTestSuite(object): t.ok() t = MMGenExpect(name,'mmgen-autosign',opts+['wait'],extra_desc='(sign)') - t.expect('3 transactions signed') + t.expect('4 transactions signed') t.expect('1 transaction failed to sign') t.expect('Waiting.') t.kill(2)