Minor changes and fixes

- eth/tw.py,main_txsign.py,protocol.py,rpc.py,tx.py: changes
- test.py,addr.py: fixes
This commit is contained in:
The MMGen Project 2018-05-30 15:33:14 +00:00
commit 26210569f8
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
7 changed files with 45 additions and 34 deletions

View file

@ -572,7 +572,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
else:
bc,mt = g.proto.base_coin,self.al_id.mmtype
l_coin = [] if bc == 'BTC' else [g.coin] if bc == 'ETH' else [bc]
l_type = [] if mt in ('L','E') else [mt.name.upper()]
l_type = [] if mt == 'E' or (mt == 'L' and not g.proto.is_testnet()) else [mt.name.upper()]
l_tn = [] if not g.proto.is_testnet() else ['TESTNET']
lbl_p2 = ':'.join(l_coin+l_type+l_tn)
lbl = self.al_id.sid + ('',' ')[bool(lbl_p2)] + lbl_p2

View file

@ -29,7 +29,7 @@ from mmgen.addr import AddrData
# No file locking - 2 processes accessing the wallet at the same time will corrupt it
class EthereumTrackingWallet(TrackingWallet):
data_dir = os.path.join(g.altcoin_data_dir,'eth')
data_dir = os.path.join(g.altcoin_data_dir,'eth',g.proto.data_subdir)
tw_file = os.path.join(data_dir,'tracking-wallet.json')
def __init__(self):

View file

@ -60,13 +60,14 @@ opts_data = lambda: {
-v, --verbose Produce more verbose output
-V, --vsize-adj= f Adjust transaction's estimated vsize by factor 'f'
-y, --yes Answer 'yes' to prompts, suppress non-essential output
""".format(
""",
'options_fmt_args': lambda: dict(
g=g,pnm=g.proj_name,pnl=g.proj_name.lower(),dn=g.proto.daemon_name,
kgs=' '.join(['{}:{}'.format(n,k) for n,k in enumerate(g.key_generators,1)]),
kg=g.key_generator,
cu=g.coin
),
'notes': '\n' + help_notes('txsign')
'notes': lambda: '\n' + help_notes('txsign')
}
infiles = opts.init(opts_data,add_opts=['b16'])

View file

@ -298,11 +298,13 @@ class EthereumProtocol(DummyWIF,BitcoinProtocolAddrgen):
base_coin = 'ETH'
pubkey_type = 'std' # required by DummyWIF
data_subdir = ''
daemon_name = 'parity'
rpc_port = 8545
mmcaps = ('key','addr','rpc')
coin_amt = ETHAmt
@classmethod
def verify_addr(cls,addr,hex_width,return_dict=False):
from mmgen.util import is_hex_str_lc
@ -317,7 +319,8 @@ class EthereumProtocol(DummyWIF,BitcoinProtocolAddrgen):
assert not p2sh,'Ethereum has no P2SH address format'
return pubkey_hash
class EthereumTestnetProtocol(EthereumProtocol): pass
class EthereumTestnetProtocol(EthereumProtocol):
data_subdir = 'testnet'
class EthereumClassicProtocol(EthereumProtocol):
name = 'ethereum_classic'
mmcaps = ('key','addr')

View file

@ -235,6 +235,7 @@ class EthereumRPCConnection(CoinDaemonRPCConnection):
'parity_minGasPrice',
'parity_mode',
'parity_netPeers',
'parity_nextNonce',
'parity_nodeKind',
'parity_nodeName',
'parity_pendingTransactions',

View file

