Browse Source

py3port: Ethereum-related changes

MMGen 6 years ago
parent
commit
9d694488d9
2 changed files with 49 additions and 46 deletions
  1. 21 12
      mmgen/altcoins/eth/contract.py
  2. 28 34
      mmgen/altcoins/eth/tx.py

+ 21 - 12
mmgen/altcoins/eth/contract.py

@@ -42,10 +42,10 @@ class Token(MMGenObject): # ERC20
 	def __init__(self,addr,decimals=None):
 		self.addr = TokenAddr(addr)
 		if decimals is None:
-			ret_hex = self.do_call('decimals()')
-			try: decimals = int(ret_hex,16)
-			except: raise TokenNotInBlockchain("Token '{}' not in blockchain".format(addr))
-		self.base_unit = Decimal(10) ** -decimals
+			decimals = self.decimals()
+			if not decimals:
+				raise TokenNotInBlockchain("Token '{}' not in blockchain".format(addr))
+		self.base_unit = Decimal('10') ** -decimals
 
 	def transferdata2amt(self,data): # online
 		return ETHAmt(int(parse_abi(data)[-1],16) * self.base_unit)
@@ -61,10 +61,17 @@ class Token(MMGenObject): # ERC20
 		return self.do_call('balanceOf(address)',acct_addr.rjust(64,'0'),toUnit=True)
 
 	def strip(self,s):
-		return ''.join(ch for ch in s if 32 <= ord(ch) <= 127).strip()
+		return ''.join([chr(b) for b in s if 32 <= b <= 127]).strip()
 
 	def total_supply(self): return self.do_call('totalSupply()',toUnit=True)
-	def decimals(self):     return int(self.do_call('decimals()'),16)
+	def decimals(self):
+			ret = self.do_call('decimals()')
+			try:
+				a,b = ret[:2],ret[2:]
+				assert a == '0x' and is_hex_str_lc(b)
+			except:
+				"RPC call to decimals() failed (returned '{}')".format(ret)
+			return int(b,16) if b else None
 	def name(self):         return self.strip(unhexlify(self.do_call('name()')[2:]))
 	def symbol(self):       return self.strip(unhexlify(self.do_call('symbol()')[2:]))
 
@@ -79,12 +86,6 @@ class Token(MMGenObject): # ERC20
 	def code(self):
 		return g.rpch.eth_getCode('0x'+self.addr)[2:]
 
-	def transfer_from(self,from_addr,to_addr,amt,key,start_gas,gasPrice):
-		raise NotImplementedError('method not implemented')
-		return self.transfer(   from_addr,to_addr,amt,key,start_gas,gasPrice,
-								method_sig='transferFrom(address,address,uint256)',
-								from_addr2=from_addr)
-
 	def create_data(self,to_addr,amt,method_sig='transfer(address,uint256)',from_addr=None):
 		from_arg = from_addr.rjust(64,'0') if from_addr else ''
 		to_arg = to_addr.rjust(64,'0')
@@ -118,6 +119,8 @@ class Token(MMGenObject): # ERC20
 			pmsg(tx.to_dict())
 		return hex_tx,coin_txid
 
+# The following are used for token deployment only:
+
 	def txsend(self,hex_tx):
 		return g.rpch.eth_sendRawTransaction('0x'+hex_tx.decode()).replace('0x','',1).encode()
 
@@ -132,3 +135,9 @@ class Token(MMGenObject): # ERC20
 								from_addr2=from_addr2)
 		(hex_tx,coin_txid) = self.txsign(tx_in,key,from_addr)
 		return self.txsend(hex_tx)
+
+	def transfer_from(self,from_addr,to_addr,amt,key,start_gas,gasPrice):
+		raise NotImplementedError('method not implemented')
+		return self.transfer(   from_addr,to_addr,amt,key,start_gas,gasPrice,
+								method_sig='transferFrom(address,address,uint256)',
+								from_addr2=from_addr)

+ 28 - 34
mmgen/altcoins/eth/tx.py

@@ -151,7 +151,8 @@ class EthereumMMGenTX(MMGenTX):
 		o_num = len(self.outputs)
 		assert o_num in o_ok,'Transaction has invalid number of outputs!'.format(o_num)
 		self.make_txobj()
