Add g.proto.witness_ver_num, minor fixes and changes

This commit is contained in:
The MMGen Project 2018-03-05 06:29:20 +00:00
commit e9385725cf
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
12 changed files with 121 additions and 87 deletions

View file

@ -27,9 +27,8 @@ from mmgen.obj import *
pnm = g.proj_name
def sc_dmsg(desc,data):
if os.getenv('MMGEN_DEBUG_ADDRLIST'):
Msg('sc_debug_{}: {}'.format(desc,data))
def dmsg_sc(desc,data):
if g.debug_addrlist: Msg('sc_debug_{}: {}'.format(desc,data))
class AddrGenerator(MMGenObject):
def __new__(cls,addr_type):
@ -45,8 +44,7 @@ class AddrGenerator(MMGenObject):
'segwit': AddrGeneratorSegwit,
'ethereum': AddrGeneratorEthereum,
'zcash_z': AddrGeneratorZcashZ,
'monero': AddrGeneratorMonero
}
'monero': AddrGeneratorMonero}
assert gen_method in gen_methods
me = super(cls,cls).__new__(gen_methods[gen_method])
me.desc = gen_methods
@ -59,7 +57,7 @@ class AddrGeneratorP2PKH(AddrGenerator):
return CoinAddr(g.proto.pubhash2addr(hash160(pubhex),p2sh=False))
def to_segwit_redeem_script(self,pubhex):
raise NotImplementedError,'Coin/type pair incompatible with Segwit'
raise NotImplementedError,'Segwit redeem script not supported by this address type'
class AddrGeneratorSegwit(AddrGenerator):
def to_addr(self,pubhex):
@ -77,7 +75,7 @@ class AddrGeneratorEthereum(AddrGenerator):
return CoinAddr(sha3.keccak_256(pubhex[2:].decode('hex')).digest()[12:].encode('hex'))
def to_segwit_redeem_script(self,pubhex):
raise NotImplementedError,'Coin/type pair incompatible with Segwit'
raise NotImplementedError,'Segwit redeem script not supported by this address type'
# github.com/FiloSottile/zcash-mini/zcash/address.go
class AddrGeneratorZcashZ(AddrGenerator):
@ -197,7 +195,7 @@ class KeyGenerator(MMGenObject):
def test_for_secp256k1(self,silent=False):
try:
from mmgen.secp256k1 import priv2pub
assert priv2pub(os.urandom(32),1)
assert priv2pub(('deadbeef'*8).decode('hex'),1)
return True
except:
return False
@ -303,7 +301,7 @@ class AddrListIDStr(unicode,Hilite):
bc = (g.proto.base_coin,g.coin)[g.proto.base_coin=='ETH']
mt = addrlist.al_id.mmtype
ret = '{}{}{}[{}]'.format(addrlist.al_id.sid,('-'+bc,'')[bc=='BTC'],('-'+mt,'')[mt in ('L','E')],s)
sc_dmsg('id_str',ret[8:].split('[')[0])
dmsg_sc('id_str',ret[8:].split('[')[0])
return unicode.__new__(cls,ret)
@ -397,7 +395,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
seed = seed.get_data()
seed = self.scramble_seed(seed)
sc_dmsg('seed',seed[:8].encode('hex'))
dmsg_sc('seed',seed[:8].encode('hex'))
compressed = self.al_id.mmtype.compressed
pubkey_type = self.al_id.mmtype.pubkey_type
@ -441,7 +439,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
dmsg('Key {:>03}: {}'.format(pos,e.passwd))
out.append(e)
if g.debug: Msg('generate():\n', e.pformat())
if g.debug: Msg('generate():\n{}'.format(e.pformat()))
qmsg('\r%s: %s %s%s generated%s' % (
self.al_id.hl(),t_addrs,self.gen_desc,suf(t_addrs,self.gen_desc_pl),' '*15))
@ -452,13 +450,13 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
def scramble_seed(self,seed):
is_btcfork = g.proto.base_coin == 'BTC'
if is_btcfork and self.al_id.mmtype == 'L':
sc_dmsg('str','(none)')
dmsg_sc('str','(none)')
return seed
if g.proto.base_coin == 'ETH':
scramble_key = g.coin.lower()
else:
scramble_key = (g.coin.lower()+':','')[is_btcfork] + self.al_id.mmtype.name
sc_dmsg('str',scramble_key)
dmsg_sc('str',scramble_key)
from mmgen.crypto import scramble_seed
return scramble_seed(seed,scramble_key,self.scramble_hash_rounds)
@ -559,7 +557,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
lbl_p2 = ':'.join(l_coin+l_type)
lbl = self.al_id.sid + ('',' ')[bool(lbl_p2)] + lbl_p2
sc_dmsg('lbl',lbl[9:])
dmsg_sc('lbl',lbl[9:])
out.append(u'{} {{'.format(lbl))
fs = ' {:<%s} {:<34}{}' % len(str(self.data[-1].idx))