@ -479,7 +479,7 @@ class MMGenTX(MMGenObject):
def fee_abs2rel(self,abs_fee):
return int(abs_fee/g.proto.coin_amt.min_coin_unit/self.estimate_size())
def get_rel_fee_from_network(self): # rel_fee is BTC/kB
def get_rel_fee_from_network(self): # rel_fee is in BTC/kB
try:
ret = g.rpch.estimatesmartfee(opt.tx_confs,on_fail='raise')
rel_fee = ret['feerate'] if 'feerate' in ret else -2
@ -496,24 +496,8 @@ class MMGenTX(MMGenObject):
return g.proto.coin_amt(int(amt)*tx_size*getattr(g.proto.coin_amt,units[unit])) \
if tx_size else None
# given tx size and absolute fee or fee spec, return absolute fee
# relative fee is N+<first letter of unit name>
def process_fee_spec(self,tx_fee,tx_size,on_fail='throw'):
import re
units = dict((u[0],u) for u in g.proto.coin_amt.units)
pat = r'([1-9][0-9]*)({})'.format('|'.join(units.keys()))
if g.proto.coin_amt(tx_fee,on_fail='silent'):
return g.proto.coin_amt(tx_fee)
elif re.match(pat,tx_fee):
return self.convert_fee_spec(tx_size,units,*re.match(pat,tx_fee).groups())
else:
if on_fail == 'return':
return False
elif on_fail == 'throw':
assert False, "'{}': invalid tx-fee argument".format(tx_fee)
# given network fee estimate in BTC/kB, return absolute fee using estimated tx size
def calculate_fee(self,rel_fee,fe_type=None):
def fee_est2abs(self,rel_fee,fe_type=None):
tx_size = self.estimate_size()
ret = g.proto.coin_amt(rel_fee) * opt.tx_fee_adj * tx_size / 1024
if opt.verbose:
@ -543,6 +527,23 @@ class MMGenTX(MMGenObject):
return abs_fee
# non-coin-specific fee routines
# given tx size and absolute fee or fee spec, return absolute fee
# relative fee is N+<first letter of unit name>
def process_fee_spec(self,tx_fee,tx_size,on_fail='throw'):
import re
units = dict((u[0],u) for u in g.proto.coin_amt.units)
pat = r'([1-9][0-9]*)({})'.format('|'.join(units.keys()))
if g.proto.coin_amt(tx_fee,on_fail='silent'):
return g.proto.coin_amt(tx_fee)
elif re.match(pat,tx_fee):
return self.convert_fee_spec(tx_size,units,*re.match(pat,tx_fee).groups())
else:
if on_fail == 'return':
return False
elif on_fail == 'throw':
assert False, "'{}': invalid tx-fee argument".format(tx_fee)
def get_usr_fee_interactive(self,tx_fee=None,desc='Starting'):
abs_fee = None
while True:
@ -578,7 +579,7 @@ class MMGenTX(MMGenObject):
have_estimate_fail.append(True)
start_fee = None
else:
start_fee = self.calculate_fee(rel_fee,fe_type)
start_fee = self.fee_est2abs(rel_fee,fe_type)
return self.get_usr_fee_interactive(start_fee,desc=desc)
@ -852,6 +853,13 @@ class MMGenTX(MMGenObject):
msg(' {}{}'.format(t,('',' in mempool')[s]))
die(0,'')
def confirm_send(self):
m1 = ("Once this transaction is sent, there's no taking it back!",'')[bool(opt.quiet)]
m2 = 'broadcast this transaction to the {} network'.format(g.chain.upper())
m3 = ('YES, I REALLY WANT TO DO THIS','YES')[bool(opt.quiet or opt.yes)]
confirm_or_exit(m1,m2,m3)
msg('Sending transaction')
def send(self,prompt_user=True,exit_on_fail=False):
if not self.marked_signed():
@ -869,17 +877,12 @@ class MMGenTX(MMGenObject):
if self.get_fee_from_tx() > g.proto.max_tx_fee:
die(2,'Transaction fee ({}) greater than {} max_tx_fee ({} {})!'.format(
self.get_fee_from_tx(),g.proto.name.capitalize(),g.proto.max_tx_fee,g.coin.upper()))
self.get_fee_from_tx(),g.proto.name.capitalize(),g.proto.max_tx_fee,g.coin))
self.get_status()
if prompt_user:
m1 = ("Once this transaction is sent, there's no taking it back!",'')[bool(opt.quiet)]
m2 = 'broadcast this transaction to the {} network'.format(g.chain.upper())
m3 = ('YES, I REALLY WANT TO DO THIS','YES')[bool(opt.quiet or opt.yes)]
confirm_or_exit(m1,m2,m3)
if prompt_user: self.confirm_send()
msg('Sending transaction')
ret = None if bogus_send else g.rpch.sendrawtransaction(self.hex,on_fail='return')
from mmgen.rpc import rpc_error,rpc_errmsg
@ -1162,6 +1165,7 @@ class MMGenTX(MMGenObject):
except Exception as e:
die(2,'Invalid {} in transaction file: {}'.format(desc,e[0]))
# test doesn't work for Ethereum
if not self.chain and not self.inputs[0].addr.is_for_chain('testnet'):
self.chain = 'mainnet'

View file

@ -2525,8 +2525,9 @@ class MMGenTestSuite(object):
for mmtype in g.proto.mmtypes:
desc = MMGenAddrType.mmtypes[mmtype]['name']
fn = os.path.join(self.regtest_user_dir(user),
u'{}{}{}[{}]{x}.addrs'.format(sid,altcoin_pfx,id_strs[desc],addr_range,
x=u'' if g.debug_utf8 else ''))
u'{}{}{}[{}]{x}.testnet.addrs'.format(
sid,altcoin_pfx,id_strs[desc],addr_range,
x=u'' if g.debug_utf8 else ''))
if mmtype == g.proto.mmtypes[0] and user == 'bob':
psave = g.proto
g.proto = CoinProtocol(g.coin,True)
@ -2634,7 +2635,8 @@ class MMGenTestSuite(object):
def get_addr_from_regtest_addrlist(self,user,sid,mmtype,idx,addr_range='1-5'):
id_str = { 'L':'', 'S':'-S', 'C':'-C' }[mmtype]
ext = u'{}{}{}[{}]{x}.addrs'.format(sid,altcoin_pfx,id_str,addr_range,x=u'' if g.debug_utf8 else '')
ext = u'{}{}{}[{}]{x}.testnet.addrs'.format(
sid,altcoin_pfx,id_str,addr_range,x=u'' if g.debug_utf8 else '')
fn = get_file_with_ext(ext,self.regtest_user_dir(user),no_dot=True)
silence()
psave = g.proto