-		self.hex = json.dumps(dict([(k,str(v))for k,v in list(self.txobj.items())]))
+		ol = [(k,v.decode() if issubclass(type(v),bytes) else str(v)) for k,v in self.txobj.items()]
+		self.hex = json.dumps(dict(ol)).encode()
 		self.update_txid()
 
 	def del_output(self,idx): pass
@@ -278,7 +279,6 @@ class EthereumMMGenTX(MMGenTX):
 		return m.format(ETHAmt(chg).hl(),g.coin)
 
 	def do_sign(self,d,wif,tx_num_str):
-
 		d_in = {'to':       unhexlify(d['to']),
 				'startgas': d['startGas'].toWei(),
 				'gasprice': d['gasPrice'].toWei(),
@@ -286,24 +286,15 @@ class EthereumMMGenTX(MMGenTX):
 				'nonce':    d['nonce'],
 				'data':     unhexlify(d['data'])}
 
-		msg_r('Signing transaction{}...'.format(tx_num_str))
-
-		try:
-			from ethereum.transactions import Transaction
-			etx = Transaction(**d_in)
-			etx.sign(wif,d['chainId'])
-			import rlp
-			self.hex = hexlify(rlp.encode(etx))
-			self.coin_txid = CoinTxID(hexlify(etx.hash))
-			msg('OK')
-			if d['data']:
-				self.token_addr = TokenAddr(hexlify(etx.creates))
-		except Exception as e:
-			m = "{!r}: transaction signing failed!"
-			msg(m.format(e.args[0]))
-			return False
-
-		return self.check_sigs()
+		from ethereum.transactions import Transaction
+		etx = Transaction(**d_in)
+		etx.sign(wif,d['chainId'])
+		import rlp
+		self.hex = hexlify(rlp.encode(etx))
+		self.coin_txid = CoinTxID(hexlify(etx.hash))
+		if d['data']:
+			self.token_addr = TokenAddr(hexlify(etx.creates).decode())
+		assert self.check_sigs(),'Signature check failed'
 
 	def sign(self,tx_num_str,keys): # return True or False; don't exit or raise exception
 
@@ -314,10 +305,21 @@ class EthereumMMGenTX(MMGenTX):
 		if not self.check_correct_chain(on_fail='return'):
 			return False
 
-		return self.do_sign(self.txobj,keys[0].sec.wif,tx_num_str)
+		msg_r('Signing transaction{}...'.format(tx_num_str))
+
+		try:
+			self.do_sign(self.txobj,keys[0].sec.wif,tx_num_str)
+			msg('OK')
+			return True
+		except Exception as e:
+			if os.getenv('MMGEN_TRACEBACK'):
+				import traceback
+				ymsg('\n'+''.join(traceback.format_exception(*sys.exc_info())))
+			m = "{!r}: transaction signing failed!"
+			msg(m.format(e.args[0]))
+			return False
 
 	def is_in_mempool(self):
-#		pmsg(g.rpch.parity_pendingTransactions())
 		return '0x'+self.coin_txid.decode() in [x['hash'] for x in g.rpch.parity_pendingTransactions()]
 
 	def is_in_wallet(self):
@@ -454,18 +456,10 @@ class EthereumTokenMMGenTX(EthereumMMGenTX):
 
 	def do_sign(self,d,wif,tx_num_str):
 		d = self.txobj
-		msg_r('Signing transaction{}...'.format(tx_num_str))
-		try:
-			t = Token(d['token_addr'],decimals=d['decimals'])
-			tx_in = t.txcreate(d['from'],d['to'],d['amt'],self.start_gas,d['gasPrice'],nonce=d['nonce'])
-			(self.hex,self.coin_txid) = t.txsign(tx_in,wif,d['from'],chain_id=d['chainId'])
-			msg('OK')
-		except Exception as e:
-			m = "{!r}: transaction signing failed!"
-			msg(m.format(e.args[0]))
-			return False
-
-		return self.check_sigs()
+		t = Token(d['token_addr'],decimals=d['decimals'])
+		tx_in = t.txcreate(d['from'],d['to'],d['amt'],self.start_gas,d['gasPrice'],nonce=d['nonce'])
+		(self.hex,self.coin_txid) = t.txsign(tx_in,wif,d['from'],chain_id=d['chainId'])
+		assert self.check_sigs(),'Signature check failed'
 
 class EthereumMMGenBumpTX(EthereumMMGenTX,MMGenBumpTX):