View file

@ -45,8 +45,8 @@ def sha256_rounds(s,n):
def scramble_seed(seed,scramble_key,hash_rounds):
import hmac
scr_seed = hmac.new(seed,scramble_key,sha256).digest()
fs = 'Seed: {}\nScramble key: {}\nScrambled seed: {}\nScrambled seed len: {}'
dmsg(fs.format(hexlify(seed),scramble_key,hexlify(scr_seed),len(scr_seed)))
fs = 'Seed: {}\nScramble key: {}\nScrambled seed: {}'
dmsg(fs.format(hexlify(seed),scramble_key,hexlify(scr_seed)))
return sha256_rounds(scr_seed,hash_rounds)
def encrypt_seed(seed,key):

View file

@ -66,6 +66,9 @@ class g(object):
coin = 'BTC'
debug = False
debug_opts = False
debug_rpc = False
debug_addrlist = False
quiet = False
no_license = False
hold_protect = True
@ -136,6 +139,9 @@ class g(object):
env_opts = (
'MMGEN_BOGUS_WALLET_DATA',
'MMGEN_DEBUG',
'MMGEN_DEBUG_OPTS',
'MMGEN_DEBUG_RPC',
'MMGEN_DEBUG_ADDRLIST',
'MMGEN_QUIET',
'MMGEN_DISABLE_COLOR',
'MMGEN_FORCE_256_COLOR',

View file

@ -36,9 +36,9 @@ Cryptocoin address/key operations (compressed public keys supported):
privhex2addr - generate coin address from private key in hex format
privhex2pubhex - generate a hex public key from a hex private key
pubhex2addr - convert a hex pubkey to an address
pubhex2redeem_script - convert a hex pubkey to a witness redeem script
wif2redeem_script - convert a WIF private key to a witness redeem script
wif2segwit_pair - generate both a Segwit redeem script and address from WIF
pubhex2redeem_script - convert a hex pubkey to a Segwit P2SH-P2WPKH redeem script
wif2redeem_script - convert a WIF private key to a Segwit P2SH-P2WPKH redeem script
wif2segwit_pair - generate both a Segwit P2SH-P2WPKH redeem script and address from WIF
pubkey2addr - convert coin public key to address
randpair - generate a random private key/address pair
randwif - generate a random private key in WIF format

View file

@ -383,8 +383,6 @@ class CoinAddr(str,Hilite,InitErrors,MMGenObject):
return Hilite.fmtc(s,**kwargs)
def is_for_chain(self,chain):
from mmgen.globalvars import g
vn = g.proto.get_protocol_by_chain(chain).addr_ver_num
def pfx_ok(pfx):
if type(pfx) == tuple:
@ -392,6 +390,10 @@ class CoinAddr(str,Hilite,InitErrors,MMGenObject):
elif self[:len(pfx)] == pfx: return True
return False
from mmgen.globalvars import g
proto = g.proto.get_protocol_by_chain(chain)
vn = proto.addr_ver_num
if self.addr_fmt == 'p2sh' and 'p2sh2' in vn:
return pfx_ok(vn['p2sh'][1]) or pfx_ok(vn['p2sh2'][1])
else:

View file

@ -224,7 +224,7 @@ def init(opts_f,add_opts=[],opt_filter=None):
uopts,args,short_opts,long_opts,skipped_opts,do_help = \
mmgen.share.Opts.parse_opts(sys.argv,opts_data,opt_filter=opt_filter,defer_help=True)
if g.debug: opt_preproc_debug(short_opts,long_opts,skipped_opts,uopts,args)
if g.debug_opts: opt_preproc_debug(short_opts,long_opts,skipped_opts,uopts,args)
# Save this for usage()
global usage_txt
@ -292,6 +292,7 @@ def init(opts_f,add_opts=[],opt_filter=None):
if g.bob or g.alice:
g.testnet = True
g.regtest = True
g.proto = CoinProtocol(g.coin,g.testnet)
g.data_dir = os.path.join(g.data_dir_root,'regtest',g.coin.lower(),('alice','bob')[g.bob])
check_or_create_dir(g.data_dir)
@ -309,7 +310,7 @@ def init(opts_f,add_opts=[],opt_filter=None):
ymsg("Warning: config file options have changed! See '{}' for details".format(g.cfg_file+'.sample'))
my_raw_input('Hit ENTER to continue: ')
if g.debug: opt_postproc_debug()
if g.debug_opts: opt_postproc_debug()
# We don't need this data anymore
del mmgen.share.Opts

View file

@ -83,10 +83,14 @@ class BitcoinProtocol(MMGenObject):
(478559,'00000000000000000019f112ec0a9982926f1258cdcc558dd7c3b7e5dc7fa148','bch',False),
(None,'','b2x',True)
]
caps = ('rbf','segwit')
mmcaps = ('key','addr','rpc','tx')
base_coin = 'BTC'
addr_width = 34
caps = ('rbf','segwit')
mmcaps = ('key','addr','rpc','tx')
base_coin = 'BTC'
addr_width = 34
# From BIP173: witness version 'n' is stored as 'OP_n'. OP_0 is encoded as 0x00,
# but OP_1 through OP_16 are encoded as 0x51 though 0x60 (81 to 96 in decimal).
witness_vernum_hex = '00'
witness_vernum = int(witness_vernum_hex,16)
@staticmethod
def get_protocol_by_chain(chain):
@ -147,7 +151,7 @@ class BitcoinProtocol(MMGenObject):
else:
if g.debug: Msg('Invalid checksum in address')
break
if g.debug: Msg("Invalid address '{}'".format(addr))
return False
@classmethod
@ -163,7 +167,7 @@ class BitcoinProtocol(MMGenObject):
# https://bitcoincore.org/en/segwit_wallet_dev/
# The P2SH redeemScript is always 22 bytes. It starts with a OP_0, followed
# by a canonical push of the keyhash (i.e. 0x0014{20-byte keyhash})
return '0014' + hash160(pubhex)
return cls.witness_vernum_hex + '14' + hash160(pubhex)
@classmethod
def pubhex2segwitaddr(cls,pubhex):

