From 9dfd06bbd09d3c9b00108fec5511d2e2c087d079 Mon Sep 17 00:00:00 2001 From: MMGen Date: Mon, 4 Jun 2018 20:46:56 +0000 Subject: [PATCH] tx.py: check for pubkey script / address mismatch --- mmgen/altcoins/eth/tx.py | 2 ++ mmgen/tx.py | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/mmgen/altcoins/eth/tx.py b/mmgen/altcoins/eth/tx.py index b51d83f7..20525559 100755 --- a/mmgen/altcoins/eth/tx.py +++ b/mmgen/altcoins/eth/tx.py @@ -46,6 +46,8 @@ class EthereumMMGenTX(MMGenTX): def get_hex_locktime(self): return None # TODO + def check_pubkey_scripts(self): pass + def check_sigs(self,deserial_tx=None): if is_hex_str(self.hex): self.mark_signed() diff --git a/mmgen/tx.py b/mmgen/tx.py index e40273c0..b0c71b9a 100755 --- a/mmgen/tx.py +++ b/mmgen/tx.py @@ -123,11 +123,11 @@ def bytes2coin_amt(hex_bytes): def scriptPubKey2addr(s): if len(s) == 50 and s[:6] == '76a914' and s[-4:] == '88ac': - return g.proto.pubhash2addr(s[6:-4],p2sh=False) + return g.proto.pubhash2addr(s[6:-4],p2sh=False),'p2pkh' elif len(s) == 46 and s[:4] == 'a914' and s[-2:] == '87': - return g.proto.pubhash2addr(s[4:-2],p2sh=True) + return g.proto.pubhash2addr(s[4:-2],p2sh=True),'p2sh' elif len(s) == 44 and s[:4] == g.proto.witness_vernum_hex + '14': - return g.proto.pubhash2bech32addr(s[4:]) + return g.proto.pubhash2bech32addr(s[4:]),'bech32' else: raise NotImplementedError,'Unknown scriptPubKey ({})'.format(s) @@ -179,7 +179,7 @@ class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types )) for i in range(d['num_txouts'])]) for o in d['txouts']: - o['address'] = scriptPubKey2addr(o['scriptPubKey']) + o['address'] = scriptPubKey2addr(o['scriptPubKey'])[0] d['witness_size'] = 0 if has_witness: @@ -297,6 +297,7 @@ class MMGenTX(MMGenObject): if filename: self.parse_tx_file(filename,coin_sym_only=coin_sym_only,silent_open=silent_open) if coin_sym_only: return + self.check_pubkey_scripts() self.check_sigs() # marks the tx as signed # repeat with sign and send, because coin daemon could be restarted @@ -684,6 +685,8 @@ class MMGenTX(MMGenObject): ymsg("TX has Segwit inputs or outputs, but {} doesn't support Segwit!".format(g.coin)) return False + self.check_pubkey_scripts() + qmsg('Passing {} key{} to {}'.format(len(keys),suf(keys,'s'),g.proto.daemon_name)) if self.has_segwit_inputs(): @@ -779,6 +782,18 @@ class MMGenTX(MMGenObject): if str(self.txid) != make_chksum_6(unhexlify(uh)).upper(): rdie(3,'MMGen TxID ({}) does not match hex transaction data!\n{}'.format(self.txid,m)) + def check_pubkey_scripts(self): + for n,i in enumerate(self.inputs,1): + addr,fmt = scriptPubKey2addr(i.scriptPubKey) + if i.addr != addr: + if fmt != i.addr.addr_fmt: + m = 'Address format of scriptPubKey ({}) does not match that of address ({}) in input #{}' + msg(m.format(fmt,i.addr.addr_fmt,n)) + m = 'ERROR: Address and scriptPubKey of transaction input #{} do not match!' + die(3,(m+'\n {:23}{}'*3).format(n, 'address:',i.addr, + 'scriptPubKey:',i.scriptPubKey, + 'scriptPubKey->address:',addr )) + # check signature and witness data def check_sigs(self,deserial_tx=None): # return False if no sigs, die on error txins = (deserial_tx or DeserializedTX(self.hex))['txins'] @@ -875,6 +890,8 @@ class MMGenTX(MMGenObject): self.check_correct_chain(on_fail='die') + self.check_pubkey_scripts() + self.check_hex_tx_matches_mmgen_tx(DeserializedTX(self.hex)) bogus_send = os.getenv('MMGEN_BOGUS_SEND')