py3port: Ethereum-related changes

This commit is contained in:
The MMGen Project 2018-10-31 18:13:27 +00:00
commit 9d694488d9
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
2 changed files with 49 additions and 46 deletions

View file

@ -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)

View file

@ -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):