View file

@ -25,14 +25,17 @@ import httplib,base64,json
from mmgen.common import *
from decimal import Decimal
def dmsg_rpc(s):
if g.debug_rpc: msg(s)
class RPCFailure(Exception): pass
class CoinDaemonRPCConnection(object):
def __init__(self,host=None,port=None,user=None,passwd=None,auth_cookie=None):
dmsg('=== CoinDaemonRPCConnection.__init__() debug ===')
dmsg(' host [{}] port [{}] user [{}] passwd [{}] auth_cookie [{}]\n'.format(
dmsg_rpc('=== CoinDaemonRPCConnection.__init__() debug ===')
dmsg_rpc(' host [{}] port [{}] user [{}] passwd [{}] auth_cookie [{}]\n'.format(
host,port,user,passwd,auth_cookie))
import socket
@ -98,8 +101,8 @@ class CoinDaemonRPCConnection(object):
elif cf['on_fail'] == 'die':
die(args[1],yellow(s))
dmsg('=== request() debug ===')
dmsg(' RPC POST data ==> %s\n' % p)
dmsg_rpc('=== request() debug ===')
dmsg_rpc(' RPC POST data ==> %s\n' % p)
caller = self
class MyJSONEncoder(json.JSONEncoder):
def default(self, obj):
@ -112,7 +115,7 @@ class CoinDaemonRPCConnection(object):
# dump = json.dumps(p,cls=MyJSONEncoder,ensure_ascii=False)
# print(dump)
dmsg(' RPC AUTHORIZATION data ==> raw: [{}]\n{}enc: [Basic {}]\n'.format(
dmsg_rpc(' RPC AUTHORIZATION data ==> raw: [{}]\n{}enc: [Basic {}]\n'.format(
self.auth_str,' '*31,base64.b64encode(self.auth_str)))
try:
hc.request('POST', '/', json.dumps(p,cls=MyJSONEncoder), {
@ -129,7 +132,7 @@ class CoinDaemonRPCConnection(object):
m = 'Unable to connect to {} at {}:{} (but port is bound?)'
return do_fail(None,2,m.format(g.proto.daemon_name,self.host,self.port))
dmsg(' RPC GETRESPONSE data ==> %s\n' % r.__dict__)
dmsg_rpc(' RPC GETRESPONSE data ==> %s\n' % r.__dict__)
if r.status != 200:
if cf['on_fail'] not in ('silent','raise'):
@ -145,7 +148,7 @@ class CoinDaemonRPCConnection(object):
r2 = r.read()
dmsg(' RPC REPLY data ==> %s\n' % r2)
dmsg_rpc(' RPC REPLY data ==> %s\n' % r2)
if not r2:
return do_fail(r,2,'Error: empty reply')

View file

@ -131,10 +131,12 @@ def bytes2coin_amt(hex_bytes):
return g.proto.coin_amt(bytes2int(hex_bytes) * g.proto.coin_amt.min_coin_unit)
def scriptPubKey2addr(s):
if len(s) == 50 and s[:6] == '76a914' and s[-4:] == '88ac': addr_hex,p2sh = s[6:-4],False
elif len(s) == 46 and s[:4] == 'a914' and s[-2:] == '87': addr_hex,p2sh = s[4:-2],True
else: raise NotImplementedError,'Unknown scriptPubKey'
return g.proto.pubhash2addr(addr_hex,p2sh)
if len(s) == 50 and s[:6] == '76a914' and s[-4:] == '88ac':
return g.proto.pubhash2addr(s[6:-4],p2sh=False)
elif len(s) == 46 and s[:4] == 'a914' and s[-2:] == '87':
return g.proto.pubhash2addr(s[4:-2],p2sh=True)
else:
raise NotImplementedError,'Unknown scriptPubKey ({})'.format(s)
from collections import OrderedDict
class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
@ -162,7 +164,7 @@ class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
return ret
d['version'] = bytes2int(hshift(tx,4))
has_witness = (False,True)[hexlify(tx[0])=='00']
has_witness = tx[0] == '\x00'
if has_witness:
u = hshift(tx,2,skip=True)[2:]
if u != '01':
@ -383,7 +385,7 @@ class MMGenTX(MMGenObject):
# serialization, divide the result by 4 and round up to the next integer.
# TODO: results differ slightly from actual transaction size
def estimate_vsize(self):
def estimate_size(self):
if not self.inputs or not self.outputs: return None
sig_size = 72 # sig in DER format
@ -439,8 +441,6 @@ class MMGenTX(MMGenObject):
# pmsg('estimate_size_old',self.estimate_size_old())
return ret
estimate_size = estimate_vsize
def get_fee(self):
return self.sum_inputs() - self.sum_outputs()
@ -609,8 +609,6 @@ class MMGenTX(MMGenObject):
msg_r('Signing transaction{}...'.format(tx_num_str))
wifs = [d.sec.wif for d in keys]
# keys.pmsg()
# pmsg(wifs)
ret = g.rpch.signrawtransaction(self.hex,sig_data,wifs,g.proto.sighash_type,on_fail='return')
from mmgen.rpc import rpc_error,rpc_errmsg

View file

@ -70,10 +70,10 @@ def pformat(d):
return pprint.PrettyPrinter(indent=4).pformat(d)
def pmsg(*args):
if not args: return
Msg(pformat(args if len(args) > 1 else args[0]))
msg(pformat(args if len(args) > 1 else args[0]))
def pdie(*args):
if not args: sys.exit(1)
Die(1,(pformat(args if len(args) > 1 else args[0])))
die(1,(pformat(args if len(args) > 1 else args[0])))
def set_for_type(val,refval,desc,invert_bool=False,src=None):
src_str = (''," in '{}'".format(src))[bool(src)]

View file

@ -235,8 +235,11 @@ class MMGenPexpect(object):
self.expect("Overwrite? Type uppercase 'YES' to confirm: ",'\n')
self.expect('Exiting at user request')
def tx_view(self):
my_expect(self.p,r'View .*?transaction.*? \(y\)es, \(N\)o, pager \(v\)iew.*?: ','\n',regex=True)
def tx_view(self,view=None):
repl = { 'terse':'t', 'full':'v' }[view] if view else 'n'
my_expect(self.p,r'View .*?transaction.*? \(y\)es, \(N\)o, pager \(v\)iew.*?: ',repl,regex=True)
if repl in ('t','v'):
my_expect(self.p,r'any key to continue: ','\n')
def expect_getend(self,s,regex=False):
ret = self.expect(s,regex=regex,nonl=True)

View file

@ -177,8 +177,14 @@ if opt.segwit and 'S' not in g.proto.mmtypes:
def randbool():
return hexlify(os.urandom(1))[1] in '12345678'
def get_segwit_val():
def get_segwit_bool():
return randbool() if opt.segwit_random else True if opt.segwit else False
def disable_debug():
ds = os.getenv('MMGEN_DEBUG')
if ds is not None: os.environ['MMGEN_DEBUG'] = ''
return ds
def restore_debug(ds):
if ds is not None: os.environ['MMGEN_DEBUG'] = ds
cfgs = {
'15': {
@ -194,7 +200,7 @@ cfgs = {
'mmseed': 'export_seed_dfl_wallet',
'del_dw_run': 'delete_dfl_wallet',
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'16': {
'tmpdir': os.path.join('test','tmp16'),
@ -203,7 +209,7 @@ cfgs = {
'dep_generators': {
pwfile: 'passchg_dfl_wallet',
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'17': { 'tmpdir': os.path.join('test','tmp17') },
'18': { 'tmpdir': os.path.join('test','tmp18') },
@ -229,7 +235,7 @@ cfgs = {
incog_id_fn: 'export_incog_hidden',
'akeys.mmenc': 'keyaddrgen'
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'2': {
'tmpdir': os.path.join('test','tmp2'),
@ -243,7 +249,7 @@ cfgs = {
'sigtx': 'txsign2',
'mmwords': 'export_mnemonic2',
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'3': {
'tmpdir': os.path.join('test','tmp3'),
@ -255,7 +261,7 @@ cfgs = {
'rawtx': 'txcreate3',
'sigtx': 'txsign3'
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'4': {
'tmpdir': os.path.join('test','tmp4'),
@ -272,7 +278,7 @@ cfgs = {
},
'bw_filename': 'brainwallet.mmbrain',
'bw_params': '192,1',
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'14': {
'kapasswd': 'Maxwell',
@ -285,7 +291,7 @@ cfgs = {
'addrs': 'addrgen14',
'akeys.mmenc': 'keyaddrgen14',
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'5': {
'tmpdir': os.path.join('test','tmp5'),
@ -295,7 +301,7 @@ cfgs = {
'mmdat': 'passchg',
pwfile: 'passchg',
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'6': {
'name': 'reference wallet check (128-bit)',
@ -347,7 +353,7 @@ cfgs = {
'addrs': 'refaddrgen1',
'akeys.mmenc': 'refkeyaddrgen1'
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'7': {
'name': 'reference wallet check (192-bit)',
@ -399,7 +405,7 @@ cfgs = {
'addrs': 'refaddrgen2',
'akeys.mmenc': 'refkeyaddrgen2'
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'8': {
'name': 'reference wallet check (256-bit)',
@ -488,7 +494,7 @@ cfgs = {
'addrs': 'refaddrgen3',
'akeys.mmenc': 'refkeyaddrgen3'
},
'segwit': get_segwit_val()
'segwit': get_segwit_bool()
},
'9': {
'tmpdir': os.path.join('test','tmp9'),
@ -1013,7 +1019,10 @@ class MMGenExpect(MMGenPexpect):
def create_fake_unspent_entry(coinaddr,al_id=None,idx=None,lbl=None,non_mmgen=False,segwit=False):
if 'S' not in g.proto.mmtypes: segwit = False
if lbl: lbl = ' ' + lbl
spk1,spk2 = (('76a914','88ac'),('a914','87'))[segwit and coinaddr.addr_fmt=='p2sh']
spk_beg,spk_end = (
('76a914','88ac'),
('a914','87'),
)[segwit and coinaddr.addr_fmt=='p2sh']
amt1,amt2 = {'btc':(10,40),'bch':(10,40),'ltc':(1000,4000)}[coin_sel]
return {
'account': '{}:{}'.format(g.proto.base_coin.lower(),coinaddr) if non_mmgen \
@ -1023,7 +1032,7 @@ def create_fake_unspent_entry(coinaddr,al_id=None,idx=None,lbl=None,non_mmgen=Fa
'amount': g.proto.coin_amt('%s.%s' % (amt1+(getrandnum(4) % amt2), getrandnum(4) % 100000000)),
'address': coinaddr,
'spendable': False,
'scriptPubKey': '{}{}{}'.format(spk1,coinaddr.hex,spk2),
'scriptPubKey': '{}{}{}'.format(spk_beg,coinaddr.hex,spk_end),
'confirmations': getrandnum(4) % 50000
}
@ -1067,10 +1076,10 @@ def create_fake_unspent_data(adata,tx_data,non_mmgen_input=''):
if non_mmgen_input:
privkey = PrivKey(os.urandom(32),compressed=True,pubkey_type='std')
coinaddr = AddrGenerator('p2pkh').to_addr(KeyGenerator('std').to_pubhex(privkey))
rand_coinaddr = AddrGenerator('p2pkh').to_addr(KeyGenerator('std').to_pubhex(privkey))
of = os.path.join(cfgs[non_mmgen_input]['tmpdir'],non_mmgen_fn)
write_data_to_file(of,privkey.wif+'\n','compressed {} key'.format(g.proto.name),silent=True)
out.append(create_fake_unspent_entry(coinaddr,non_mmgen=True,segwit=False))
out.append(create_fake_unspent_entry(rand_coinaddr,non_mmgen=True,segwit=False))
# msg('\n'.join([repr(o) for o in out])); sys.exit(0)
return out
@ -1108,7 +1117,7 @@ def create_tx_data(sources):
def make_txcreate_cmdline(tx_data):
privkey = PrivKey(os.urandom(32),compressed=True,pubkey_type='std')
t = ('p2pkh','segwit')['S' in g.proto.mmtypes]
coinaddr = AddrGenerator(t).to_addr(KeyGenerator('std').to_pubhex(privkey))
rand_coinaddr = AddrGenerator(t).to_addr(KeyGenerator('std').to_pubhex(privkey))
# total of two outputs must be < 10 BTC (<1000 LTC)
mods = {'btc':(6,4),'bch':(6,4),'ltc':(600,400)}[coin_sel]
@ -1127,7 +1136,7 @@ def make_txcreate_cmdline(tx_data):
# + one change address and one BTC address
if num is tx_data.keys()[-1]:
cmd_args += ['{}:{}'.format(s['al_id'],s['addr_idxs'][1])]
cmd_args += ['{},{}'.format(coinaddr,cfgs[num]['amts'][1])]
cmd_args += ['{},{}'.format(rand_coinaddr,cfgs[num]['amts'][1])]
return cmd_args + [tx_data[num]['addrfile'] for num in tx_data]
@ -1441,7 +1450,8 @@ class MMGenTestSuite(object):
ok()
def addrgen(self,name,wf,pf=None,check_ref=False,ftype='addr',id_str=None,extra_args=[],mmtype=None):
if cfg['segwit'] and ftype[:4] != 'pass' and not mmtype: mmtype = 'segwit'
if ftype[:4] != 'pass' and not mmtype:
if cfg['segwit']: mmtype = 'segwit'
cmd_pfx = (ftype,'pass')[ftype[:4]=='pass']
t = MMGenExpect(name,'mmgen-{}gen'.format(cmd_pfx),
['-d',cfg['tmpdir']] +
@ -1455,16 +1465,20 @@ class MMGenTestSuite(object):
t.expect('Passphrase is OK')
desc = ('address','password')[ftype[:4]=='pass']
chk = t.expect_getend(r'Checksum for {} data .*?: '.format(desc),regex=True)
if ftype[:4] == 'pass':
t.expect('Encrypt password list? (y/N): ','\n')
t.written_to_file('Password list',oo=True)
else:
t.written_to_file('Addresses',oo=True)
if check_ref:
k = 'passfile32_chk' if ftype == 'pass32' \
else 'passfilehex_chk' if ftype == 'passhex' \
else 'passfile_chk' if ftype == 'pass' \
else '{}file{}_chk'.format(ftype,'_'+mmtype if mmtype else '')
chk_ref = cfg[k] if ftype[:4] == 'pass' else cfg[k][fork][g.testnet]
refcheck('address data checksum',chk,chk_ref)
return
t.written_to_file('Addresses',oo=True)
t.ok()
refcheck('{}list data checksum'.format(ftype),chk,chk_ref)
else:
t.ok()
def addrgen_dfl_wallet(self,name,pf=None,check_ref=False):
return self.addrgen(name,wf=None,pf=pf,check_ref=check_ref)
@ -1486,7 +1500,7 @@ class MMGenTestSuite(object):
vmsg('This is a simulation, so no addresses were actually imported into the tracking\nwallet')
t.ok(exit_val=1)
def txcreate_common(self,name,sources=['1'],non_mmgen_input='',do_label=False,txdo_args=[],add_args=[]):
def txcreate_common(self,name,sources=['1'],non_mmgen_input='',do_label=False,txdo_args=[],add_args=[],view=None):
if opt.verbose or opt.exact_output:
sys.stderr.write(green('Generating fake tracking wallet info\n'))
@ -1538,7 +1552,7 @@ class MMGenTestSuite(object):
t.expect('Comment: ',ref_tx_label.encode('utf8')+'\n')
else:
t.expect('Add a comment to transaction? (y/N): ','\n')
t.tx_view()
t.tx_view(view=view)
if txdo_args: return t
t.expect('Save transaction? (y/N): ','y')
t.written_to_file('Transaction')
@ -1619,7 +1633,7 @@ class MMGenTestSuite(object):
t = MMGenExpect(name,'mmgen-txsend', extra_opts + ['-d',cfg['tmpdir'],sigfile])
if really_send: os.environ['MMGEN_BOGUS_SEND'] = '1'
t.license()
t.tx_view()
t.tx_view(view='terse')
t.expect('Add a comment to transaction? (y/N): ','\n')
t.expect('Are you sure you want to broadcast this')
m = 'YES, I REALLY WANT TO DO THIS'
@ -1735,7 +1749,8 @@ class MMGenTestSuite(object):
args=['-H','%s,%s'%(rf,hincog_offset),'-l',str(hincog_seedlen)])
def keyaddrgen(self,name,wf,pf=None,check_ref=False,mmtype=None):
if cfg['segwit'] and not mmtype: mmtype = 'segwit'
if cfg['segwit'] and not mmtype:
mmtype = 'segwit'
args = ['-d',cfg['tmpdir'],usr_rand_arg,wf,cfg['addr_idx_list']]
t = MMGenExpect(name,'mmgen-keygen',
([],['--type='+str(mmtype)])[bool(mmtype)] + args,extra_desc=('','(segwit)')[mmtype=='segwit'])
@ -1866,7 +1881,7 @@ class MMGenTestSuite(object):
t.hash_preset('key-address data','1')
t.passphrase('key-address data',cfgs['14']['kapasswd'])
t.expect('Check key-to-address validity? (y/N): ','y')
t.tx_view()
t.tx_view(view='terse')
for cnum,desc in (('1','incognito data'),('3','MMGen wallet')):
t.passphrase(('%s' % desc),cfgs[cnum]['wpasswd'])
@ -2134,8 +2149,7 @@ class MMGenTestSuite(object):
def ref_segwitaddrfile_chk(self,name):
if not 'S' in g.proto.mmtypes:
msg_r('Skipping {} (not supported)'.format(name))
ok()
msg_r('Skipping {} (not supported)'.format(name)); ok()
else:
self.ref_addrfile_chk(name,ftype='segwitaddr')
@ -2294,7 +2308,7 @@ class MMGenTestSuite(object):
def regtest_user_bal(self,name,user,bal):
t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','showempty=1'])
total = t.expect_getend('TOTAL: ')
cmp_or_die(total,'{} {}'.format(bal,g.coin))
cmp_or_die('{} {}'.format(bal,g.coin),total)
def regtest_alice_bal1(self,name):
return self.regtest_user_bal(name,'alice',rtFundAmt)
@ -2318,11 +2332,11 @@ class MMGenTestSuite(object):
t = MMGenExpect(name,'mmgen-regtest',['get_balances'])
t.expect('Switching')
ret = t.expect_getend("Bob's balance:").strip()
cmp_or_die(ret,rtBals[4],skip_ok=True)
cmp_or_die(rtBals[4],ret,skip_ok=True)
ret = t.expect_getend("Alice's balance:").strip()
cmp_or_die(ret,rtBals[5],skip_ok=True)
cmp_or_die(rtBals[5],ret,skip_ok=True)
ret = t.expect_getend("Total balance:").strip()
cmp_or_die(ret,rtBals[6],skip_ok=True)
cmp_or_die(rtBals[6],ret,skip_ok=True)
t.ok()
def regtest_user_txdo( self,name,user,fee,
@ -2437,9 +2451,11 @@ class MMGenTestSuite(object):
t.ok()
def regtest_get_mempool(self,name):
t = MMGenExpect(name,'mmgen-regtest',['show_mempool'])
ds = disable_debug()
ret = MMGenExpect(name,'mmgen-regtest',['show_mempool']).read()
restore_debug(ds)
from ast import literal_eval
return literal_eval(t.read())
return literal_eval(ret)
def regtest_get_mempool1(self,name):
mp = self.regtest_get_mempool(name)
@ -2461,11 +2477,14 @@ class MMGenTestSuite(object):
@staticmethod
def gen_pairs(n):
return [subprocess.check_output(
ds = disable_debug()
ret = [subprocess.check_output(
['python',os.path.join('cmds','mmgen-tool'),'--testnet=1'] +
([],['--type=compressed'])[bool((i+1)%2)] +
['-r0','randpair']
).split() for i in range(n)]
restore_debug(ds)
return ret
def regtest_bob_pre_import(self,name):
pairs = self.gen_pairs(5)