whitespace: test/unit_tests_d
This commit is contained in:
parent
72fd9c1ca1
commit
6d90d180c1
28 changed files with 856 additions and 816 deletions
|
|
@ -4,7 +4,7 @@
|
|||
test.unit_tests_d.__init__: shared data for unit tests for the MMGen suite
|
||||
"""
|
||||
|
||||
import sys,os
|
||||
import sys, os
|
||||
|
||||
from mmgen.cfg import gv
|
||||
from ..include.common import cfg
|
||||
|
|
@ -17,7 +17,7 @@ class unit_tests_base:
|
|||
if not cfg.verbose:
|
||||
self.stdout_save = sys.stdout
|
||||
self.stderr_save = sys.stderr
|
||||
sys.stdout = sys.stderr = gv.stdout = gv.stderr = open(os.devnull,'w')
|
||||
sys.stdout = sys.stderr = gv.stdout = gv.stderr = open(os.devnull, 'w')
|
||||
|
||||
def _end_silence(self):
|
||||
if not cfg.verbose:
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ from mmgen.util import msg
|
|||
|
||||
from mmgen.seed import Seed
|
||||
from mmgen.addr import MMGenAddrType
|
||||
from mmgen.addrlist import AddrIdxList,AddrList,KeyList,KeyAddrList,ViewKeyAddrList
|
||||
from mmgen.addrlist import AddrIdxList, AddrList, KeyList, KeyAddrList, ViewKeyAddrList
|
||||
from mmgen.passwdlist import PasswordList
|
||||
from mmgen.protocol import init_proto
|
||||
from ..include.common import cfg,qmsg,vmsg
|
||||
from ..include.common import cfg, qmsg, vmsg
|
||||
|
||||
def do_test(
|
||||
list_type,
|
||||
|
|
@ -24,8 +24,8 @@ def do_test(
|
|||
addrtype = None):
|
||||
|
||||
qmsg(blue(f'Testing {list_type.__name__}'))
|
||||
proto = init_proto( cfg, coin or 'btc' )
|
||||
seed = Seed(cfg,seed_bin=bytes.fromhex('feedbead'*8))
|
||||
proto = init_proto(cfg, coin or 'btc')
|
||||
seed = Seed(cfg, seed_bin=bytes.fromhex('feedbead'*8))
|
||||
mmtype = MMGenAddrType(proto, addrtype or 'C')
|
||||
idxs = AddrIdxList(idx_spec or '1-3')
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ def do_test(
|
|||
if add_kwargs:
|
||||
kwargs.update(add_kwargs)
|
||||
|
||||
al = list_type( cfg, proto, **kwargs )
|
||||
al = list_type(cfg, proto, **kwargs)
|
||||
|
||||
al.file.format()
|
||||
|
||||
|
|
@ -65,10 +65,10 @@ def do_test(
|
|||
|
||||
class unit_tests:
|
||||
|
||||
altcoin_deps = ('keyaddr_xmr','viewkeyaddr')
|
||||
altcoin_deps = ('keyaddr_xmr', 'viewkeyaddr')
|
||||
|
||||
def idxlist(self,name,ut):
|
||||
for i,o in (
|
||||
def idxlist(self, name, ut):
|
||||
for i, o in (
|
||||
('99,88-102,1-3,4,9,818,444-445,816', '1-4,9,88-102,444-445,816,818'),
|
||||
('99,88-99,100,102,4-7,9,818,444-445,816,1', '1,4-7,9,88-100,102,444-445,816,818'),
|
||||
('8', '8'),
|
||||
|
|
@ -91,26 +91,26 @@ class unit_tests:
|
|||
|
||||
return True
|
||||
|
||||
def addr(self,name,ut):
|
||||
def addr(self, name, ut):
|
||||
return (
|
||||
do_test(AddrList,'BCE8 082C 0973 A525','1-3') and
|
||||
do_test(AddrList,'88FA B04B A380 C1CB','199999,99-101,77-78,7,3,2-9')
|
||||
do_test(AddrList, 'BCE8 082C 0973 A525', '1-3') and
|
||||
do_test(AddrList, '88FA B04B A380 C1CB', '199999,99-101,77-78,7,3,2-9')
|
||||
)
|
||||
|
||||
def key(self,name,ut):
|
||||
return do_test(KeyList,None)
|
||||
def key(self, name, ut):
|
||||
return do_test(KeyList, None)
|
||||
|
||||
def keyaddr(self,name,ut):
|
||||
return do_test(KeyAddrList,'4A36 AA65 8C2B 7C35')
|
||||
def keyaddr(self, name, ut):
|
||||
return do_test(KeyAddrList, '4A36 AA65 8C2B 7C35')
|
||||
|
||||
def keyaddr_xmr(self,name,ut):
|
||||
return do_test(KeyAddrList,'AAA2 BA69 17FC 9A88',coin='XMR',addrtype='M')
|
||||
def keyaddr_xmr(self, name, ut):
|
||||
return do_test(KeyAddrList, 'AAA2 BA69 17FC 9A88', coin='XMR', addrtype='M')
|
||||
|
||||
def viewkeyaddr(self,name,ut):
|
||||
return do_test(ViewKeyAddrList,'C122 2E58 DC28 D6AE',coin='XMR',addrtype='M')
|
||||
def viewkeyaddr(self, name, ut):
|
||||
return do_test(ViewKeyAddrList, 'C122 2E58 DC28 D6AE', coin='XMR', addrtype='M')
|
||||
|
||||
def passwd(self,name,ut):
|
||||
return do_test(PasswordList,'FF4A B716 4513 8F8F',pw_id_str='foo')
|
||||
def passwd(self, name, ut):
|
||||
return do_test(PasswordList, 'FF4A B716 4513 8F8F', pw_id_str='foo')
|
||||
|
||||
def passwd_bip39(self,name,ut):
|
||||
return do_test(PasswordList,'C3A8 B2B2 1AA1 FB40',pw_id_str='foo',add_kwargs={'pw_fmt':'bip39'})
|
||||
def passwd_bip39(self, name, ut):
|
||||
return do_test(PasswordList, 'C3A8 B2B2 1AA1 FB40', pw_id_str='foo', add_kwargs={'pw_fmt': 'bip39'})
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
test/unit_tests_d/ut_addrparse: address parsing tests for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.color import yellow,cyan
|
||||
from mmgen.util import msg,msg_r,pp_fmt
|
||||
from mmgen.color import yellow, cyan
|
||||
from mmgen.util import msg, msg_r, pp_fmt
|
||||
|
||||
from ..include.common import cfg,vmsg
|
||||
from ..include.common import cfg, vmsg
|
||||
|
||||
vectors = {
|
||||
'btc_mainnet': [
|
||||
|
|
@ -22,14 +22,14 @@ vectors = {
|
|||
],
|
||||
'xmr_mainnet': [
|
||||
{ # ut_xmrseed.vectors[0]:
|
||||
'std': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
|
||||
# https://github.com/monero-project/monero/tests/functional_tests/integrated_address.py
|
||||
'int': '4CMe2PUhs4J4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfSbLRB61BQVATzerHGj',
|
||||
'id': '0123456789abcdef'
|
||||
},{
|
||||
'std': '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK',
|
||||
'int': '4GYjoMG9Y2BBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCVSs1ZojwrDCGS5rUuo',
|
||||
'id': '1122334455667788'
|
||||
'std': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
|
||||
# https://github.com/monero-project/monero/tests/functional_tests/integrated_address.py
|
||||
'int': '4CMe2PUhs4J4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfSbLRB61BQVATzerHGj',
|
||||
'id': '0123456789abcdef'
|
||||
}, {
|
||||
'std': '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK',
|
||||
'int': '4GYjoMG9Y2BBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCVSs1ZojwrDCGS5rUuo',
|
||||
'id': '1122334455667788'
|
||||
}
|
||||
],
|
||||
'zec_mainnet': [
|
||||
|
|
@ -41,22 +41,22 @@ vectors = {
|
|||
],
|
||||
}
|
||||
|
||||
def test_network(proto,addrs):
|
||||
def test_network(proto, addrs):
|
||||
|
||||
def check_equal(a,b):
|
||||
def check_equal(a, b):
|
||||
assert a == b, f'{a.hex()} != {b.hex()}'
|
||||
|
||||
def check_bytes(addr):
|
||||
if addr.parsed.ver_bytes is not None:
|
||||
check_equal(
|
||||
addr.parsed.ver_bytes,
|
||||
proto.addr_fmt_to_ver_bytes.get(addr.addr_fmt) )
|
||||
proto.addr_fmt_to_ver_bytes.get(addr.addr_fmt))
|
||||
check_equal(
|
||||
addr.parsed.data + ((addr.parsed.payment_id or b'') if proto.coin == 'XMR' else b''),
|
||||
addr.bytes )
|
||||
addr.bytes)
|
||||
|
||||
def fmt_addr_data(addr):
|
||||
return pp_fmt({k:(v.hex() if isinstance(v,bytes) else v) for k,v in addr.parsed._asdict().items()})
|
||||
return pp_fmt({k:(v.hex() if isinstance(v, bytes) else v) for k, v in addr.parsed._asdict().items()})
|
||||
|
||||
def print_info(addr):
|
||||
vmsg('\n{}\n{}\n{}'.format(yellow(addr.addr_fmt), cyan(addr), fmt_addr_data(addr)))
|
||||
|
|
@ -67,17 +67,17 @@ def test_network(proto,addrs):
|
|||
from mmgen.addr import CoinAddr
|
||||
|
||||
for addr in addrs:
|
||||
a1 = CoinAddr(proto,addr['std'])
|
||||
a1 = CoinAddr(proto, addr['std'])
|
||||
print_info(a1)
|
||||
check_bytes(a1)
|
||||
assert not hasattr(a1.parsed,'payment_id') or a1.parsed.payment_id is None
|
||||
assert not hasattr(a1.parsed, 'payment_id') or a1.parsed.payment_id is None
|
||||
|
||||
if 'int' in addr:
|
||||
a2 = CoinAddr(proto,addr['int'])
|
||||
a2 = CoinAddr(proto, addr['int'])
|
||||
print_info(a2)
|
||||
check_bytes(a2)
|
||||
check_equal( a1.parsed.data, a2.parsed.data )
|
||||
check_equal( a2.parsed.payment_id, bytes.fromhex(addr['id']) )
|
||||
check_equal(a1.parsed.data, a2.parsed.data)
|
||||
check_equal(a2.parsed.payment_id, bytes.fromhex(addr['id']))
|
||||
|
||||
msg('OK')
|
||||
vmsg('')
|
||||
|
|
@ -85,16 +85,16 @@ def test_network(proto,addrs):
|
|||
|
||||
class unit_test:
|
||||
|
||||
def run_test(self,name,ut):
|
||||
def run_test(self, name, ut):
|
||||
|
||||
from mmgen.protocol import init_proto
|
||||
|
||||
for net_id,addrs in vectors.items():
|
||||
coin,network = net_id.split('_')
|
||||
for net_id, addrs in vectors.items():
|
||||
coin, network = net_id.split('_')
|
||||
if cfg.no_altcoin_deps and coin != 'btc':
|
||||
continue
|
||||
test_network(
|
||||
init_proto( cfg, coin, network=network ),
|
||||
addrs )
|
||||
init_proto(cfg, coin, network=network),
|
||||
addrs)
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -4,158 +4,168 @@
|
|||
test.unit_tests_d.ut_baseconv: Base conversion unit test for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.util import msg,msg_r
|
||||
from mmgen.util import msg, msg_r
|
||||
|
||||
from ..include.common import cfg,qmsg,qmsg_r,vmsg,vmsg_r
|
||||
from ..include.common import cfg, qmsg, qmsg_r, vmsg, vmsg_r
|
||||
|
||||
class unit_test:
|
||||
|
||||
vectors = {
|
||||
'b58': (
|
||||
(('00',None),'1'),
|
||||
(('00',1),'1'),
|
||||
(('00',2),'11'),
|
||||
(('01',None),'2'),
|
||||
(('01',1),'2'),
|
||||
(('01',2),'12'),
|
||||
(('0f',None),'G'),
|
||||
(('0f',1),'G'),
|
||||
(('0f',2),'1G'),
|
||||
(('deadbeef',None),'6h8cQN'),
|
||||
(('deadbeef',20),'111111111111116h8cQN'),
|
||||
(('00000000',None),'1'),
|
||||
(('00000000',20),'11111111111111111111'),
|
||||
(('ffffffff',None),'7YXq9G'),
|
||||
(('ffffffff',20),'111111111111117YXq9G'),
|
||||
(('ff'*16,'seed'),'YcVfxkQb6JRzqk5kF2tNLv'),
|
||||
(('ff'*24,'seed'),'QLbz7JHiBTspS962RLKV8GndWFwiEaqKL'),
|
||||
(('ff'*32,'seed'),'JEKNVnkbo3jma5nREBBJCDoXFVeKkD56V3xKrvRmWxFG'),
|
||||
(('00'*16,'seed'),'1111111111111111111111'),
|
||||
(('00'*24,'seed'),'111111111111111111111111111111111'),
|
||||
(('00'*32,'seed'),'11111111111111111111111111111111111111111111'),
|
||||
(('00', None), '1'),
|
||||
(('00', 1), '1'),
|
||||
(('00', 2), '11'),
|
||||
(('01', None), '2'),
|
||||
(('01', 1), '2'),
|
||||
(('01', 2), '12'),
|
||||
(('0f', None), 'G'),
|
||||
(('0f', 1), 'G'),
|
||||
(('0f', 2), '1G'),
|
||||
(('deadbeef', None), '6h8cQN'),
|
||||
(('deadbeef', 20), '111111111111116h8cQN'),
|
||||
(('00000000', None), '1'),
|
||||
(('00000000', 20), '11111111111111111111'),
|
||||
(('ffffffff', None), '7YXq9G'),
|
||||
(('ffffffff', 20), '111111111111117YXq9G'),
|
||||
(('ff'*16, 'seed'), 'YcVfxkQb6JRzqk5kF2tNLv'),
|
||||
(('ff'*24, 'seed'), 'QLbz7JHiBTspS962RLKV8GndWFwiEaqKL'),
|
||||
(('ff'*32, 'seed'), 'JEKNVnkbo3jma5nREBBJCDoXFVeKkD56V3xKrvRmWxFG'),
|
||||
(('00'*16, 'seed'), '1111111111111111111111'),
|
||||
(('00'*24, 'seed'), '111111111111111111111111111111111'),
|
||||
(('00'*32, 'seed'), '11111111111111111111111111111111111111111111'),
|
||||
),
|
||||
# MMGen-flavored base32 using simple base conversion
|
||||
'b32': (
|
||||
(('00',None),'A'),
|
||||
(('00',1),'A'),
|
||||
(('00',2),'AA'),
|
||||
(('01',None),'B'),
|
||||
(('01',1),'B'),
|
||||
(('01',2),'AB'),
|
||||
(('0f',None),'P'),
|
||||
(('0f',1),'P'),
|
||||
(('0f',2),'AP'),
|
||||
(('deadbeef',None),'DPK3PXP'),
|
||||
(('deadbeef',20),'AAAAAAAAAAAAADPK3PXP'),
|
||||
(('00000000',None),'A'),
|
||||
(('00000000',20),'AAAAAAAAAAAAAAAAAAAA'),
|
||||
(('ffffffff',None),'D777777'),
|
||||
(('ffffffff',20),'AAAAAAAAAAAAAD777777'),
|
||||
(('00', None), 'A'),
|
||||
(('00', 1), 'A'),
|
||||
(('00', 2), 'AA'),
|
||||
(('01', None), 'B'),
|
||||
(('01', 1), 'B'),
|
||||
(('01', 2), 'AB'),
|
||||
(('0f', None), 'P'),
|
||||
(('0f', 1), 'P'),
|
||||
(('0f', 2), 'AP'),
|
||||
(('deadbeef', None), 'DPK3PXP'),
|
||||
(('deadbeef', 20), 'AAAAAAAAAAAAADPK3PXP'),
|
||||
(('00000000', None), 'A'),
|
||||
(('00000000', 20), 'AAAAAAAAAAAAAAAAAAAA'),
|
||||
(('ffffffff', None), 'D777777'),
|
||||
(('ffffffff', 20), 'AAAAAAAAAAAAAD777777'),
|
||||
),
|
||||
'b16': (
|
||||
(('00',None),'0'),
|
||||
(('00',1),'0'),
|
||||
(('00',2),'00'),
|
||||
(('01',None),'1'),
|
||||
(('01',1),'1'),
|
||||
(('01',2),'01'),
|
||||
(('0f',None),'f'),
|
||||
(('0f',1),'f'),
|
||||
(('0f',2),'0f'),
|
||||
(('deadbeef',None),'deadbeef'),
|
||||
(('deadbeef',20),'000000000000deadbeef'),
|
||||
(('00000000',None),'0'),
|
||||
(('00000000',20),'00000000000000000000'),
|
||||
(('ffffffff',None),'ffffffff'),
|
||||
(('ffffffff',20),'000000000000ffffffff'),
|
||||
(('00', None), '0'),
|
||||
(('00', 1), '0'),
|
||||
(('00', 2), '00'),
|
||||
(('01', None), '1'),
|
||||
(('01', 1), '1'),
|
||||
(('01', 2), '01'),
|
||||
(('0f', None), 'f'),
|
||||
(('0f', 1), 'f'),
|
||||
(('0f', 2), '0f'),
|
||||
(('deadbeef', None), 'deadbeef'),
|
||||
(('deadbeef', 20), '000000000000deadbeef'),
|
||||
(('00000000', None), '0'),
|
||||
(('00000000', 20), '00000000000000000000'),
|
||||
(('ffffffff', None), 'ffffffff'),
|
||||
(('ffffffff', 20), '000000000000ffffffff'),
|
||||
),
|
||||
'b10': (
|
||||
(('00',None),'0'),
|
||||
(('00',1),'0'),
|
||||
(('00',2),'00'),
|
||||
(('01',None),'1'),
|
||||
(('01',1),'1'),
|
||||
(('01',2),'01'),
|
||||
(('0f',None),'15'),
|
||||
(('0f',1),'15'),
|
||||
(('0f',2),'15'),
|
||||
(('deadbeef',None),'3735928559'),
|
||||
(('deadbeef',20),'00000000003735928559'),
|
||||
(('00000000',None),'0'),
|
||||
(('00000000',20),'00000000000000000000'),
|
||||
(('ffffffff',None),'4294967295'),
|
||||
(('ffffffff',20),'00000000004294967295'),
|
||||
(('00', None), '0'),
|
||||
(('00', 1), '0'),
|
||||
(('00', 2), '00'),
|
||||
(('01', None), '1'),
|
||||
(('01', 1), '1'),
|
||||
(('01', 2), '01'),
|
||||
(('0f', None), '15'),
|
||||
(('0f', 1), '15'),
|
||||
(('0f', 2), '15'),
|
||||
(('deadbeef', None), '3735928559'),
|
||||
(('deadbeef', 20), '00000000003735928559'),
|
||||
(('00000000', None), '0'),
|
||||
(('00000000', 20), '00000000000000000000'),
|
||||
(('ffffffff', None), '4294967295'),
|
||||
(('ffffffff', 20), '00000000004294967295'),
|
||||
),
|
||||
'b8': (
|
||||
(('00',None),'0'),
|
||||
(('00',1),'0'),
|
||||
(('00',2),'00'),
|
||||
(('01',None),'1'),
|
||||
(('01',1),'1'),
|
||||
(('01',2),'01'),
|
||||
(('0f',None),'17'),
|
||||
(('0f',1),'17'),
|
||||
(('0f',2),'17'),
|
||||
(('deadbeef',None),'33653337357'),
|
||||
(('deadbeef',20),'00000000033653337357'),
|
||||
(('00000000',None),'0'),
|
||||
(('00000000',20),'00000000000000000000'),
|
||||
(('ffffffff',None),'37777777777'),
|
||||
(('ffffffff',20),'00000000037777777777'),
|
||||
(('00', None), '0'),
|
||||
(('00', 1), '0'),
|
||||
(('00', 2), '00'),
|
||||
(('01', None), '1'),
|
||||
(('01', 1), '1'),
|
||||
(('01', 2), '01'),
|
||||
(('0f', None), '17'),
|
||||
(('0f', 1), '17'),
|
||||
(('0f', 2), '17'),
|
||||
(('deadbeef', None), '33653337357'),
|
||||
(('deadbeef', 20), '00000000033653337357'),
|
||||
(('00000000', None), '0'),
|
||||
(('00000000', 20), '00000000000000000000'),
|
||||
(('ffffffff', None), '37777777777'),
|
||||
(('ffffffff', 20), '00000000037777777777'),
|
||||
),
|
||||
'b6d': (
|
||||
(('00',None),'1'),
|
||||
(('00',1),'1'),
|
||||
(('00',2),'11'),
|
||||
(('01',None),'2'),
|
||||
(('01',1),'2'),
|
||||
(('01',2),'12'),
|
||||
(('0f',None),'34'),
|
||||
(('0f',1),'34'),
|
||||
(('0f',2),'34'),
|
||||
(('010f',None),'2242'),
|
||||
(('010f',20),'11111111111111112242'),
|
||||
(('deadbeef',None),'2525524636426'),
|
||||
(('deadbeef',20),'11111112525524636426'),
|
||||
(('00000000',None),'1'),
|
||||
(('00000000',20),'11111111111111111111'),
|
||||
(('ffffffff',None),'2661215126614'),
|
||||
(('ffffffff',20),'11111112661215126614'),
|
||||
(('00', None), '1'),
|
||||
(('00', 1), '1'),
|
||||
(('00', 2), '11'),
|
||||
(('01', None), '2'),
|
||||
(('01', 1), '2'),
|
||||
(('01', 2), '12'),
|
||||
(('0f', None), '34'),
|
||||
(('0f', 1), '34'),
|
||||
(('0f', 2), '34'),
|
||||
(('010f', None), '2242'),
|
||||
(('010f', 20), '11111111111111112242'),
|
||||
(('deadbeef', None), '2525524636426'),
|
||||
(('deadbeef', 20), '11111112525524636426'),
|
||||
(('00000000', None), '1'),
|
||||
(('00000000', 20), '11111111111111111111'),
|
||||
(('ffffffff', None), '2661215126614'),
|
||||
(('ffffffff', 20), '11111112661215126614'),
|
||||
|
||||
(('ff'*16,'seed'),'34164464641266661652465154654653354436664555521414'),
|
||||
(('ff'*24,'seed'),'246111411433323364222465566552324652566121541623426135163525451613554313654'),
|
||||
(('ff'*32,'seed'),'2132521653312613134145131423465414636252114131225324246311141642456513416322412146151432142242565134'),
|
||||
(('00'*16,'seed'),'1'*50),
|
||||
(('00'*24,'seed'),'1'*75),
|
||||
(('00'*32,'seed'),'1'*100),
|
||||
(('ff'*16, 'seed'), '34164464641266661652465154654653354436664555521414'),
|
||||
(('ff'*24, 'seed'), '246111411433323364222465566552324652566121541623426135163525451613554313654'),
|
||||
(('ff'*32, 'seed'), '2132521653312613134145131423465414636252114131225324246311141642456513416322412146151432142242565134'),
|
||||
(('00'*16, 'seed'), '1'*50),
|
||||
(('00'*24, 'seed'), '1'*75),
|
||||
(('00'*32, 'seed'), '1'*100),
|
||||
),
|
||||
'mmgen': (
|
||||
(('deadbeefdeadbeefdeadbeefdeadbeef','seed'),
|
||||
'table cast forgive master funny gaze sadness ripple million paint moral match' ),
|
||||
(('deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef','seed'),
|
||||
'swirl maybe anymore mix scale stray fog use approach page crime rhyme ' +
|
||||
'class former strange window snap soon'),
|
||||
(('deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef','seed'),
|
||||
'swell type milk figure cheese phone fill black test bloom heard comfort ' +
|
||||
'image terrible radio lesson own reply battle goal goodbye need laugh stream'),
|
||||
(('ffffffffffffffffffffffffffffffff','seed'),
|
||||
'yellow yeah show bowl season spider cling defeat poison law shelter reflect'),
|
||||
(('ffffffffffffffffffffffffffffffffffffffffffffffff','seed'),
|
||||
'yeah youth quit fail perhaps drum out person young click skin ' +
|
||||
'weird inside silently perfectly together anyone memory'),
|
||||
(('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff','seed'),
|
||||
'wrote affection object cell opinion here laughter stare honest north cost begin ' +
|
||||
'murder something yourself effort acid dot doubt game broke tell guilt innocent'),
|
||||
(('00000000000000000000000000000001','seed'),
|
||||
'able ' * 11 + 'about'),
|
||||
(('000000000000000000000000000000000000000000000001','seed'),
|
||||
'able ' * 17 + 'about'),
|
||||
(('0000000000000000000000000000000000000000000000000000000000000001','seed'),
|
||||
'able ' * 23 + 'about'),
|
||||
(
|
||||
('deadbeefdeadbeefdeadbeefdeadbeef', 'seed'),
|
||||
'table cast forgive master funny gaze sadness ripple million paint moral match'
|
||||
), (
|
||||
('deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef', 'seed'),
|
||||
'swirl maybe anymore mix scale stray fog use approach page crime rhyme ' +
|
||||
'class former strange window snap soon'
|
||||
), (
|
||||
('deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef', 'seed'),
|
||||
'swell type milk figure cheese phone fill black test bloom heard comfort ' +
|
||||
'image terrible radio lesson own reply battle goal goodbye need laugh stream'
|
||||
), (
|
||||
('ffffffffffffffffffffffffffffffff', 'seed'),
|
||||
'yellow yeah show bowl season spider cling defeat poison law shelter reflect'
|
||||
), (
|
||||
('ffffffffffffffffffffffffffffffffffffffffffffffff', 'seed'),
|
||||
'yeah youth quit fail perhaps drum out person young click skin ' +
|
||||
'weird inside silently perfectly together anyone memory'
|
||||
), (
|
||||
('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 'seed'),
|
||||
'wrote affection object cell opinion here laughter stare honest north cost begin ' +
|
||||
'murder something yourself effort acid dot doubt game broke tell guilt innocent'
|
||||
), (
|
||||
('00000000000000000000000000000001', 'seed'),
|
||||
'able ' * 11 + 'about'
|
||||
), (
|
||||
('000000000000000000000000000000000000000000000001', 'seed'),
|
||||
'able ' * 17 + 'about'
|
||||
), (
|
||||
('0000000000000000000000000000000000000000000000000000000000000001', 'seed'),
|
||||
'able ' * 23 + 'about'
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
def run_test(self,name,ut):
|
||||
def run_test(self, name, ut):
|
||||
|
||||
msg_r('Testing base conversion routines...')
|
||||
|
||||
|
|
@ -164,38 +174,35 @@ class unit_test:
|
|||
rerr = "return value ({!r}) does not match reference value ({!r})"
|
||||
|
||||
qmsg_r('\nChecking hex-to-base conversion:')
|
||||
for base,data in self.vectors.items():
|
||||
for base, data in self.vectors.items():
|
||||
fs = " {h:%s} {p:<6} {r}" % max(len(d[0][0]) for d in data)
|
||||
if not cfg.verbose:
|
||||
qmsg_r(f' {base}')
|
||||
vmsg(f'\nBase: {base}')
|
||||
vmsg(fs.format(h='Input',p='Pad',r='Output'))
|
||||
for (hexstr,pad),ret_chk in data:
|
||||
ret = baseconv(base).fromhex(hexstr,pad=pad,tostr=True)
|
||||
vmsg(fs.format(h='Input', p='Pad', r='Output'))
|
||||
for (hexstr, pad), ret_chk in data:
|
||||
ret = baseconv(base).fromhex(hexstr, pad=pad, tostr=True)
|
||||
if pad != 'seed':
|
||||
assert len(ret) >= (pad or 0), perr.format(ret,pad or 0)
|
||||
assert ret == ret_chk, rerr.format(ret,ret_chk)
|
||||
vmsg(fs.format(h=hexstr,r=ret,p=str(pad)))
|
||||
# msg("(('{h}',{p}),'{r}'),".format(h=hexstr,r=ret,c=ret_chk,p=pad))
|
||||
# msg('')
|
||||
# return True
|
||||
assert len(ret) >= (pad or 0), perr.format(ret, pad or 0)
|
||||
assert ret == ret_chk, rerr.format(ret, ret_chk)
|
||||
vmsg(fs.format(h=hexstr, r=ret, p=str(pad)))
|
||||
|
||||
qmsg_r('\nChecking base-to-hex conversion:')
|
||||
for base,data in self.vectors.items():
|
||||
for base, data in self.vectors.items():
|
||||
fs = " {h:%s} {p:<6} {r}" % max(len(d[1]) for d in data)
|
||||
if not cfg.verbose:
|
||||
qmsg_r(f' {base}')
|
||||
vmsg(f'\nBase: {base}')
|
||||
vmsg(fs.format(h='Input',p='Pad',r='Output'))
|
||||
for (hexstr,pad),ret_chk in data:
|
||||
vmsg(fs.format(h='Input', p='Pad', r='Output'))
|
||||
for (hexstr, pad), ret_chk in data:
|
||||
if type(pad) is int:
|
||||
pad = len(hexstr)
|
||||
ret = baseconv(base).tohex( ret_chk.split() if base == 'mmgen' else ret_chk, pad=pad )
|
||||
if pad is None:
|
||||
assert int(ret,16) == int(hexstr,16), rerr.format(int(ret,16),int(hexstr,16))
|
||||
assert int(ret, 16) == int(hexstr, 16), rerr.format(int(ret, 16), int(hexstr, 16))
|
||||
else:
|
||||
assert ret == hexstr, rerr.format(ret,hexstr)
|
||||
vmsg(fs.format(h=ret_chk,r=ret,p=str(pad)))
|
||||
# msg("(('{h}',{p}),'{r}'),".format(h=hexstr,r=ret_chk,c=ret_chk,p=pad))
|
||||
assert ret == hexstr, rerr.format(ret, hexstr)
|
||||
vmsg(fs.format(h=ret_chk, r=ret, p=str(pad)))
|
||||
|
||||
qmsg_r('\nChecking wordlist checksums:')
|
||||
vmsg('')
|
||||
|
|
@ -222,23 +229,23 @@ class unit_test:
|
|||
sle = 'SeedLengthError'
|
||||
|
||||
bad_data = (
|
||||
('hexstr', hse, ': not a hexadecimal str', lambda:fr58('x')),
|
||||
('hexstr (seed)', hse, 'seed data not a hexadec', lambda:fr58('x',pad='seed')),
|
||||
('hexstr (empty)', bce, 'empty data not allowed', lambda:fr58('')),
|
||||
('b58 data', bce, ': not in base58', lambda:to58('IfFzZ')),
|
||||
('b58 data (seed)', bce, 'seed data not in base58', lambda:to58(bad_b58,pad='seed')),
|
||||
('b58 len (seed)', bce, 'invalid length for', lambda:to58(bad_b58len,pad='seed')),
|
||||
('b58 data (empty)', bce, 'empty base58 data', lambda:to58('')),
|
||||
('b8 data (empty)' , bce, 'empty base8 string data', lambda:to8('')),
|
||||
('b32 data', bce, 'not in MMGen base32', lambda:to32('1az')),
|
||||
('pad arg (in)', bpe, "illegal value for 'pad'", lambda:fr58('ff',pad='foo')),
|
||||
('pad arg (in)', bpe, "illegal value for 'pad'", lambda:fr58('ff',pad=False)),
|
||||
('pad arg (in)', bpe, "illegal value for 'pad'", lambda:fr58('ff',pad=True)),
|
||||
('seedlen (in)', sle, 'invalid byte length', lambda:fr58('ff',pad='seed')),
|
||||
('pad arg (out)', bpe, "illegal value for 'pad'", lambda:to58('Z',pad='foo')),
|
||||
('pad arg (out)', bpe, "illegal value for 'pad'", lambda:to58('Z',pad=False)),
|
||||
('pad arg (out)', bpe, "illegal value for 'pad'", lambda:to58('Z',pad=True)),
|
||||
('seedlen (out)', bce, 'invalid length for seed', lambda:to58('Z',pad='seed')),
|
||||
('hexstr', hse, ': not a hexadecimal str', lambda: fr58('x')),
|
||||
('hexstr (seed)', hse, 'seed data not a hexadec', lambda: fr58('x', pad='seed')),
|
||||
('hexstr (empty)', bce, 'empty data not allowed', lambda: fr58('')),
|
||||
('b58 data', bce, ': not in base58', lambda: to58('IfFzZ')),
|
||||
('b58 data (seed)', bce, 'seed data not in base58', lambda: to58(bad_b58, pad='seed')),
|
||||
('b58 len (seed)', bce, 'invalid length for', lambda: to58(bad_b58len, pad='seed')),
|
||||
('b58 data (empty)', bce, 'empty base58 data', lambda: to58('')),
|
||||
('b8 data (empty)' , bce, 'empty base8 string data', lambda: to8('')),
|
||||
('b32 data', bce, 'not in MMGen base32', lambda: to32('1az')),
|
||||
('pad arg (in)', bpe, "illegal value for 'pad'", lambda: fr58('ff', pad='foo')),
|
||||
('pad arg (in)', bpe, "illegal value for 'pad'", lambda: fr58('ff', pad=False)),
|
||||
('pad arg (in)', bpe, "illegal value for 'pad'", lambda: fr58('ff', pad=True)),
|
||||
('seedlen (in)', sle, 'invalid byte length', lambda: fr58('ff', pad='seed')),
|
||||
('pad arg (out)', bpe, "illegal value for 'pad'", lambda: to58('Z', pad='foo')),
|
||||
('pad arg (out)', bpe, "illegal value for 'pad'", lambda: to58('Z', pad=False)),
|
||||
('pad arg (out)', bpe, "illegal value for 'pad'", lambda: to58('Z', pad=True)),
|
||||
('seedlen (out)', bce, 'invalid length for seed', lambda: to58('Z', pad='seed')),
|
||||
)
|
||||
|
||||
ut.process_bad_data(bad_data)
|
||||
|
|
|
|||
|
|
@ -12,81 +12,96 @@ from ..include.common import cfg, qmsg, vmsg
|
|||
class unit_tests:
|
||||
|
||||
vectors = (
|
||||
( "00000000000000000000000000000000",
|
||||
(
|
||||
"00000000000000000000000000000000",
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
|
||||
),
|
||||
( "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
), (
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"legal winner thank year wave sausage worth useful legal winner thank yellow"
|
||||
),
|
||||
( "80808080808080808080808080808080",
|
||||
), (
|
||||
"80808080808080808080808080808080",
|
||||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage above"
|
||||
),
|
||||
( "ffffffffffffffffffffffffffffffff",
|
||||
), (
|
||||
"ffffffffffffffffffffffffffffffff",
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong"
|
||||
),
|
||||
( "000000000000000000000000000000000000000000000000",
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent"
|
||||
),
|
||||
( "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will"
|
||||
),
|
||||
( "808080808080808080808080808080808080808080808080",
|
||||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always"
|
||||
),
|
||||
( "ffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
), (
|
||||
"000000000000000000000000000000000000000000000000",
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon "
|
||||
"abandon abandon abandon abandon abandon agent"
|
||||
), (
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth "
|
||||
"useful legal will"
|
||||
), (
|
||||
"808080808080808080808080808080808080808080808080",
|
||||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor "
|
||||
"acoustic avoid letter always"
|
||||
), (
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when"
|
||||
),
|
||||
( "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art"
|
||||
),
|
||||
( "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title"
|
||||
),
|
||||
( "8080808080808080808080808080808080808080808080808080808080808080",
|
||||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless"
|
||||
),
|
||||
( "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
), (
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon "
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art"
|
||||
), (
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth "
|
||||
"useful legal winner thank year wave sausage worth title"
|
||||
), (
|
||||
"8080808080808080808080808080808080808080808080808080808080808080",
|
||||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor "
|
||||
"acoustic avoid letter advice cage absurd amount doctor acoustic bless"
|
||||
), (
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote"
|
||||
),
|
||||
( "9e885d952ad362caeb4efe34a8e91bd2",
|
||||
), (
|
||||
"9e885d952ad362caeb4efe34a8e91bd2",
|
||||
"ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic"
|
||||
),
|
||||
( "6610b25967cdcca9d59875f5cb50b0ea75433311869e930b",
|
||||
"gravity machine north sort system female filter attitude volume fold club stay feature office ecology stable narrow fog"
|
||||
),
|
||||
( "68a79eaca2324873eacc50cb9c6eca8cc68ea5d936f98787c60c7ebc74e6ce7c",
|
||||
"hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay length"
|
||||
),
|
||||
( "c0ba5a8e914111210f2bd131f3d5e08d",
|
||||
), (
|
||||
"6610b25967cdcca9d59875f5cb50b0ea75433311869e930b",
|
||||
"gravity machine north sort system female filter attitude volume fold club stay feature office "
|
||||
"ecology stable narrow fog"
|
||||
), (
|
||||
"68a79eaca2324873eacc50cb9c6eca8cc68ea5d936f98787c60c7ebc74e6ce7c",
|
||||
"hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy "
|
||||
"gospel tennis maple dilemma loan word shrug inflict delay length"
|
||||
), (
|
||||
"c0ba5a8e914111210f2bd131f3d5e08d",
|
||||
"scheme spot photo card baby mountain device kick cradle pact join borrow"
|
||||
),
|
||||
( "6d9be1ee6ebd27a258115aad99b7317b9c8d28b6d76431c3",
|
||||
"horn tenant knee talent sponsor spell gate clip pulse soap slush warm silver nephew swap uncle crack brave"
|
||||
),
|
||||
( "9f6a2878b2520799a44ef18bc7df394e7061a224d2c33cd015b157d746869863",
|
||||
"panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed nation flash devote level hobby quick inner drive ghost inside"
|
||||
),
|
||||
( "23db8160a31d3e0dca3688ed941adbf3",
|
||||
), (
|
||||
"6d9be1ee6ebd27a258115aad99b7317b9c8d28b6d76431c3",
|
||||
"horn tenant knee talent sponsor spell gate clip pulse soap slush warm silver nephew swap uncle "
|
||||
"crack brave"
|
||||
), (
|
||||
"9f6a2878b2520799a44ef18bc7df394e7061a224d2c33cd015b157d746869863",
|
||||
"panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed "
|
||||
"nation flash devote level hobby quick inner drive ghost inside"
|
||||
), (
|
||||
"23db8160a31d3e0dca3688ed941adbf3",
|
||||
"cat swing flag economy stadium alone churn speed unique patch report train"
|
||||
),
|
||||
( "8197a4a47f0425faeaa69deebc05ca29c0a5b5cc76ceacc0",
|
||||
"light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain crack supply proud access"
|
||||
),
|
||||
( "066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad",
|
||||
"all hour make first leader extend hole alien behind guard gospel lava path output census museum junior mass reopen famous sing advance salt reform"
|
||||
),
|
||||
( "f30f8c1da665478f49b001d94c5fc452",
|
||||
), (
|
||||
"8197a4a47f0425faeaa69deebc05ca29c0a5b5cc76ceacc0",
|
||||
"light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain "
|
||||
"crack supply proud access"
|
||||
), (
|
||||
"066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad",
|
||||
"all hour make first leader extend hole alien behind guard gospel lava path output census museum "
|
||||
"junior mass reopen famous sing advance salt reform"
|
||||
), (
|
||||
"f30f8c1da665478f49b001d94c5fc452",
|
||||
"vessel ladder alter error federal sibling chat ability sun glass valve picture"
|
||||
),
|
||||
( "c10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05",
|
||||
"scissors invite lock maple supreme raw rapid void congress muscle digital elegant little brisk hair mango congress clump"
|
||||
),
|
||||
( "f585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f",
|
||||
"void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold"
|
||||
), (
|
||||
"c10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05",
|
||||
"scissors invite lock maple supreme raw rapid void congress muscle digital elegant little brisk "
|
||||
"hair mango congress clump"
|
||||
), (
|
||||
"f585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f",
|
||||
"void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen "
|
||||
"patrol group space point ten exist slush involve unfold"
|
||||
)
|
||||
)
|
||||
|
||||
def conversion(self,name,ut):
|
||||
def conversion(self, name, ut):
|
||||
|
||||
vmsg('')
|
||||
qmsg(blue('Testing BIP39 conversion routines'))
|
||||
|
|
@ -99,7 +114,7 @@ class unit_tests:
|
|||
for v in self.vectors:
|
||||
chk = tuple(v[1].split())
|
||||
vmsg(' '+v[1])
|
||||
res = b.fromhex( v[0] )
|
||||
res = b.fromhex(v[0])
|
||||
assert res == chk, f'mismatch:\nres: {res}\nchk: {chk}'
|
||||
|
||||
vmsg('')
|
||||
|
|
@ -107,7 +122,7 @@ class unit_tests:
|
|||
for v in self.vectors:
|
||||
chk = v[0]
|
||||
vmsg(' '+chk)
|
||||
res = b.tohex( v[1].split() )
|
||||
res = b.tohex(v[1].split())
|
||||
assert res == chk, f'mismatch:\nres: {res}\nchk: {chk}'
|
||||
|
||||
qmsg('OK')
|
||||
|
|
@ -115,7 +130,7 @@ class unit_tests:
|
|||
|
||||
return True
|
||||
|
||||
def errors(self,name,ut):
|
||||
def errors(self, name, ut):
|
||||
|
||||
vmsg('')
|
||||
qmsg(blue('Testing error handling'))
|
||||
|
|
@ -131,15 +146,15 @@ class unit_tests:
|
|||
th = b.tohex
|
||||
fh = b.fromhex
|
||||
bad_data = (
|
||||
('hex', 'AssertionError', 'not a hexadecimal',lambda:fh('xx')),
|
||||
('seed len', 'AssertionError', 'invalid seed bit', lambda:fh(bad_seed)),
|
||||
('mnemonic type', 'AssertionError', 'must be list', lambda:th('string')),
|
||||
('arg (tostr=True)', 'AssertionError', "'tostr' must be", lambda:fh(good_seed,tostr=True)),
|
||||
('pad len (fromhex)','AssertionError', "invalid 'pad' arg",lambda:fh(good_seed,pad=23)),
|
||||
('pad len (tohex)', 'AssertionError', "invalid 'pad' arg",lambda:th(good_mn,pad=23)),
|
||||
('word', 'MnemonicError', "not in the BIP39", lambda:th(bad_word_mn)),
|
||||
('checksum', 'MnemonicError', "checksum", lambda:th(bad_chksum_mn)),
|
||||
('seed phrase len', 'MnemonicError', "phrase len", lambda:th(bad_len_mn)),
|
||||
('hex', 'AssertionError', 'not a hexadecimal', lambda: fh('xx')),
|
||||
('seed len', 'AssertionError', 'invalid seed bit', lambda: fh(bad_seed)),
|
||||
('mnemonic type', 'AssertionError', 'must be list', lambda: th('string')),
|
||||
('arg (tostr=True)', 'AssertionError', "'tostr' must be", lambda: fh(good_seed, tostr=True)),
|
||||
('pad len (fromhex)', 'AssertionError', "invalid 'pad' arg", lambda: fh(good_seed, pad=23)),
|
||||
('pad len (tohex)', 'AssertionError', "invalid 'pad' arg", lambda: th(good_mn, pad=23)),
|
||||
('word', 'MnemonicError', "not in the BIP39", lambda: th(bad_word_mn)),
|
||||
('checksum', 'MnemonicError', "checksum", lambda: th(bad_chksum_mn)),
|
||||
('seed phrase len', 'MnemonicError', "phrase len", lambda: th(bad_len_mn)),
|
||||
)
|
||||
|
||||
ut.process_bad_data(bad_data)
|
||||
|
|
@ -149,7 +164,7 @@ class unit_tests:
|
|||
|
||||
return True
|
||||
|
||||
def genseed(self,name,ut):
|
||||
def genseed(self, name, ut):
|
||||
|
||||
vmsg('')
|
||||
qmsg(blue('Testing seed generation with password'))
|
||||
|
|
@ -165,7 +180,7 @@ class unit_tests:
|
|||
assert seed_hex == '3c30b98d3d9a713cf5a7a42f5dd27b3bf7f4d792d2b9225f6f519a0da978e13c6f36989ef2123b12a96d6ad5a443a95d61022ffaa9fbce8f946da7b67f75d339'
|
||||
|
||||
passwd = 'passw0rd'
|
||||
seed_hex = bip39().generate_seed(mnemonic.split(),passwd).hex()
|
||||
seed_hex = bip39().generate_seed(mnemonic.split(), passwd).hex()
|
||||
vmsg(f' Password: {orange(passwd)}\n {seed_hex}')
|
||||
assert seed_hex == '7eb773bf60f1a5071f96736b6ddbe5c544a7b7740182a80493e29577e58b7cde011d4e38d26f65dab6c9fdebe5594e523447a1427ffd60746e6d04b4daa42eb1'
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@
|
|||
test.unit_tests_d.ut_bip_hd: bip_hd unit test for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.color import gray,pink,blue
|
||||
from mmgen.color import gray, pink, blue
|
||||
from mmgen.util import fmt
|
||||
from mmgen.bip_hd import Bip32ExtendedKey,BipHDConfig,BipHDNode,MasterNode,get_chain_params
|
||||
from mmgen.bip_hd import Bip32ExtendedKey, BipHDConfig, BipHDNode, MasterNode, get_chain_params
|
||||
|
||||
from ..include.common import cfg,vmsg
|
||||
from ..include.common import cfg, vmsg
|
||||
|
||||
# Source: BIP-32
|
||||
vectors_bip32 = [
|
||||
|
|
@ -46,7 +46,7 @@ vectors_bip32 = [
|
|||
'xpub': 'xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy',
|
||||
'xprv': 'xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76',
|
||||
},
|
||||
},{
|
||||
}, {
|
||||
'seed': 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542',
|
||||
'm': {
|
||||
'xpub': 'xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB',
|
||||
|
|
@ -72,7 +72,7 @@ vectors_bip32 = [
|
|||
'xpub': 'xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt',
|
||||
'xprv': 'xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j',
|
||||
},
|
||||
},{
|
||||
}, {
|
||||
'comment': 'These vectors test for the retention of leading zeros. See bitpay/bitcore-lib#47 and iancoleman/bip39#58 for more information.',
|
||||
'seed': '4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be',
|
||||
'm': {
|
||||
|
|
@ -83,7 +83,7 @@ vectors_bip32 = [
|
|||
'xpub': 'xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y',
|
||||
'xprv': 'xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L',
|
||||
},
|
||||
},{
|
||||
}, {
|
||||
'comment': 'These vectors test for the retention of leading zeros. See btcsuite/btcutil#172 for more information.',
|
||||
'seed': '3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678',
|
||||
"m": {
|
||||
|
|
@ -156,7 +156,7 @@ vectors_multicoin = {
|
|||
'bnb_beacon': 'bnb179c3ymltqm4utlp089zxqeta5dvn48a305rhe5',
|
||||
}
|
||||
|
||||
def wif2addr(cfg,wif):
|
||||
def wif2addr(cfg, wif):
|
||||
from mmgen.tool.coin import tool_cmd
|
||||
return tool_cmd(
|
||||
cfg = cfg.base_cfg,
|
||||
|
|
@ -170,15 +170,15 @@ class unit_tests:
|
|||
|
||||
@property
|
||||
def _seed(self):
|
||||
if not hasattr(self,'__seed'):
|
||||
if not hasattr(self, '__seed'):
|
||||
with open('test/ref/98831F3A.bip39') as fh:
|
||||
mnemonic = fh.read().strip()
|
||||
from mmgen.bip39 import bip39
|
||||
self.__seed = bip39().generate_seed(mnemonic.split())
|
||||
return self.__seed
|
||||
|
||||
def chainparams(self,name,ut):
|
||||
for bipnum,idx,chain,addr_cls in (
|
||||
def chainparams(self, name, ut):
|
||||
for bipnum, idx, chain, addr_cls in (
|
||||
(44, 0, 'btc', 'P2PKH'),
|
||||
(49, 0, 'btc', 'P2SH'),
|
||||
(84, 0, 'btc', 'P2WPKH'),
|
||||
|
|
@ -187,7 +187,7 @@ class unit_tests:
|
|||
(44, 2, 'ltc', 'P2PKH'),
|
||||
(44, 3, 'doge', 'P2PKH'),
|
||||
):
|
||||
res = get_chain_params(bipnum,chain)
|
||||
res = get_chain_params(bipnum, chain)
|
||||
assert res.idx == idx, res.idx
|
||||
assert res.chain == chain.upper()
|
||||
assert res.addr_cls == addr_cls
|
||||
|
|
@ -195,35 +195,35 @@ class unit_tests:
|
|||
vmsg('')
|
||||
return True
|
||||
|
||||
def derive(self,name,ut):
|
||||
def derive(self, name, ut):
|
||||
vmsg('seed: 98831F3A (default derivation)')
|
||||
|
||||
m = MasterNode(cfg,self._seed)
|
||||
m = MasterNode(cfg, self._seed)
|
||||
|
||||
purpose = m.init_cfg(coin='btc',addr_type='bech32').derive_private()
|
||||
purpose = m.init_cfg(coin='btc', addr_type='bech32').derive_private()
|
||||
vmsg(f' {purpose.address=}')
|
||||
|
||||
coin_type1 = purpose.derive_private()
|
||||
|
||||
coin_type2 = m.to_coin_type('btc',addr_type='bech32')
|
||||
coin_type2 = m.to_coin_type('btc', addr_type='bech32')
|
||||
assert coin_type1.address == coin_type2.address
|
||||
vmsg(f' {coin_type1.address=}')
|
||||
|
||||
acct = coin_type2.derive_private(idx=0)
|
||||
chain1 = acct.derive_private(idx=0,hardened=False)
|
||||
chain1 = acct.derive_private(idx=0, hardened=False)
|
||||
|
||||
chain2 = m.to_chain(idx=0,coin='btc',addr_type='bech32',public=False)
|
||||
chain2 = m.to_chain(idx=0, coin='btc', addr_type='bech32', public=False)
|
||||
assert chain2.address == chain1.address
|
||||
|
||||
chain3 = m.to_coin_type(coin='btc',addr_type='bech32').to_chain(0,public=True)
|
||||
chain3 = m.to_coin_type(coin='btc', addr_type='bech32').to_chain(0, public=True)
|
||||
assert chain3.address == chain1.address
|
||||
vmsg(f' {chain1.address=}')
|
||||
|
||||
a = BipHDNode.from_extended_key(cfg,'btc',chain2.xpub)
|
||||
b = BipHDNode.from_extended_key(cfg,'btc',chain2.xprv)
|
||||
a = BipHDNode.from_extended_key(cfg, 'btc', chain2.xpub)
|
||||
b = BipHDNode.from_extended_key(cfg, 'btc', chain2.xprv)
|
||||
vmsg(
|
||||
'\n xpub:\n' +
|
||||
fmt(str(Bip32ExtendedKey(b.xpub)),indent=' ')
|
||||
fmt(str(Bip32ExtendedKey(b.xpub)), indent=' ')
|
||||
)
|
||||
assert a.xpub == b.xpub
|
||||
|
||||
|
|
@ -238,20 +238,20 @@ class unit_tests:
|
|||
vmsg('')
|
||||
return True
|
||||
|
||||
def derive_addrfmt(self,name,ut):
|
||||
def derive_addrfmt(self, name, ut):
|
||||
vmsg('seed: 98831F3A (default derivation)')
|
||||
|
||||
m = MasterNode(cfg,self._seed)
|
||||
m = MasterNode(cfg, self._seed)
|
||||
|
||||
for addr_type in ('compressed','segwit','bech32'):
|
||||
for addr_type in ('compressed', 'segwit', 'bech32'):
|
||||
chk_xpub = vectors_addrfmt['pub'][addr_type]
|
||||
chk_xprv = vectors_addrfmt['prv'][addr_type]
|
||||
|
||||
res1 = m.to_chain(idx=0,coin='btc',addr_type=addr_type).derive_public(0)
|
||||
res1 = m.to_chain(idx=0, coin='btc', addr_type=addr_type).derive_public(0)
|
||||
vmsg(f' {addr_type}: {res1.xpub}')
|
||||
assert res1.xpub == chk_xpub
|
||||
|
||||
res2 = m.to_chain(idx=0,coin='btc',addr_type=addr_type).derive_private(0,False)
|
||||
res2 = m.to_chain(idx=0, coin='btc', addr_type=addr_type).derive_private(0, False)
|
||||
vmsg(f' {addr_type}: {res2.xprv}')
|
||||
assert res2.xprv == chk_xprv
|
||||
assert res2.xpub == chk_xpub
|
||||
|
|
@ -261,55 +261,55 @@ class unit_tests:
|
|||
vmsg('')
|
||||
return True
|
||||
|
||||
def path(self,name,ut):
|
||||
def path(self, name, ut):
|
||||
|
||||
for vec in vectors_bip32:
|
||||
seed = bytes.fromhex(vec['seed'])
|
||||
vmsg(f'Seed: {vec["seed"]}')
|
||||
|
||||
for n,path_str in enumerate(vec):
|
||||
if path_str in ('seed','comment'):
|
||||
for n, path_str in enumerate(vec):
|
||||
if path_str in ('seed', 'comment'):
|
||||
continue
|
||||
|
||||
path_arg = path_str.replace("'",'H') if n % 2 else path_str
|
||||
node = BipHDNode.from_path(cfg,seed,path_arg,no_path_checks=True)
|
||||
vmsg(' Path {} {}'.format(pink(path_str),blue('('+node.desc+')')))
|
||||
path_arg = path_str.replace("'", 'H') if n % 2 else path_str
|
||||
node = BipHDNode.from_path(cfg, seed, path_arg, no_path_checks=True)
|
||||
vmsg(' Path {} {}'.format(pink(path_str), blue('('+node.desc+')')))
|
||||
|
||||
for xkey_type in ('xpub','xprv'):
|
||||
vmsg(f' {getattr(node,xkey_type)}')
|
||||
assert getattr(node,xkey_type) == vec[path_str][xkey_type]
|
||||
for xkey_type in ('xpub', 'xprv'):
|
||||
vmsg(f' {getattr(node, xkey_type)}')
|
||||
assert getattr(node, xkey_type) == vec[path_str][xkey_type]
|
||||
|
||||
vmsg('')
|
||||
|
||||
return True
|
||||
|
||||
def parse_extended(self,name,ut):
|
||||
def parse_extended(self, name, ut):
|
||||
vmsg('Parsing and validating extended keys:\n')
|
||||
|
||||
for vec in vectors_bip32:
|
||||
vmsg(f' Seed: {vec["seed"]}')
|
||||
|
||||
for path_str in vec:
|
||||
if path_str in ('seed','comment'):
|
||||
if path_str in ('seed', 'comment'):
|
||||
continue
|
||||
|
||||
vmsg(' Path {}'.format(pink(path_str)))
|
||||
for xkey_type in ('xpub','xprv'):
|
||||
for xkey_type in ('xpub', 'xprv'):
|
||||
xkey = vec[path_str][xkey_type]
|
||||
vmsg(f' {xkey}')
|
||||
node = BipHDNode.from_extended_key(cfg,'btc',xkey)
|
||||
assert getattr(node,xkey_type) == xkey
|
||||
node = BipHDNode.from_extended_key(cfg, 'btc', xkey)
|
||||
assert getattr(node, xkey_type) == xkey
|
||||
|
||||
vmsg('')
|
||||
|
||||
return True
|
||||
|
||||
def multicoin(self,name,ut):
|
||||
m = MasterNode(cfg,self._seed)
|
||||
def multicoin(self, name, ut):
|
||||
m = MasterNode(cfg, self._seed)
|
||||
|
||||
fs = ' {:6} {:10} {}'
|
||||
vmsg(fs.format('COIN','ADDR_TYPE','ADDR'))
|
||||
for id_str,addr_chk in vectors_multicoin.items():
|
||||
vmsg(fs.format('COIN', 'ADDR_TYPE', 'ADDR'))
|
||||
for id_str, addr_chk in vectors_multicoin.items():
|
||||
ss = id_str.split('_')
|
||||
coin = ss[0]
|
||||
addr_type = ss[1] if len(ss) == 2 else None
|
||||
|
|
@ -317,7 +317,7 @@ class unit_tests:
|
|||
vmsg(gray(fs.format(coin.upper(), (addr_type or ''), '[not supported yet]')))
|
||||
continue
|
||||
vmsg(fs.format(coin.upper(), (addr_type or 'auto'), addr_chk))
|
||||
node = m.to_chain(idx=0,coin=coin,addr_type=addr_type).derive_private(0)
|
||||
node = m.to_chain(idx=0, coin=coin, addr_type=addr_type).derive_private(0)
|
||||
xpub_parsed = node.key_extended(public=True)
|
||||
xprv_parsed = node.key_extended(public=False)
|
||||
addr = node.address
|
||||
|
|
@ -339,19 +339,19 @@ class unit_tests:
|
|||
vmsg('')
|
||||
return True
|
||||
|
||||
def errors(self,name,ut):
|
||||
def errors(self, name, ut):
|
||||
vmsg('Checking error handling:')
|
||||
|
||||
m = MasterNode(cfg,self._seed)
|
||||
m_btc = m.init_cfg(coin='btc',addr_type='bech32')
|
||||
m = MasterNode(cfg, self._seed)
|
||||
m_btc = m.init_cfg(coin='btc', addr_type='bech32')
|
||||
|
||||
purpose = m_btc.derive_private()
|
||||
coin_type = purpose.derive_private()
|
||||
acct = coin_type.derive_private(idx=0)
|
||||
chain = acct.derive_private(idx=0,hardened=False)
|
||||
chain = acct.derive_private(idx=0, hardened=False)
|
||||
|
||||
def bad01():
|
||||
m.to_chain(idx=0,coin='erq',addr_type='C')
|
||||
m.to_chain(idx=0, coin='erq', addr_type='C')
|
||||
def bad02():
|
||||
m_btc.derive_private(idx=0)
|
||||
def bad03():
|
||||
|
|
@ -365,13 +365,13 @@ class unit_tests:
|
|||
def bad08():
|
||||
m_btc.derive_public() # must be private
|
||||
def bad09():
|
||||
coin_type.derive_private(idx=8,hardened=False)
|
||||
coin_type.derive_private(idx=8, hardened=False)
|
||||
def bad10():
|
||||
acct.derive_private()
|
||||
def bad11():
|
||||
chain.derive_private()
|
||||
def bad12():
|
||||
chain.derive_private(hardened=True,idx=3)
|
||||
chain.derive_private(hardened=True, idx=3)
|
||||
|
||||
bad_data = (
|
||||
('unsupported coin', 'ValueError', 'not supported', bad01),
|
||||
|
|
@ -387,14 +387,14 @@ class unit_tests:
|
|||
('depth 5 (leaf node): hardened True', 'ValueError', 'must be None', bad12),
|
||||
)
|
||||
|
||||
ut.process_bad_data(bad_data,pfx='')
|
||||
ut.process_bad_data(bad_data, pfx='')
|
||||
vmsg('')
|
||||
return True
|
||||
|
||||
def parse_extended_errors(self,name,ut):
|
||||
def parse_extended_errors(self, name, ut):
|
||||
vmsg('Parsing and validating invalid extended keys:')
|
||||
vec = vectors_bip32_invalid
|
||||
func = [lambda m=n: BipHDNode.from_extended_key(cfg,'btc',vec[m][0]) for n in range(len(vec))]
|
||||
func = [lambda m=n: BipHDNode.from_extended_key(cfg, 'btc', vec[m][0]) for n in range(len(vec))]
|
||||
exc = (
|
||||
'first byte for public',
|
||||
'first byte for private',
|
||||
|
|
@ -413,6 +413,6 @@ class unit_tests:
|
|||
'Public key could not be parsed', # extmod
|
||||
'incorrect checksum',
|
||||
)
|
||||
ut.process_bad_data([(vec[n][1], 'ValueError', exc[n], func[n]) for n in range(len(vec))],pfx='')
|
||||
ut.process_bad_data([(vec[n][1], 'ValueError', exc[n], func[n]) for n in range(len(vec))], pfx='')
|
||||
vmsg('')
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ class unit_tests:
|
|||
|
||||
def errors(self, name, ut, desc='error handling'):
|
||||
# could do these in objtest.py:
|
||||
def bad1(): a = CoinAddr(proto, self.aliases[0].cashaddr.replace('g','G'))
|
||||
def bad1(): a = CoinAddr(proto, self.aliases[0].cashaddr.replace('g', 'G'))
|
||||
def bad2(): a = CoinAddr(proto, 'x' + self.aliases[0].cashaddr)
|
||||
def bad3(): a = CoinAddr(proto, self.aliases[0].cashaddr[:-1])
|
||||
def bad4(): a = CoinAddr(proto, self.aliases[0].cashaddr[:-1]+'i')
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
test.unit_tests_d.ut_daemon: unit test for the MMGen suite's Daemon class
|
||||
"""
|
||||
|
||||
from subprocess import run,PIPE
|
||||
from subprocess import run, PIPE
|
||||
from collections import namedtuple
|
||||
|
||||
from mmgen.color import orange, red
|
||||
|
|
@ -14,19 +14,19 @@ from mmgen.daemon import CoinDaemon
|
|||
from ..include.common import cfg, qmsg, qmsg_r, vmsg, msg
|
||||
|
||||
def test_flags():
|
||||
d = CoinDaemon(cfg,'eth')
|
||||
vmsg(f'Available opts: {fmt_list(d.avail_opts,fmt="bare")}')
|
||||
vmsg(f'Available flags: {fmt_list(d.avail_flags,fmt="bare")}')
|
||||
vals = namedtuple('vals',['online','no_daemonize','keep_cfg_file'])
|
||||
d = CoinDaemon(cfg, 'eth')
|
||||
vmsg(f'Available opts: {fmt_list(d.avail_opts, fmt="bare")}')
|
||||
vmsg(f'Available flags: {fmt_list(d.avail_flags, fmt="bare")}')
|
||||
vals = namedtuple('vals', ['online', 'no_daemonize', 'keep_cfg_file'])
|
||||
|
||||
def gen():
|
||||
for opts,flags,val in (
|
||||
(None,None, vals(False,False,False)),
|
||||
(None,['keep_cfg_file'], vals(False,False,True)),
|
||||
(['online'],['keep_cfg_file'], vals(True,False,True)),
|
||||
(['online','no_daemonize'],['keep_cfg_file'], vals(True,True,True)),
|
||||
for opts, flags, val in (
|
||||
(None, None, vals(False, False, False)),
|
||||
(None, ['keep_cfg_file'], vals(False, False, True)),
|
||||
(['online'], ['keep_cfg_file'], vals(True, False, True)),
|
||||
(['online', 'no_daemonize'], ['keep_cfg_file'], vals(True, True, True)),
|
||||
):
|
||||
d = CoinDaemon(cfg,'eth',opts=opts,flags=flags)
|
||||
d = CoinDaemon(cfg, 'eth', opts=opts, flags=flags)
|
||||
assert d.flag.keep_cfg_file == val.keep_cfg_file
|
||||
assert d.opt.online == val.online
|
||||
assert d.opt.no_daemonize == val.no_daemonize
|
||||
|
|
@ -36,7 +36,7 @@ def test_flags():
|
|||
|
||||
return tuple(gen())
|
||||
|
||||
def test_flags_err(ut,d):
|
||||
def test_flags_err(ut, d):
|
||||
|
||||
def bad1(): d[0].flag.foo = False
|
||||
def bad2(): d[0].opt.foo = False
|
||||
|
|
@ -47,23 +47,23 @@ def test_flags_err(ut,d):
|
|||
def bad7(): d[1].flag.keep_cfg_file = True
|
||||
|
||||
ut.process_bad_data((
|
||||
('flag (1)', 'ClassFlagsError', 'unrecognized flag', bad1 ),
|
||||
('opt (1)', 'ClassFlagsError', 'unrecognized opt', bad2 ),
|
||||
('opt (2)', 'AttributeError', 'is read-only', bad3 ),
|
||||
('flag (2)', 'AssertionError', 'not boolean', bad4 ),
|
||||
('opt (3)', 'AttributeError', 'is read-only', bad5 ),
|
||||
('flag (3)', 'ClassFlagsError', 'not set', bad6 ),
|
||||
('flag (4)', 'ClassFlagsError', 'already set', bad7 ),
|
||||
('flag (1)', 'ClassFlagsError', 'unrecognized flag', bad1),
|
||||
('opt (1)', 'ClassFlagsError', 'unrecognized opt', bad2),
|
||||
('opt (2)', 'AttributeError', 'is read-only', bad3),
|
||||
('flag (2)', 'AssertionError', 'not boolean', bad4),
|
||||
('opt (3)', 'AttributeError', 'is read-only', bad5),
|
||||
('flag (3)', 'ClassFlagsError', 'not set', bad6),
|
||||
('flag (4)', 'ClassFlagsError', 'already set', bad7),
|
||||
))
|
||||
|
||||
class unit_tests:
|
||||
|
||||
win_skip = ('start','status','stop')
|
||||
win_skip = ('start', 'status', 'stop')
|
||||
|
||||
def _pre(self):
|
||||
self.daemon_ctrl_args = ['btc','btc_tn','btc_rt'] if cfg.no_altcoin_deps else ['all']
|
||||
self.daemon_ctrl_args = ['btc', 'btc_tn', 'btc_rt'] if cfg.no_altcoin_deps else ['all']
|
||||
|
||||
def _test_cmd(self,args_in,message):
|
||||
def _test_cmd(self, args_in, message):
|
||||
qmsg_r(message)
|
||||
args = ['python3', f'test/{args_in[0]}-coin-daemons.py'] + list(args_in[1:]) + self.daemon_ctrl_args
|
||||
vmsg('\n' + orange(f"Running '{' '.join(args)}':"))
|
||||
|
|
@ -77,7 +77,7 @@ class unit_tests:
|
|||
qmsg('OK')
|
||||
return True
|
||||
|
||||
def flags(self,name,ut):
|
||||
def flags(self, name, ut):
|
||||
|
||||
qmsg_r('Testing flags and opts...')
|
||||
vmsg('')
|
||||
|
|
@ -86,22 +86,22 @@ class unit_tests:
|
|||
|
||||
qmsg_r('Testing error handling for flags and opts...')
|
||||
vmsg('')
|
||||
test_flags_err(ut,daemons)
|
||||
test_flags_err(ut, daemons)
|
||||
qmsg('OK')
|
||||
|
||||
return True
|
||||
|
||||
def exec(self,name,ut):
|
||||
return self._test_cmd(['start','-Vm'], 'Testing availability of coin daemons...')
|
||||
def exec(self, name, ut):
|
||||
return self._test_cmd(['start', '-Vm'], 'Testing availability of coin daemons...')
|
||||
|
||||
def cmds(self,name,ut):
|
||||
return self._test_cmd(['start','-t'], 'Testing start commands for coin daemons...')
|
||||
def cmds(self, name, ut):
|
||||
return self._test_cmd(['start', '-t'], 'Testing start commands for coin daemons...')
|
||||
|
||||
def start(self,name,ut):
|
||||
def start(self, name, ut):
|
||||
return self._test_cmd(['start'], 'Starting coin daemons...')
|
||||
|
||||
def status(self,name,ut):
|
||||
def status(self, name, ut):
|
||||
return self._test_cmd(['start'], 'Checking status of coin daemons...')
|
||||
|
||||
def stop(self,name,ut):
|
||||
def stop(self, name, ut):
|
||||
return self._test_cmd(['stop'], 'Stopping coin daemons...')
|
||||
|
|
|
|||
|
|
@ -7,19 +7,19 @@ test.unit_tests_d.ut_dep: dependency unit tests for the MMGen suite
|
|||
No data verification is performed.
|
||||
"""
|
||||
|
||||
from subprocess import run,PIPE
|
||||
from subprocess import run, PIPE
|
||||
|
||||
from mmgen.util import msg,rmsg,ymsg,gmsg
|
||||
from mmgen.util import msg, rmsg, ymsg, gmsg
|
||||
from mmgen.exception import NoLEDSupport
|
||||
|
||||
from ..include.common import cfg,vmsg,check_solc_ver
|
||||
from ..include.common import cfg, vmsg, check_solc_ver
|
||||
|
||||
class unit_tests:
|
||||
|
||||
altcoin_deps = ('py_ecc','solc','keccak','pysocks')
|
||||
altcoin_deps = ('py_ecc', 'solc', 'keccak', 'pysocks')
|
||||
win_skip = ('led',)
|
||||
|
||||
def led(self,name,ut):
|
||||
def led(self, name, ut):
|
||||
from mmgen.led import LEDControl
|
||||
try:
|
||||
LEDControl(enabled=True)
|
||||
|
|
@ -29,7 +29,7 @@ class unit_tests:
|
|||
gmsg('LED support found!')
|
||||
return True
|
||||
|
||||
def keccak(self,name,ut): # used by ETH, XMR
|
||||
def keccak(self, name, ut): # used by ETH, XMR
|
||||
from mmgen.util2 import get_keccak
|
||||
try:
|
||||
get_keccak()
|
||||
|
|
@ -39,12 +39,12 @@ class unit_tests:
|
|||
else:
|
||||
return True
|
||||
|
||||
def py_ecc(self,name,ut): # ETH
|
||||
def py_ecc(self, name, ut): # ETH
|
||||
from py_ecc.secp256k1 import privtopub
|
||||
return True
|
||||
|
||||
def pysocks(self,name,ut):
|
||||
import requests,urllib3
|
||||
def pysocks(self, name, ut):
|
||||
import requests, urllib3
|
||||
urllib3.disable_warnings()
|
||||
session = requests.Session()
|
||||
session.trust_env = False
|
||||
|
|
@ -59,62 +59,62 @@ class unit_tests:
|
|||
msg('Is the ‘pysocks’ package installed?')
|
||||
return False
|
||||
|
||||
def secp256k1(self,name,ut):
|
||||
def secp256k1(self, name, ut):
|
||||
from mmgen.proto.secp256k1.secp256k1 import pubkey_gen
|
||||
pubkey_gen(bytes.fromhex('deadbeef'*8),1)
|
||||
pubkey_gen(bytes.fromhex('deadbeef'*8), 1)
|
||||
return True
|
||||
|
||||
def cryptography(self,name,ut):
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher,algorithms,modes
|
||||
def cryptography(self, name, ut):
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
c = Cipher(algorithms.AES(b'deadbeef'*4),modes.CTR(b'deadbeef'*2),backend=default_backend())
|
||||
c = Cipher(algorithms.AES(b'deadbeef'*4), modes.CTR(b'deadbeef'*2), backend=default_backend())
|
||||
encryptor = c.encryptor()
|
||||
encryptor.update(b'foo') + encryptor.finalize()
|
||||
return True
|
||||
|
||||
def ecdsa(self,name,ut):
|
||||
def ecdsa(self, name, ut):
|
||||
import ecdsa
|
||||
pko = ecdsa.SigningKey.from_secret_exponent(12345678901234,curve=ecdsa.SECP256k1)
|
||||
pko = ecdsa.SigningKey.from_secret_exponent(12345678901234, curve=ecdsa.SECP256k1)
|
||||
pko.get_verifying_key().to_string().hex()
|
||||
return True
|
||||
|
||||
def ripemd160(self,name,ut):
|
||||
def ripemd160(self, name, ut):
|
||||
import hashlib
|
||||
if hashlib.new.__name__ == 'hashlib_new_wrapper':
|
||||
ymsg('Warning: RIPEMD160 missing in hashlib, falling back on pure-Python implementation')
|
||||
hashlib.new('ripemd160')
|
||||
return True
|
||||
|
||||
def gmpy(self,name,ut):
|
||||
from gmpy2 import context,set_context,sqrt,cbrt
|
||||
def gmpy(self, name, ut):
|
||||
from gmpy2 import context, set_context, sqrt, cbrt
|
||||
# context() parameters are platform-dependent!
|
||||
set_context(context(precision=75,round=1)) # OK for gmp 6.1.2 / gmpy 2.1.0
|
||||
set_context(context(precision=75, round=1)) # OK for gmp 6.1.2 / gmpy 2.1.0
|
||||
return True
|
||||
|
||||
def aiohttp(self,name,ut):
|
||||
import asyncio,aiohttp
|
||||
def aiohttp(self, name, ut):
|
||||
import asyncio, aiohttp
|
||||
async def do():
|
||||
async with aiohttp.ClientSession(
|
||||
headers = { 'Content-Type': 'application/json' },
|
||||
headers = {'Content-Type': 'application/json'},
|
||||
connector = aiohttp.TCPConnector(),
|
||||
):
|
||||
pass
|
||||
asyncio.run(do())
|
||||
return True
|
||||
|
||||
def pexpect(self,name,ut):
|
||||
def pexpect(self, name, ut):
|
||||
import pexpect
|
||||
from pexpect.popen_spawn import PopenSpawn
|
||||
return True
|
||||
|
||||
def scrypt(self,name,ut):
|
||||
passwd,salt = b'foo',b'bar'
|
||||
N,r,p = 4,8,16
|
||||
def scrypt(self, name, ut):
|
||||
passwd, salt = b'foo', b'bar'
|
||||
N, r, p = 4, 8, 16
|
||||
buflen = 64
|
||||
|
||||
vmsg('Testing builtin scrypt module (hashlib)')
|
||||
from hashlib import scrypt # max N == 14!!
|
||||
scrypt(password=passwd,salt=salt,n=2**N,r=r,p=p,maxmem=0,dklen=buflen)
|
||||
scrypt(password=passwd, salt=salt, n=2**N, r=r, p=p, maxmem=0, dklen=buflen)
|
||||
|
||||
vmsg('Testing standalone scrypt module')
|
||||
import scrypt
|
||||
|
|
@ -122,7 +122,7 @@ class unit_tests:
|
|||
|
||||
return True
|
||||
|
||||
def solc(self,name,ut):
|
||||
def solc(self, name, ut):
|
||||
from mmgen.protocol import init_proto
|
||||
solc_ok = check_solc_ver()
|
||||
if solc_ok:
|
||||
|
|
@ -135,9 +135,9 @@ class unit_tests:
|
|||
'--supply=100000000000000000000000000',
|
||||
'--decimals=18',
|
||||
'--stdout',
|
||||
init_proto( cfg, 'eth' ).checksummed_addr('deadbeef'*5),
|
||||
init_proto(cfg, 'eth').checksummed_addr('deadbeef'*5),
|
||||
]
|
||||
cp = run(cmd,stdout=PIPE,stderr=PIPE)
|
||||
cp = run(cmd, stdout=PIPE, stderr=PIPE)
|
||||
vmsg(cp.stderr.decode())
|
||||
if cp.returncode:
|
||||
msg(cp.stderr.decode())
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
test.unit_tests_d.ut_devtools: devtools unit tests for the MMGen suite
|
||||
"""
|
||||
|
||||
import os,json
|
||||
import os, json
|
||||
from mmgen.util import msg
|
||||
from mmgen.devtools import print_diff,get_ndiff,print_stack_trace,pmsg_r,pmsg,Pmsg
|
||||
from mmgen.devtools import print_diff, get_ndiff, print_stack_trace, pmsg_r, pmsg, Pmsg
|
||||
from . import unit_tests_base
|
||||
|
||||
textA = """
|
||||
|
|
@ -47,34 +47,34 @@ def print_hdr(hdr):
|
|||
print('{a} {b} {c}'.format(
|
||||
a = '-' * ((78 - len(hdr))//2),
|
||||
b = hdr,
|
||||
c = '-' * ((78 - len(hdr))//2 + (len(hdr) % 2)) ))
|
||||
c = '-' * ((78 - len(hdr))//2 + (len(hdr) % 2))))
|
||||
|
||||
# TODO: add data checks
|
||||
class unit_tests(unit_tests_base):
|
||||
|
||||
silence_output = True
|
||||
|
||||
def _post_subtest(self,name,subname,ut):
|
||||
def _post_subtest(self, name, subname, ut):
|
||||
print('-' * 80 + '\n')
|
||||
|
||||
def diff(self,name,ut):
|
||||
def diff(self, name, ut):
|
||||
for data in text_data + json_data:
|
||||
print_hdr(data[-1])
|
||||
print_diff(*data[:-1])
|
||||
return True
|
||||
|
||||
def ndiff(self,name,ut):
|
||||
def ndiff(self, name, ut):
|
||||
for data in text_data:
|
||||
print_hdr(data[-1])
|
||||
print('\n'.join(get_ndiff(*data[:2])))
|
||||
return True
|
||||
|
||||
def stack_trace(self,name,ut):
|
||||
def stack_trace(self, name, ut):
|
||||
print_hdr('stack trace')
|
||||
print_stack_trace('Test',fh_list=[open(os.devnull,'w')],trim=0)
|
||||
print_stack_trace('Test', fh_list=[open(os.devnull, 'w')], trim=0)
|
||||
return True
|
||||
|
||||
def obj_pmsg(self,name,ut):
|
||||
def obj_pmsg(self, name, ut):
|
||||
from mmgen.protocol import init_proto
|
||||
from mmgen.seed import Seed
|
||||
from mmgen.addrlist import AddrList
|
||||
|
|
@ -82,26 +82,26 @@ class unit_tests(unit_tests_base):
|
|||
print_hdr('MMGenObject.pmsg()')
|
||||
AddrList(
|
||||
cfg = cfg,
|
||||
proto = init_proto( cfg, 'btc' ),
|
||||
seed = Seed(cfg,seed_bin=bytes.fromhex('bead'*16)),
|
||||
proto = init_proto(cfg, 'btc'),
|
||||
seed = Seed(cfg, seed_bin=bytes.fromhex('bead'*16)),
|
||||
addr_idxs = '1',
|
||||
mmtype = 'B',
|
||||
skip_chksum = True ).pmsg(color='green')
|
||||
skip_chksum = True).pmsg(color='green')
|
||||
return True
|
||||
|
||||
def pmsg(self,name,ut):
|
||||
colors = (None,'red','green','yellow','blue','purple')
|
||||
def pmsg(self, name, ut):
|
||||
colors = (None, 'red', 'green', 'yellow', 'blue', 'purple')
|
||||
|
||||
msg('\npmsg_r():')
|
||||
for color in colors:
|
||||
pmsg_r({'color':color},color=color)
|
||||
pmsg_r({'color':color}, color=color)
|
||||
|
||||
msg('\n\npmsg():')
|
||||
for color in colors:
|
||||
pmsg({'color':color},color=color)
|
||||
pmsg({'color':color}, color=color)
|
||||
|
||||
msg('\nPmsg():')
|
||||
for color in colors:
|
||||
Pmsg({'color':color},color=color)
|
||||
Pmsg({'color':color}, color=color)
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
test.unit_tests_d.ut_ecc: elliptic curve unit test for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.proto.secp256k1.secp256k1 import pubkey_gen,pubkey_tweak_add,pubkey_check
|
||||
from mmgen.proto.secp256k1.secp256k1 import pubkey_gen, pubkey_tweak_add, pubkey_check
|
||||
|
||||
from ..include.common import vmsg
|
||||
from ..include.ecc import pubkey_tweak_add_pyecdsa
|
||||
|
|
@ -14,9 +14,9 @@ secp256k1_group_order = CoinProtocol.Secp256k1.secp256k1_group_order
|
|||
|
||||
class unit_tests:
|
||||
|
||||
def pubkey_ops(self,name,ut):
|
||||
def pubkey_ops(self, name, ut):
|
||||
vmsg(' Generating pubkey, adding scalar 123456789 to pubkey:')
|
||||
pk_addend_bytes = int.to_bytes(123456789,length=32,byteorder='big')
|
||||
pk_addend_bytes = int.to_bytes(123456789, length=32, byteorder='big')
|
||||
|
||||
for privkey in (
|
||||
'beadcafe' * 8,
|
||||
|
|
@ -24,9 +24,9 @@ class unit_tests:
|
|||
f'{secp256k1_group_order-1:x}',
|
||||
):
|
||||
vmsg(f' privkey = 0x{privkey}')
|
||||
for compressed,length in ((False,65),(True,33)):
|
||||
for compressed, length in ((False, 65), (True, 33)):
|
||||
vmsg(f' {compressed=}')
|
||||
pubkey_bytes = pubkey_gen(bytes.fromhex(privkey),int(compressed))
|
||||
pubkey_bytes = pubkey_gen(bytes.fromhex(privkey), int(compressed))
|
||||
pubkey_check(pubkey_bytes)
|
||||
vmsg(f' pubkey: {pubkey_bytes.hex()}')
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ class unit_tests:
|
|||
pubkey_check(res1)
|
||||
vmsg(f' tweaked: {res1.hex()}')
|
||||
|
||||
res2 = pubkey_tweak_add_pyecdsa(pubkey_bytes,pk_addend_bytes)
|
||||
res2 = pubkey_tweak_add_pyecdsa(pubkey_bytes, pk_addend_bytes)
|
||||
pubkey_check(res2)
|
||||
|
||||
assert len(res1) == length
|
||||
|
|
@ -42,18 +42,18 @@ class unit_tests:
|
|||
|
||||
return True
|
||||
|
||||
def pubkey_errors(self,name,ut):
|
||||
def pubkey_errors(self, name, ut):
|
||||
|
||||
def gen1(): pubkey_gen(bytes(32),1)
|
||||
def gen2(): pubkey_gen(secp256k1_group_order.to_bytes(length=32,byteorder='big'),1)
|
||||
def gen3(): pubkey_gen((secp256k1_group_order+1).to_bytes(length=32,byteorder='big'),1)
|
||||
def gen4(): pubkey_gen(bytes.fromhex('ff'*32),1)
|
||||
def gen5(): pubkey_gen(bytes.fromhex('ab'*31),1)
|
||||
def gen6(): pubkey_gen(bytes.fromhex('ab'*33),1)
|
||||
def gen1(): pubkey_gen(bytes(32), 1)
|
||||
def gen2(): pubkey_gen(secp256k1_group_order.to_bytes(length=32, byteorder='big'), 1)
|
||||
def gen3(): pubkey_gen((secp256k1_group_order+1).to_bytes(length=32, byteorder='big'), 1)
|
||||
def gen4(): pubkey_gen(bytes.fromhex('ff'*32), 1)
|
||||
def gen5(): pubkey_gen(bytes.fromhex('ab'*31), 1)
|
||||
def gen6(): pubkey_gen(bytes.fromhex('ab'*33), 1)
|
||||
|
||||
pubkey_bytes = pubkey_gen(bytes.fromhex('beadcafe'*8), 1)
|
||||
def tweak1(): pubkey_tweak_add(pubkey_bytes,bytes(32))
|
||||
def tweak2(): pubkey_tweak_add(bytes.fromhex('03'*64),int.to_bytes(1,length=32,byteorder='big'))
|
||||
def tweak1(): pubkey_tweak_add(pubkey_bytes, bytes(32))
|
||||
def tweak2(): pubkey_tweak_add(bytes.fromhex('03'*64), int.to_bytes(1, length=32, byteorder='big'))
|
||||
|
||||
def check1(): pubkey_check(bytes.fromhex('04'*33))
|
||||
def check2(): pubkey_check(bytes.fromhex('03'*65))
|
||||
|
|
@ -79,5 +79,5 @@ class unit_tests:
|
|||
('pubkey length == 0', 'ValueError', 'Serialized public key length not', check5),
|
||||
)
|
||||
|
||||
ut.process_bad_data(bad_data,pfx='')
|
||||
ut.process_bad_data(bad_data, pfx='')
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
test.unit_tests_d.ut_flags: unit test for the MMGen suite's ClassFlags class
|
||||
"""
|
||||
|
||||
from mmgen.flags import ClassOpts,ClassFlags
|
||||
from mmgen.flags import ClassOpts, ClassFlags
|
||||
|
||||
from ..include.common import qmsg,qmsg_r,vmsg
|
||||
from ..include.common import qmsg, qmsg_r, vmsg
|
||||
|
||||
class unit_test:
|
||||
|
||||
def run_test(self,name,ut):
|
||||
def run_test(self, name, ut):
|
||||
|
||||
class MyClassOpts(ClassOpts):
|
||||
reserved_attrs = ('foo',)
|
||||
|
|
@ -18,12 +18,12 @@ class unit_test:
|
|||
class cls1:
|
||||
avail_opts = ()
|
||||
avail_flags = ()
|
||||
def __init__(self,opts=None,flags=None):
|
||||
self.opt = ClassOpts(self,opts)
|
||||
self.flag = ClassFlags(self,flags)
|
||||
def __init__(self, opts=None, flags=None):
|
||||
self.opt = ClassOpts(self, opts)
|
||||
self.flag = ClassFlags(self, flags)
|
||||
|
||||
class cls2(cls1):
|
||||
avail_opts = ('foo','bar')
|
||||
avail_opts = ('foo', 'bar')
|
||||
avail_flags = ('baz',)
|
||||
|
||||
class cls3(cls1):
|
||||
|
|
@ -31,20 +31,20 @@ class unit_test:
|
|||
|
||||
class cls4(cls1):
|
||||
avail_opts = ('foo',)
|
||||
def __init__(self,opts=None,flags=None):
|
||||
self.opt = MyClassOpts(self,opts)
|
||||
def __init__(self, opts=None, flags=None):
|
||||
self.opt = MyClassOpts(self, opts)
|
||||
|
||||
def test_flags():
|
||||
def gen():
|
||||
for n,cls in enumerate((
|
||||
for n, cls in enumerate((
|
||||
cls1(),
|
||||
cls2(),
|
||||
cls2(opts=['bar']),
|
||||
cls2(flags=['baz']),
|
||||
)):
|
||||
vmsg(f'Cfg {n+1}:')
|
||||
for k in ('opt','flag'):
|
||||
vmsg(f' {k}s: {getattr(cls,k)}')
|
||||
for k in ('opt', 'flag'):
|
||||
vmsg(f' {k}s: {getattr(cls, k)}')
|
||||
yield cls
|
||||
return list(gen())
|
||||
|
||||
|
|
@ -61,15 +61,15 @@ class unit_test:
|
|||
def bad9(): d[1].flag.baz = 'x'
|
||||
|
||||
ut.process_bad_data((
|
||||
('flag (1)', 'ClassFlagsError', 'unrecognized flag', bad1 ),
|
||||
('opt (1)', 'ClassFlagsError', 'unrecognized opt', bad2 ),
|
||||
('avail_opts (1)', 'ClassFlagsError', 'underscore', bad3 ),
|
||||
('avail_opts (2)', 'ClassFlagsError', 'reserved name', bad4 ),
|
||||
('class invocation (1)', 'AssertionError', 'list or tuple', bad5 ),
|
||||
('class invocation (2)', 'ClassFlagsError', 'unrecognized opt', bad6 ),
|
||||
('flag (2)', 'ClassFlagsError', 'not set', bad7 ),
|
||||
('flag (3)', 'ClassFlagsError', 'already set', bad8 ),
|
||||
('flag (4)', 'AssertionError', 'not boolean', bad9 ),
|
||||
('flag (1)', 'ClassFlagsError', 'unrecognized flag', bad1),
|
||||
('opt (1)', 'ClassFlagsError', 'unrecognized opt', bad2),
|
||||
('avail_opts (1)', 'ClassFlagsError', 'underscore', bad3),
|
||||
('avail_opts (2)', 'ClassFlagsError', 'reserved name', bad4),
|
||||
('class invocation (1)', 'AssertionError', 'list or tuple', bad5),
|
||||
('class invocation (2)', 'ClassFlagsError', 'unrecognized opt', bad6),
|
||||
('flag (2)', 'ClassFlagsError', 'not set', bad7),
|
||||
('flag (3)', 'ClassFlagsError', 'already set', bad8),
|
||||
('flag (4)', 'AssertionError', 'not boolean', bad9),
|
||||
))
|
||||
|
||||
qmsg_r('Testing flags and opts...')
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ from mmgen.color import blue
|
|||
from mmgen.protocol import init_proto
|
||||
from mmgen.key import PrivKey
|
||||
from mmgen.addr import MMGenAddrType
|
||||
from mmgen.addrgen import KeyGenerator,AddrGenerator
|
||||
from mmgen.addrgen import KeyGenerator, AddrGenerator
|
||||
from mmgen.keygen import get_backends
|
||||
|
||||
from ..include.common import cfg,qmsg
|
||||
from ..include.common import cfg, qmsg
|
||||
|
||||
# TODO: add viewkey checks
|
||||
vectors = { # from tooltest2
|
||||
'btc': ( (
|
||||
'btc': ((
|
||||
'5HwzecKMWD82ppJK3qMKpC7ohXXAwcyAN5VgdJ9PLFaAzpBG4sX',
|
||||
'1C5VPtgq9xQ6AcTgMAR3J6GDrs72HC4pS1',
|
||||
'legacy'
|
||||
|
|
@ -30,26 +30,26 @@ vectors = { # from tooltest2
|
|||
), (
|
||||
'KwojSzt1VvW343mQfWQi3J537siAt5ktL2qbuCg1ZyKR8BLQ6UJm',
|
||||
'bc1q6pqnfwwakuuejpm9w52ds342f9d5u36v0qnz7c',
|
||||
'bech32' ),
|
||||
'bech32'),
|
||||
),
|
||||
'eth': ( (
|
||||
'eth': ((
|
||||
'0000000000000000000000000000000000000000000000000000000000000001',
|
||||
'7e5f4552091a69125d5dfcb7b8c2659029395bdf',
|
||||
'ethereum',
|
||||
), ),
|
||||
'xmr': ( (
|
||||
),),
|
||||
'xmr': ((
|
||||
'0000000000000000000000000000000000000000000000000000000000000001',
|
||||
'42nsXK8WbVGTNayQ6Kjw5UdgqbQY5KCCufdxdCgF7NgTfjC69Mna7DJSYyie77hZTQ8H92G2HwgFhgEUYnDzrnLnQdF28r3',
|
||||
'monero',
|
||||
), ),
|
||||
'zec': ( (
|
||||
),),
|
||||
'zec': ((
|
||||
'SKxny894fJe2rmZjeuoE6GVfNkWoXfPp8337VrLLNWG56FjqVUYR',
|
||||
'zceQDpyNwek7dKqF5ZuFGj7YrNVxh7X1aPkrVxDLVxWSiZAFDEuy5C7XNV8VhyZ3ghTPQ61xjCGiyLT3wqpiN1Yi6mdmaCq',
|
||||
'zcash_z',
|
||||
), ),
|
||||
),),
|
||||
}
|
||||
|
||||
def do_test(proto,wif,addr_chk,addr_type,internal_keccak):
|
||||
def do_test(proto, wif, addr_chk, addr_type, internal_keccak):
|
||||
|
||||
if internal_keccak:
|
||||
cfg.use_internal_keccak_module = True
|
||||
|
|
@ -57,21 +57,21 @@ def do_test(proto,wif,addr_chk,addr_type,internal_keccak):
|
|||
else:
|
||||
add_msg = ''
|
||||
|
||||
at = MMGenAddrType(proto,addr_type)
|
||||
privkey = PrivKey(proto,wif=wif)
|
||||
at = MMGenAddrType(proto, addr_type)
|
||||
privkey = PrivKey(proto, wif=wif)
|
||||
|
||||
for n,backend in enumerate(get_backends(at.pubkey_type)):
|
||||
for n, backend in enumerate(get_backends(at.pubkey_type)):
|
||||
|
||||
kg = KeyGenerator( cfg, proto, at.pubkey_type, n+1 )
|
||||
kg = KeyGenerator( cfg, proto, at.pubkey_type, n+1)
|
||||
qmsg(blue(f' Testing backend {backend!r} for addr type {addr_type!r}{add_msg}'))
|
||||
|
||||
data = kg.gen_data(privkey)
|
||||
|
||||
for k,v in data._asdict().items():
|
||||
if v and k in ('pubkey','viewkey_bytes'):
|
||||
for k, v in data._asdict().items():
|
||||
if v and k in ('pubkey', 'viewkey_bytes'):
|
||||
qmsg(f' {k+":":19} {v.hex()}')
|
||||
|
||||
ag = AddrGenerator( cfg, proto, addr_type )
|
||||
ag = AddrGenerator( cfg, proto, addr_type)
|
||||
addr = ag.to_addr(data)
|
||||
qmsg(f' addr: {addr}\n')
|
||||
|
||||
|
|
@ -79,27 +79,27 @@ def do_test(proto,wif,addr_chk,addr_type,internal_keccak):
|
|||
|
||||
cfg.use_internal_keccak_module = False
|
||||
|
||||
def do_tests(coin,internal_keccak=False):
|
||||
proto = init_proto( cfg, coin )
|
||||
for wif,addr,addr_type in vectors[coin]:
|
||||
do_test(proto,wif,addr,addr_type,internal_keccak)
|
||||
def do_tests(coin, internal_keccak=False):
|
||||
proto = init_proto( cfg, coin)
|
||||
for wif, addr, addr_type in vectors[coin]:
|
||||
do_test(proto, wif, addr, addr_type, internal_keccak)
|
||||
return True
|
||||
|
||||
class unit_tests:
|
||||
|
||||
altcoin_deps = ('eth','xmr','zec')
|
||||
altcoin_deps = ('eth', 'xmr', 'zec')
|
||||
|
||||
def btc(self,name,ut):
|
||||
def btc(self, name, ut):
|
||||
return do_tests('btc')
|
||||
|
||||
def eth(self,name,ut):
|
||||
def eth(self, name, ut):
|
||||
do_tests('eth')
|
||||
return do_tests('eth',internal_keccak=True)
|
||||
return do_tests('eth', internal_keccak=True)
|
||||
|
||||
def xmr(self,name,ut):
|
||||
def xmr(self, name, ut):
|
||||
if not cfg.fast:
|
||||
do_tests('xmr')
|
||||
return do_tests('xmr',internal_keccak=True)
|
||||
return do_tests('xmr', internal_keccak=True)
|
||||
|
||||
def zec(self,name,ut):
|
||||
def zec(self, name, ut):
|
||||
return do_tests('zec')
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
test/unit_tests_d/ut_indexed_dict: IndexedDict class unit test for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.util import msg,msg_r,die
|
||||
from mmgen.util import msg, msg_r, die
|
||||
|
||||
from ..include.common import vmsg
|
||||
|
||||
class unit_test:
|
||||
|
||||
def run_test(self,name,ut):
|
||||
def run_test(self, name, ut):
|
||||
bad_msg = (
|
||||
'initializing values via constructor',
|
||||
'reassignment to existing key',
|
||||
|
|
@ -25,7 +25,7 @@ class unit_test:
|
|||
def bad4(): d.clear()
|
||||
def bad5(): d.update(d)
|
||||
|
||||
def odie(n): die(4,f'\nillegal action {bad_msg[n]!r} failed to raise exception')
|
||||
def odie(n): die(4, f'\nillegal action {bad_msg[n]!r} failed to raise exception')
|
||||
def omsg(e): vmsg(' - ' + e.args[0])
|
||||
|
||||
msg_r('Testing class IndexedDict...')
|
||||
|
|
@ -38,7 +38,7 @@ class unit_test:
|
|||
|
||||
vmsg('\nChecking error handling:')
|
||||
|
||||
arg = [('a',1),('b',2)]
|
||||
arg = [('a', 1), ('b', 2)]
|
||||
dict(arg)
|
||||
|
||||
for n, func in enumerate([bad0, bad1, bad2, bad3, bad4, bad5]):
|
||||
|
|
@ -58,10 +58,10 @@ class unit_test:
|
|||
|
||||
d['c'] = 3
|
||||
|
||||
d_chk = {'a':1,'b':2,'c':3}
|
||||
d_chk = {'a':1, 'b':2, 'c':3}
|
||||
assert d == d_chk, d
|
||||
|
||||
d_keys_chk = ['a','b','c']
|
||||
d_keys_chk = ['a', 'b', 'c']
|
||||
assert d.keys == d_keys_chk, d.keys
|
||||
|
||||
A = d.key(0)
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ class unit_tests:
|
|||
|
||||
class MyLockable(Lockable): # class without attrs
|
||||
_autolock = False
|
||||
_set_ok = ('foo','baz','alpha','beta','gamma','delta','epsilon')
|
||||
_reset_ok = ('bar','baz')
|
||||
_set_ok = ('foo', 'baz', 'alpha', 'beta', 'gamma', 'delta', 'epsilon')
|
||||
_reset_ok = ('bar', 'baz')
|
||||
|
||||
lc = MyLockable()
|
||||
lc.foo = None
|
||||
|
|
@ -121,8 +121,8 @@ class unit_tests:
|
|||
class MyLockableClsCheck(Lockable): # class with attrs
|
||||
_autolock = False
|
||||
_use_class_attr = True
|
||||
_set_ok = ('foo','baz')
|
||||
_reset_ok = ('bar','baz')
|
||||
_set_ok = ('foo', 'baz')
|
||||
_reset_ok = ('bar', 'baz')
|
||||
foo = None
|
||||
bar = 1
|
||||
baz = 3.5
|
||||
|
|
@ -171,7 +171,7 @@ class unit_tests:
|
|||
assert lcdn.bar is None
|
||||
|
||||
class MyLockableBad(Lockable):
|
||||
_set_ok = ('foo','bar')
|
||||
_set_ok = ('foo', 'bar')
|
||||
foo = 1
|
||||
|
||||
def bad1(): lca.foo = None
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ class unit_tests:
|
|||
vs = namedtuple('vector_data', ['text', 'groups'])
|
||||
fs = '{:16} {}'
|
||||
|
||||
vmsg(blue(' ' + fs.format('ID','ANNOT')))
|
||||
for k,v in uarg_info.items():
|
||||
vmsg(blue(' ' + fs.format('ID', 'ANNOT')))
|
||||
for k, v in uarg_info.items():
|
||||
vmsg(' ' + fs.format(k, v[0]))
|
||||
|
||||
vectors = {
|
||||
|
|
@ -81,7 +81,7 @@ class unit_tests:
|
|||
}
|
||||
|
||||
vmsg('')
|
||||
for k,v in uarg_info.items():
|
||||
for k, v in uarg_info.items():
|
||||
vmsg(f' {k}')
|
||||
if k in vectors:
|
||||
vmsg(f' pat: {v.pat}')
|
||||
|
|
@ -96,17 +96,17 @@ class unit_tests:
|
|||
return True
|
||||
|
||||
def pyversion(self, name, ut, desc='class pyversion.PythonVersion'):
|
||||
from mmgen.pyversion import PythonVersion,python_version
|
||||
from mmgen.pyversion import PythonVersion, python_version
|
||||
|
||||
ver = {}
|
||||
fs = '{:<7} {:<9} {:<5} {}'
|
||||
vmsg('\n' + fs.format('Version','PyVersion','Major','Minor'))
|
||||
vmsg('\n' + fs.format('Version', 'PyVersion', 'Major', 'Minor'))
|
||||
|
||||
for k in ('current','3.3','3.12','4.3','7.0'):
|
||||
for k in ('current', '3.3', '3.12', '4.3', '7.0'):
|
||||
obj = python_version if k == 'current' else PythonVersion(k)
|
||||
major,minor = [int(s) for s in obj.split('.')]
|
||||
major, minor = [int(s) for s in obj.split('.')]
|
||||
assert obj.major == major and obj.minor == minor
|
||||
vmsg(fs.format(k.upper(),obj,major,minor))
|
||||
vmsg(fs.format(k.upper(), obj, major, minor))
|
||||
ver[k] = obj
|
||||
|
||||
vmsg('\nPerforming comparison tests:')
|
||||
|
|
|
|||
|
|
@ -13,37 +13,40 @@ class unit_tests:
|
|||
'mmgen': {
|
||||
'usl': 10, 'sw': 3, 'lw': 12,
|
||||
'idx_minimal': ( # None: non-unique match. False: no match
|
||||
('a', None),
|
||||
('aa', False),
|
||||
('as', None),
|
||||
('ask', 70),
|
||||
('afte', None),
|
||||
('after', None),
|
||||
('aftern', 20),
|
||||
('afternoon', 20),
|
||||
('afternoons',False),
|
||||
('g', None),
|
||||
('gg', False),
|
||||
('z', False),
|
||||
('abi', False),
|
||||
('abo', None),
|
||||
('abl', 0),
|
||||
('able', 0),
|
||||
('abler', False),
|
||||
('you', None),
|
||||
('yout', 1625),
|
||||
('youth', 1625),
|
||||
('youths', False),
|
||||
('a', None),
|
||||
('aa', False),
|
||||
('as', None),
|
||||
('ask', 70),
|
||||
('afte', None),
|
||||
('after', None),
|
||||
('aftern', 20),
|
||||
('afternoon', 20),
|
||||
('afternoons', False),
|
||||
('g', None),
|
||||
('gg', False),
|
||||
('z', False),
|
||||
('abi', False),
|
||||
('abo', None),
|
||||
('abl', 0),
|
||||
('able', 0),
|
||||
('abler', False),
|
||||
('you', None),
|
||||
('yout', 1625),
|
||||
('youth', 1625),
|
||||
('youths', False),
|
||||
),
|
||||
},
|
||||
'xmrseed': { 'usl': 3, 'sw': 4, 'lw': 12 },
|
||||
'bip39': { 'usl': 4, 'sw': 3, 'lw': 8 },
|
||||
'xmrseed': {'usl': 3, 'sw': 4, 'lw': 12},
|
||||
'bip39': {'usl': 4, 'sw': 3, 'lw': 8},
|
||||
}
|
||||
|
||||
def wl(self, name, ut, desc='MnemonicEntry - computed wordlist constants'):
|
||||
for wl_id in self.vectors:
|
||||
for j,k in (('uniq_ss_len','usl'),('shortest_word','sw'),('longest_word','lw')):
|
||||
a = getattr(mn_entry( cfg, wl_id ),j)
|
||||
for j, k in (
|
||||
('uniq_ss_len', 'usl'),
|
||||
('shortest_word', 'sw'),
|
||||
('longest_word', 'lw')):
|
||||
a = getattr(mn_entry(cfg, wl_id), j)
|
||||
b = self.vectors[wl_id][k]
|
||||
assert a == b, f'{wl_id}:{j} {a} != {b}'
|
||||
return True
|
||||
|
|
@ -51,24 +54,24 @@ class unit_tests:
|
|||
def idx(self, name, ut, desc='MnemonicEntry - idx()'):
|
||||
junk = 'a g z aa gg zz aaa ggg zzz aaaa gggg zzzz aaaaaaaaaaaaaa gggggggggggggg zzzzzzzzzzzzzz'
|
||||
for wl_id in self.vectors:
|
||||
m = mn_entry( cfg, wl_id )
|
||||
m = mn_entry(cfg, wl_id)
|
||||
vmsg('Wordlist: '+wl_id)
|
||||
for entry_mode in ('full','short'):
|
||||
for a,word in enumerate(m.wl):
|
||||
b = m.idx(word,entry_mode)
|
||||
for entry_mode in ('full', 'short'):
|
||||
for a, word in enumerate(m.wl):
|
||||
b = m.idx(word, entry_mode)
|
||||
assert a == b, f'{a} != {b} ({word!r} - entry mode: {entry_mode!r})'
|
||||
a = None
|
||||
for word in junk.split():
|
||||
b = m.idx(word,entry_mode)
|
||||
b = m.idx(word, entry_mode)
|
||||
assert a == b, f'{a} != {b} ({word!r} - entry mode: {entry_mode!r})'
|
||||
if 'idx_minimal' in self.vectors[wl_id]:
|
||||
for vec in self.vectors[wl_id]['idx_minimal']:
|
||||
chk = vec[1]
|
||||
b = m.idx(vec[0],'minimal')
|
||||
b = m.idx(vec[0], 'minimal')
|
||||
if chk is False:
|
||||
assert b is None, (b,None)
|
||||
assert b is None, (b, None)
|
||||
elif chk is None:
|
||||
assert type(b) is tuple, (type(b),tuple)
|
||||
assert type(b) is tuple, (type(b), tuple)
|
||||
elif type(chk) is int:
|
||||
assert b == chk, (b,chk)
|
||||
assert b == chk, (b, chk)
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import os
|
|||
|
||||
from mmgen.util import msg, pumsg, suf
|
||||
from mmgen.protocol import CoinProtocol
|
||||
from mmgen.msg import NewMsg,UnsignedMsg,SignedMsg,SignedOnlineMsg,ExportedMsgSigs
|
||||
from mmgen.msg import NewMsg, UnsignedMsg, SignedMsg, SignedOnlineMsg, ExportedMsgSigs
|
||||
from mmgen.addr import MMGenID
|
||||
|
||||
from ..include.common import cfg,silence,end_silence,restart_test_daemons,stop_test_daemons
|
||||
from ..include.common import cfg, silence, end_silence, restart_test_daemons, stop_test_daemons
|
||||
|
||||
def get_obj(coin,network,msghash_type):
|
||||
def get_obj(coin, network, msghash_type):
|
||||
|
||||
if coin == 'bch':
|
||||
addrlists = 'DEADBEEF:C:1-20 98831F3A:C:8,2 A091ABAA:L:111 A091ABAA:C:1'
|
||||
|
|
@ -29,85 +29,85 @@ def get_obj(coin,network,msghash_type):
|
|||
network = network,
|
||||
message = '08/Jun/2021 Bitcoin Law Enacted by El Salvador Legislative Assembly',
|
||||
addrlists = addrlists,
|
||||
msghash_type = msghash_type )
|
||||
msghash_type = msghash_type)
|
||||
|
||||
def print_total(n):
|
||||
msg(f'{n} signature{suf(n)} verified')
|
||||
|
||||
async def run_test(network_id,chksum,msghash_type='raw'):
|
||||
async def run_test(network_id, chksum, msghash_type='raw'):
|
||||
|
||||
coin,network = CoinProtocol.Base.parse_network_id(network_id)
|
||||
coin, network = CoinProtocol.Base.parse_network_id(network_id)
|
||||
|
||||
if not cfg.verbose:
|
||||
silence()
|
||||
|
||||
m = get_obj(coin,network,msghash_type)
|
||||
m = get_obj(coin, network, msghash_type)
|
||||
|
||||
if m.proto.sign_mode == 'daemon':
|
||||
restart_test_daemons(network_id)
|
||||
|
||||
pumsg('\nTesting data creation:\n')
|
||||
|
||||
tmpdir = os.path.join('test','trash2')
|
||||
tmpdir = os.path.join('test', 'trash2')
|
||||
|
||||
os.makedirs(tmpdir,exist_ok=True)
|
||||
os.makedirs(tmpdir, exist_ok=True)
|
||||
|
||||
assert m.chksum.upper() == chksum, f'{m.chksum.upper()} != {chksum}'
|
||||
|
||||
m.write_to_file(
|
||||
outdir = tmpdir,
|
||||
ask_overwrite = False )
|
||||
ask_overwrite = False)
|
||||
|
||||
pumsg('\nTesting signing:\n')
|
||||
|
||||
m = UnsignedMsg( cfg, infile = os.path.join(tmpdir,get_obj(coin,network,msghash_type).filename) )
|
||||
m = UnsignedMsg(cfg, infile = os.path.join(tmpdir, get_obj(coin, network, msghash_type).filename))
|
||||
await m.sign(wallet_files=['test/ref/98831F3A.mmwords'])
|
||||
|
||||
m = SignedMsg( cfg, data=m.__dict__ )
|
||||
m = SignedMsg(cfg, data=m.__dict__)
|
||||
m.write_to_file(
|
||||
outdir = tmpdir,
|
||||
ask_overwrite = False )
|
||||
ask_overwrite = False)
|
||||
|
||||
pumsg('\nTesting display:\n')
|
||||
|
||||
m = SignedOnlineMsg( cfg, infile = os.path.join(tmpdir,get_obj(coin,network,msghash_type).signed_filename) )
|
||||
m = SignedOnlineMsg(cfg, infile = os.path.join(tmpdir, get_obj(coin, network, msghash_type).signed_filename))
|
||||
|
||||
msg(m.format())
|
||||
|
||||
single_addr = 'A091ABAA:E:111' if m.proto.base_proto == 'Ethereum' else 'A091ABAA:111'
|
||||
single_addr_coin = m.sigs[MMGenID(m.proto,single_addr)]['addr']
|
||||
single_addr_coin = m.sigs[MMGenID(m.proto, single_addr)]['addr']
|
||||
|
||||
pumsg('\nTesting single address display:\n')
|
||||
msg(m.format(single_addr))
|
||||
|
||||
pumsg('\nTesting verification:\n')
|
||||
print_total( await m.verify() )
|
||||
print_total(await m.verify())
|
||||
|
||||
pumsg('\nTesting single address verification:\n')
|
||||
print_total( await m.verify(single_addr) )
|
||||
print_total(await m.verify(single_addr))
|
||||
|
||||
pumsg('\nTesting JSON dump for export:\n')
|
||||
msg( m.get_json_for_export() )
|
||||
msg(m.get_json_for_export())
|
||||
|
||||
pumsg('\nTesting single address JSON dump for export:\n')
|
||||
msg( m.get_json_for_export(single_addr) )
|
||||
msg(m.get_json_for_export(single_addr))
|
||||
|
||||
from mmgen.fileutil import write_data_to_file
|
||||
exported_sigs = os.path.join(tmpdir,'signatures.json')
|
||||
exported_sigs = os.path.join(tmpdir, 'signatures.json')
|
||||
write_data_to_file(
|
||||
cfg = cfg,
|
||||
outfile = exported_sigs,
|
||||
data = m.get_json_for_export(),
|
||||
desc = 'signature data',
|
||||
ask_overwrite = False )
|
||||
ask_overwrite = False)
|
||||
|
||||
m = ExportedMsgSigs( cfg, infile=exported_sigs )
|
||||
m = ExportedMsgSigs(cfg, infile=exported_sigs)
|
||||
|
||||
pumsg('\nTesting verification (exported data):\n')
|
||||
print_total( await m.verify() )
|
||||
print_total(await m.verify())
|
||||
|
||||
pumsg('\nTesting single address verification (exported data):\n')
|
||||
print_total( await m.verify(single_addr_coin) )
|
||||
print_total(await m.verify(single_addr_coin))
|
||||
|
||||
pumsg('\nTesting display (exported data):\n')
|
||||
msg(m.format())
|
||||
|
|
@ -127,25 +127,25 @@ async def run_test(network_id,chksum,msghash_type='raw'):
|
|||
|
||||
class unit_tests:
|
||||
|
||||
altcoin_deps = ('ltc','bch','eth','eth_raw')
|
||||
altcoin_deps = ('ltc', 'bch', 'eth', 'eth_raw')
|
||||
|
||||
def btc(self, name, ut, desc='Bitcoin mainnet'):
|
||||
return run_test('btc','AA0DB5')
|
||||
return run_test('btc', 'AA0DB5')
|
||||
|
||||
def btc_tn(self, name, ut, desc='Bitcoin testnet'):
|
||||
return run_test('btc_tn','A88E1D')
|
||||
return run_test('btc_tn', 'A88E1D')
|
||||
|
||||
def btc_rt(self, name, ut, desc='Bitcoin regtest'):
|
||||
return run_test('btc_rt','578018')
|
||||
return run_test('btc_rt', '578018')
|
||||
|
||||
def ltc(self, name, ut, desc='Litecoin mainnet'):
|
||||
return run_test('ltc','BA7549')
|
||||
return run_test('ltc', 'BA7549')
|
||||
|
||||
def bch(self, name, ut, desc='Bitcoin Cash mainnet'):
|
||||
return run_test('bch','1B8065')
|
||||
return run_test('bch', '1B8065')
|
||||
|
||||
def eth(self, name, ut, desc='Ethereum mainnet'):
|
||||
return run_test('eth','35BAD9',msghash_type='eth_sign')
|
||||
return run_test('eth', '35BAD9', msghash_type='eth_sign')
|
||||
|
||||
def eth_raw(self, name, ut, desc='Ethereum mainnet (raw message)'):
|
||||
return run_test('eth','9D900C')
|
||||
return run_test('eth', '9D900C')
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ def coinamt_test(cls, aa, bb, ut):
|
|||
do('a', a, A)
|
||||
do('b', b, B)
|
||||
do('b + a', b + a, B + A)
|
||||
do('sum([b,a])', sum([b,a]), B + A)
|
||||
do('sum([b,a])', sum([b, a]), B + A)
|
||||
do('b - a', b - a, B - A)
|
||||
do('b * a', b * a, B * A)
|
||||
do('b * A', b * A, B * A)
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@ test.unit_tests_d.ut_rpc: RPC unit test for the MMGen suite
|
|||
import sys, os
|
||||
|
||||
from mmgen.cfg import Config
|
||||
from mmgen.color import yellow,cyan
|
||||
from mmgen.util import msg,gmsg,make_timestr,pp_fmt,die
|
||||
from mmgen.color import yellow, cyan
|
||||
from mmgen.util import msg, gmsg, make_timestr, pp_fmt, die
|
||||
from mmgen.protocol import init_proto
|
||||
from mmgen.rpc import rpc_init
|
||||
from mmgen.daemon import CoinDaemon
|
||||
from mmgen.proto.xmr.rpc import MoneroRPCClient,MoneroWalletRPCClient
|
||||
from mmgen.proto.xmr.rpc import MoneroRPCClient, MoneroWalletRPCClient
|
||||
from mmgen.proto.xmr.daemon import MoneroWalletDaemon
|
||||
|
||||
from ..include.common import cfg,qmsg,vmsg
|
||||
from ..include.common import cfg, qmsg, vmsg
|
||||
|
||||
async def cfg_file_auth_test(cfg, d, bad_auth=False):
|
||||
m = 'missing credentials' if bad_auth else f'credentials from {d.cfg_file}'
|
||||
|
|
@ -25,22 +25,22 @@ async def cfg_file_auth_test(cfg, d, bad_auth=False):
|
|||
os.makedirs(d.network_datadir)
|
||||
|
||||
if not bad_auth:
|
||||
cf = os.path.join(d.datadir,d.cfg_file)
|
||||
with open(cf,'a') as fp:
|
||||
cf = os.path.join(d.datadir, d.cfg_file)
|
||||
with open(cf, 'a') as fp:
|
||||
fp.write('\nrpcuser = ut_rpc\nrpcpassword = ut_rpc_passw0rd\n')
|
||||
d.flag.keep_cfg_file = True
|
||||
|
||||
d.start()
|
||||
|
||||
if bad_auth:
|
||||
os.rename(d.auth_cookie_fn,d.auth_cookie_fn+'.bak')
|
||||
os.rename(d.auth_cookie_fn, d.auth_cookie_fn+'.bak')
|
||||
try:
|
||||
await rpc_init(cfg, d.proto)
|
||||
except Exception as e:
|
||||
vmsg(yellow(str(e)))
|
||||
else:
|
||||
die(3,'No error on missing credentials!')
|
||||
os.rename(d.auth_cookie_fn+'.bak',d.auth_cookie_fn)
|
||||
die(3, 'No error on missing credentials!')
|
||||
os.rename(d.auth_cookie_fn+'.bak', d.auth_cookie_fn)
|
||||
else:
|
||||
rpc = await rpc_init(cfg, d.proto)
|
||||
assert rpc.auth.user == 'ut_rpc', f'{rpc.auth.user}: user is not ut_rpc!'
|
||||
|
|
@ -68,7 +68,7 @@ async def print_daemon_info(rpc):
|
|||
|
||||
if rpc.proto.base_proto == 'Bitcoin':
|
||||
def fmt_dict(d):
|
||||
return '\n ' + '\n '.join( pp_fmt(d).split('\n') ) + '\n'
|
||||
return '\n ' + '\n '.join(pp_fmt(d).split('\n')) + '\n'
|
||||
msg(f"""
|
||||
NETWORKINFO: {fmt_dict(rpc.cached["networkinfo"])}
|
||||
BLOCKCHAININFO: {fmt_dict(rpc.cached["blockchaininfo"])}
|
||||
|
|
@ -78,30 +78,30 @@ async def print_daemon_info(rpc):
|
|||
|
||||
msg('')
|
||||
|
||||
def do_msg(rpc,backend):
|
||||
def do_msg(rpc, backend):
|
||||
bname = type(rpc.backend).__name__
|
||||
qmsg(' Testing backend {!r}{}'.format( bname, '' if backend == bname else f' [{backend}]' ))
|
||||
qmsg(' Testing backend {!r}{}'.format(bname, '' if backend == bname else f' [{backend}]'))
|
||||
|
||||
class init_test:
|
||||
|
||||
@staticmethod
|
||||
async def btc(cfg, daemon, backend):
|
||||
rpc = await rpc_init(cfg, daemon.proto, backend, daemon)
|
||||
do_msg(rpc,backend)
|
||||
do_msg(rpc, backend)
|
||||
|
||||
if cfg.tw_name:
|
||||
wi = await rpc.walletinfo
|
||||
assert wi['walletname'] == rpc.cfg.tw_name, f'{wi["walletname"]!r} != {rpc.cfg.tw_name!r}'
|
||||
|
||||
bh = (await rpc.call('getblockchaininfo',timeout=300))['bestblockhash']
|
||||
await rpc.gathered_call('getblock',((bh,),(bh,1)),timeout=300)
|
||||
await rpc.gathered_call(None,(('getblock',(bh,)),('getblock',(bh,1))),timeout=300)
|
||||
bh = (await rpc.call('getblockchaininfo', timeout=300))['bestblockhash']
|
||||
await rpc.gathered_call('getblock', ((bh,), (bh, 1)), timeout=300)
|
||||
await rpc.gathered_call(None, (('getblock', (bh,)), ('getblock', (bh, 1))), timeout=300)
|
||||
return rpc
|
||||
|
||||
@staticmethod
|
||||
async def bch(cfg, daemon, backend):
|
||||
rpc = await rpc_init(cfg, daemon.proto, backend, daemon)
|
||||
do_msg(rpc,backend)
|
||||
do_msg(rpc, backend)
|
||||
return rpc
|
||||
|
||||
ltc = bch
|
||||
|
|
@ -109,8 +109,8 @@ class init_test:
|
|||
@staticmethod
|
||||
async def eth(cfg, daemon, backend):
|
||||
rpc = await rpc_init(cfg, daemon.proto, backend, daemon)
|
||||
do_msg(rpc,backend)
|
||||
await rpc.call('eth_blockNumber',timeout=300)
|
||||
do_msg(rpc, backend)
|
||||
await rpc.call('eth_blockNumber', timeout=300)
|
||||
return rpc
|
||||
|
||||
etc = eth
|
||||
|
|
@ -152,33 +152,33 @@ async def run_test(network_ids, test_cf_auth=False, daemon_ids=None, cfg_in=None
|
|||
all_ids = CoinDaemon.get_daemon_ids(cfg_arg, proto.coin)
|
||||
ids = set(daemon_ids) & set(all_ids) if daemon_ids else all_ids
|
||||
for daemon_id in ids:
|
||||
await do_test(CoinDaemon(cfg_arg, proto=proto,test_suite=True,daemon_id=daemon_id), cfg_arg)
|
||||
await do_test(CoinDaemon(cfg_arg, proto=proto, test_suite=True, daemon_id=daemon_id), cfg_arg)
|
||||
|
||||
return True
|
||||
|
||||
class unit_tests:
|
||||
|
||||
altcoin_deps = ('ltc','bch','geth','erigon','parity','xmrwallet')
|
||||
altcoin_deps = ('ltc', 'bch', 'geth', 'erigon', 'parity', 'xmrwallet')
|
||||
arm_skip = ('parity',) # no prebuilt binaries for ARM
|
||||
|
||||
async def btc(self, name, ut):
|
||||
return await run_test(
|
||||
['btc','btc_tn'],
|
||||
['btc', 'btc_tn'],
|
||||
test_cf_auth = True,
|
||||
cfg_in = Config({'_clone': cfg, 'tw_name': 'alternate-tracking-wallet'}))
|
||||
|
||||
async def ltc(self, name, ut):
|
||||
return await run_test(['ltc','ltc_tn'], test_cf_auth=True)
|
||||
return await run_test(['ltc', 'ltc_tn'], test_cf_auth=True)
|
||||
|
||||
async def bch(self, name, ut):
|
||||
return await run_test(['bch','bch_tn'], test_cf_auth=True)
|
||||
return await run_test(['bch', 'bch_tn'], test_cf_auth=True)
|
||||
|
||||
async def geth(self, name, ut):
|
||||
# mainnet returns EIP-155 error on empty blockchain:
|
||||
return await run_test(['eth_tn','eth_rt'], daemon_ids=['geth'])
|
||||
return await run_test(['eth_tn', 'eth_rt'], daemon_ids=['geth'])
|
||||
|
||||
async def erigon(self, name, ut):
|
||||
return await run_test(['eth','eth_tn','eth_rt'], daemon_ids=['erigon'])
|
||||
return await run_test(['eth', 'eth_tn', 'eth_rt'], daemon_ids=['erigon'])
|
||||
|
||||
async def parity(self, name, ut):
|
||||
return await run_test(['etc'])
|
||||
|
|
@ -203,40 +203,40 @@ class unit_tests:
|
|||
from mmgen.xmrseed import xmrseed
|
||||
|
||||
async def run():
|
||||
networks = init_proto( cfg, 'xmr' ).networks
|
||||
networks = init_proto(cfg, 'xmr').networks
|
||||
daemons = [(
|
||||
CoinDaemon( cfg, proto=proto, test_suite=True ),
|
||||
CoinDaemon(cfg, proto=proto, test_suite=True),
|
||||
MoneroWalletDaemon(
|
||||
cfg = cfg,
|
||||
proto = proto,
|
||||
test_suite = True,
|
||||
wallet_dir = os.path.join('test','trash2'),
|
||||
datadir = os.path.join('test','trash2','wallet_rpc'),
|
||||
passwd = 'ut_rpc_passw0rd' )
|
||||
) for proto in (init_proto( cfg, 'xmr', network=network ) for network in networks) ]
|
||||
wallet_dir = os.path.join('test', 'trash2'),
|
||||
datadir = os.path.join('test', 'trash2', 'wallet_rpc'),
|
||||
passwd = 'ut_rpc_passw0rd')
|
||||
) for proto in (init_proto(cfg, 'xmr', network=network) for network in networks)]
|
||||
|
||||
for md,wd in daemons:
|
||||
for md, wd in daemons:
|
||||
if not cfg.no_daemon_autostart:
|
||||
md.start()
|
||||
wd.start()
|
||||
|
||||
await test_monerod_rpc(md)
|
||||
|
||||
c = MoneroWalletRPCClient( cfg=cfg, daemon=wd )
|
||||
c = MoneroWalletRPCClient(cfg=cfg, daemon=wd)
|
||||
fn = f'monero-{wd.network}-junk-wallet'
|
||||
qmsg(f'Creating {wd.network} wallet')
|
||||
c.call(
|
||||
'restore_deterministic_wallet',
|
||||
filename = fn,
|
||||
password = 'foo',
|
||||
seed = xmrseed().fromhex('beadface'*8,tostr=True) )
|
||||
seed = xmrseed().fromhex('beadface'*8, tostr=True))
|
||||
|
||||
if sys.platform == 'win32':
|
||||
wd.stop()
|
||||
wd.start()
|
||||
|
||||
qmsg(f'Opening {wd.network} wallet')
|
||||
c.call( 'open_wallet', filename=fn, password='foo' )
|
||||
c.call('open_wallet', filename=fn, password='foo')
|
||||
|
||||
await c.stop_daemon()
|
||||
|
||||
|
|
@ -249,7 +249,7 @@ class unit_tests:
|
|||
gmsg('OK')
|
||||
|
||||
import shutil
|
||||
shutil.rmtree('test/trash2',ignore_errors=True)
|
||||
shutil.rmtree('test/trash2', ignore_errors=True)
|
||||
os.makedirs('test/trash2/wallet_rpc')
|
||||
await run()
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
test.unit_tests_d.ut_scrypt: password hashing unit test for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.util import msg,msg_r
|
||||
from mmgen.util import msg, msg_r
|
||||
|
||||
from ..include.common import cfg,qmsg,vmsg,omsg_r,silence,end_silence
|
||||
from ..include.common import cfg, qmsg, vmsg, omsg_r, silence, end_silence
|
||||
|
||||
class unit_test:
|
||||
|
||||
def run_test(self,name,ut):
|
||||
def run_test(self, name, ut):
|
||||
import time
|
||||
|
||||
msg_r('Testing password hashing...')
|
||||
|
|
@ -21,27 +21,31 @@ class unit_test:
|
|||
|
||||
salt = bytes.fromhex('f00f' * 16)
|
||||
|
||||
presets = { '1': '64898d01ffcea1252c17411e7bd6c12d00191ee8ddcbf95420e5de8f37a7a1cb',
|
||||
'2': '625d0c59fcbcf85eca51b4337d3a4952e554c7c95fe32f4199ad0e9e9370e279',
|
||||
'3': 'b30a5cf0e606515be4a983cc4a1a4c21e04806f19aaa0ad354a353c83aecd3ee',
|
||||
'4': 'a3a1b99393734510b68adf2c2cfdc627a2bc3281913d8ea6fbb677d39781a9fa',
|
||||
'5': '0c7e1a672738cee49cf0ff6f3208190ca418e741835fd6995ce9558cc19f3f04',
|
||||
'6': '91f9d1c9baf3948433dab58dcc912d96035392c1db21ede96d2f369e025ab06d',
|
||||
'7': 'fcb2cd05268de43b0d2d45f78a56e5d446b0bd2d3b57bdbc77cc17a42942f1bd' }
|
||||
presets = {
|
||||
'1': '64898d01ffcea1252c17411e7bd6c12d00191ee8ddcbf95420e5de8f37a7a1cb',
|
||||
'2': '625d0c59fcbcf85eca51b4337d3a4952e554c7c95fe32f4199ad0e9e9370e279',
|
||||
'3': 'b30a5cf0e606515be4a983cc4a1a4c21e04806f19aaa0ad354a353c83aecd3ee',
|
||||
'4': 'a3a1b99393734510b68adf2c2cfdc627a2bc3281913d8ea6fbb677d39781a9fa',
|
||||
'5': '0c7e1a672738cee49cf0ff6f3208190ca418e741835fd6995ce9558cc19f3f04',
|
||||
'6': '91f9d1c9baf3948433dab58dcc912d96035392c1db21ede96d2f369e025ab06d',
|
||||
'7': 'fcb2cd05268de43b0d2d45f78a56e5d446b0bd2d3b57bdbc77cc17a42942f1bd'
|
||||
}
|
||||
|
||||
pws = ( ('', 'cc8d99ce7365d8a9d2422d71ce330e130b2cade46a8cc0459a3f83e1a6ac3d30'),
|
||||
('foo', 'f0e2cce1d9980edf2373a2070ad3560c2506faf9bc50704a1bc5cdb3c7f63f3b'),
|
||||
('φυβαρ', '64898d01ffcea1252c17411e7bd6c12d00191ee8ddcbf95420e5de8f37a7a1cb') )
|
||||
pws = (
|
||||
('', 'cc8d99ce7365d8a9d2422d71ce330e130b2cade46a8cc0459a3f83e1a6ac3d30'),
|
||||
('foo', 'f0e2cce1d9980edf2373a2070ad3560c2506faf9bc50704a1bc5cdb3c7f63f3b'),
|
||||
('φυβαρ', '64898d01ffcea1252c17411e7bd6c12d00191ee8ddcbf95420e5de8f37a7a1cb')
|
||||
)
|
||||
|
||||
def test_passwords():
|
||||
for pw_base,res in pws:
|
||||
for pw in (pw_base,pw_base.encode()):
|
||||
pw_disp = "'"+pw+"'" if isinstance(pw,str) else "b'"+pw.decode()+"'"
|
||||
for pw_base, res in pws:
|
||||
for pw in (pw_base, pw_base.encode()):
|
||||
pw_disp = "'"+pw+"'" if isinstance(pw, str) else "b'"+pw.decode()+"'"
|
||||
if cfg.quiet:
|
||||
omsg_r('.')
|
||||
else:
|
||||
msg_r(f'\n password {pw_disp:9} ')
|
||||
ret = crypto.scrypt_hash_passphrase(pw,salt,'1').hex()
|
||||
ret = crypto.scrypt_hash_passphrase(pw, salt, '1').hex()
|
||||
assert ret == res, ret
|
||||
|
||||
def test_presets(do_presets):
|
||||
|
|
@ -54,7 +58,7 @@ class unit_test:
|
|||
else:
|
||||
msg_r(f'\n {hp!r:3}: {crypto.hash_presets[hp]!r:12} ')
|
||||
st = time.time()
|
||||
ret = crypto.scrypt_hash_passphrase(pw,salt,hp).hex()
|
||||
ret = crypto.scrypt_hash_passphrase(pw, salt, hp).hex()
|
||||
t = time.time() - st
|
||||
vmsg('' if cfg.test_suite_deterministic else f' {t:0.4f} secs')
|
||||
assert ret == res, ret
|
||||
|
|
@ -66,13 +70,13 @@ class unit_test:
|
|||
vmsg('Passwords (auto module selection):')
|
||||
test_passwords()
|
||||
vmsg('Hash presets (auto module selection):')
|
||||
test_presets((1,2,3,4) if cfg.fast else (1,2,3,4,5,6,7))
|
||||
test_presets((1, 2, 3, 4) if cfg.fast else (1, 2, 3, 4, 5, 6, 7))
|
||||
|
||||
cfg.force_standalone_scrypt_module = True
|
||||
vmsg('Passwords (force standalone scrypt module):')
|
||||
test_passwords()
|
||||
vmsg('Hash presets (force standalone scrypt module):')
|
||||
test_presets((1,2,3))
|
||||
test_presets((1, 2, 3))
|
||||
|
||||
if cfg.quiet:
|
||||
end_silence()
|
||||
|
|
|
|||
|
|
@ -4,66 +4,76 @@
|
|||
test/unit_tests_d/ut_seedsplit: seed splitting unit test for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.util import msg,msg_r
|
||||
from mmgen.util import msg, msg_r
|
||||
|
||||
from ..include.common import cfg,vmsg,vmsg_r
|
||||
from ..include.common import cfg, vmsg, vmsg_r
|
||||
|
||||
class unit_test:
|
||||
|
||||
def run_test(self,name,ut):
|
||||
def run_test(self, name, ut):
|
||||
from mmgen.seed import Seed
|
||||
from mmgen.seedsplit import SeedShareList,SeedShareIdx
|
||||
from mmgen.seedsplit import SeedShareList, SeedShareIdx
|
||||
|
||||
cfg.debug_subseed = bool(cfg.verbose)
|
||||
|
||||
def basic_ops(master_idx):
|
||||
test_data = {
|
||||
'default': (
|
||||
(8,'4710FBF0','B3D9411B','2670E83D','D1FC57ED','AE49CABE','63FFBA62',0,0),
|
||||
(6,'9D07ABBD','AF5DC2F6','1A3BBDAC','2548AEE9','B94F7450','1F4E5A12',0,0),
|
||||
(4,'43670520','1F72C066','E5AA8DA1','A33966A0','D2BCE0A5','A568C315',0,0),
|
||||
(8, '4710FBF0', 'B3D9411B', '2670E83D', 'D1FC57ED', 'AE49CABE', '63FFBA62', 0, 0),
|
||||
(6, '9D07ABBD', 'AF5DC2F6', '1A3BBDAC', '2548AEE9', 'B94F7450', '1F4E5A12', 0, 0),
|
||||
(4, '43670520', '1F72C066', 'E5AA8DA1', 'A33966A0', 'D2BCE0A5', 'A568C315', 0, 0),
|
||||
),
|
||||
'φυβαρ': (
|
||||
(8,'4710FBF0','269D658C','9D25889E','6D730ECB','C61A963F','9FE99C05',0,0),
|
||||
(6,'9D07ABBD','4998B33E','F00CE041','C612BEE5','35CD3675','41B3BE61',0,0),
|
||||
(4,'43670520','77140076','EA82CB30','80F7AEDE','D168D768','77BE57AA',0,0),
|
||||
(8, '4710FBF0', '269D658C', '9D25889E', '6D730ECB', 'C61A963F', '9FE99C05', 0, 0),
|
||||
(6, '9D07ABBD', '4998B33E', 'F00CE041', 'C612BEE5', '35CD3675', '41B3BE61', 0, 0),
|
||||
(4, '43670520', '77140076', 'EA82CB30', '80F7AEDE', 'D168D768', '77BE57AA', 0, 0),
|
||||
)
|
||||
}
|
||||
test_data_master = {
|
||||
'1': {
|
||||
'default': (
|
||||
(8,'4710FBF0','6AE6177F','AC12090C','6AE6177F','3E87A907','7D1FEA56','BFEBFFFF','629A9808'),
|
||||
(4,'43670520','6739535C','ABF4DD38','6739535C','778E9C60','89CBCFD2','689FABF5','70BED76B'),
|
||||
(8, '4710FBF0', '6AE6177F', 'AC12090C', '6AE6177F',
|
||||
'3E87A907', '7D1FEA56', 'BFEBFFFF', '629A9808'),
|
||||
(4, '43670520', '6739535C', 'ABF4DD38', '6739535C',
|
||||
'778E9C60', '89CBCFD2', '689FABF5', '70BED76B'),
|
||||
),
|
||||
'φυβαρ': (
|
||||
(8,'4710FBF0','6AE6177F','AC5FA32E','6AE6177F','9777A750','C7CF2AFC','035AAACB','C777FBE4'),
|
||||
(4,'43670520','6739535C','37EBA2F5','6739535C','927549D2','29BADEE7','9CA73A03','313F5528'))
|
||||
(8, '4710FBF0', '6AE6177F', 'AC5FA32E', '6AE6177F',
|
||||
'9777A750', 'C7CF2AFC', '035AAACB', 'C777FBE4'),
|
||||
(4, '43670520', '6739535C', '37EBA2F5', '6739535C',
|
||||
'927549D2', '29BADEE7', '9CA73A03', '313F5528'))
|
||||
},
|
||||
'5': {
|
||||
'default': (
|
||||
(8,'4710FBF0','5EFAC3D6','B489167D','5EFAC3D6','BB004DC5','1A0381C0','4EA182E3','547FB2DC'),
|
||||
(4,'43670520','EE93DB0E','44962A7D','EE93DB0E','07339882','376A05B1','CE51D022','00149CA3'),
|
||||
(8, '4710FBF0', '5EFAC3D6', 'B489167D', '5EFAC3D6',
|
||||
'BB004DC5', '1A0381C0', '4EA182E3', '547FB2DC'),
|
||||
(4, '43670520', 'EE93DB0E', '44962A7D', 'EE93DB0E',
|
||||
'07339882', '376A05B1', 'CE51D022', '00149CA3'),
|
||||
),
|
||||
'φυβαρ': (
|
||||
(8,'4710FBF0','5EFAC3D6','A6E27EE3','5EFAC3D6','32C24668','B4C54297','1EC9B71B','8C5C6B1C'),
|
||||
(4,'43670520','EE93DB0E','B584E963','EE93DB0E','4BEA2AB2','4BEA65C7','140FC43F','BBD19461'))
|
||||
(8, '4710FBF0', '5EFAC3D6', 'A6E27EE3', '5EFAC3D6',
|
||||
'32C24668', 'B4C54297', '1EC9B71B', '8C5C6B1C'),
|
||||
(4, '43670520', 'EE93DB0E', 'B584E963', 'EE93DB0E',
|
||||
'4BEA2AB2', '4BEA65C7', '140FC43F', 'BBD19461'))
|
||||
}
|
||||
}
|
||||
if master_idx:
|
||||
test_data = test_data_master[str(master_idx)]
|
||||
|
||||
for id_str in (None,'default','φυβαρ'):
|
||||
for id_str in (None, 'default', 'φυβαρ'):
|
||||
msg_r(f'Testing basic ops (id_str={id_str!r}, master_idx={master_idx})...')
|
||||
vmsg('')
|
||||
|
||||
for a,b,c,d,e,f,h,i,p in test_data[id_str if id_str is not None else 'default']:
|
||||
for a, b, c, d, e, f, h, i, p in test_data[id_str if id_str is not None else 'default']:
|
||||
seed_bin = bytes.fromhex('deadbeef' * a)
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
assert seed.sid == b, seed.sid
|
||||
|
||||
for share_count,j,k,l,m in ((2,c,c,d,i),(5,e,f,h,p)):
|
||||
for share_count, j, k, l, m in (
|
||||
(2, c, c, d, i),
|
||||
(5, e, f, h, p)):
|
||||
|
||||
shares = seed.split(share_count,id_str,master_idx)
|
||||
shares = seed.split(share_count, id_str, master_idx)
|
||||
A = len(shares)
|
||||
assert A == share_count, A
|
||||
|
||||
|
|
@ -72,16 +82,16 @@ class unit_test:
|
|||
assert len(s.strip().split('\n')) == share_count+6, s
|
||||
|
||||
if master_idx:
|
||||
A = shares.get_share_by_idx(1,base_seed=False).sid
|
||||
B = shares.get_share_by_seed_id(j,base_seed=False).sid
|
||||
A = shares.get_share_by_idx(1, base_seed=False).sid
|
||||
B = shares.get_share_by_seed_id(j, base_seed=False).sid
|
||||
assert A == B == m, A
|
||||
|
||||
A = shares.get_share_by_idx(1,base_seed=True).sid
|
||||
B = shares.get_share_by_seed_id(j,base_seed=True).sid
|
||||
A = shares.get_share_by_idx(1, base_seed=True).sid
|
||||
B = shares.get_share_by_seed_id(j, base_seed=True).sid
|
||||
assert A == B == j, A
|
||||
|
||||
A = shares.get_share_by_idx(share_count-1,base_seed=True).sid
|
||||
B = shares.get_share_by_seed_id(k,base_seed=True).sid
|
||||
A = shares.get_share_by_idx(share_count-1, base_seed=True).sid
|
||||
B = shares.get_share_by_seed_id(k, base_seed=True).sid
|
||||
assert A == B == k, A
|
||||
|
||||
A = shares.get_share_by_idx(share_count).sid
|
||||
|
|
@ -92,8 +102,8 @@ class unit_test:
|
|||
assert A == b, A
|
||||
|
||||
if master_idx:
|
||||
slist = [shares.get_share_by_idx(i+1,base_seed=True) for i in range(len(shares))]
|
||||
A = Seed.join_shares( cfg, slist, master_idx, id_str ).sid
|
||||
slist = [shares.get_share_by_idx(i+1, base_seed=True) for i in range(len(shares))]
|
||||
A = Seed.join_shares(cfg, slist, master_idx, id_str).sid
|
||||
assert A == b, A
|
||||
|
||||
msg('OK')
|
||||
|
|
@ -102,7 +112,7 @@ class unit_test:
|
|||
msg_r('Testing defaults and limits...')
|
||||
|
||||
seed_bin = bytes.fromhex('deadbeef' * 8)
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
|
||||
shares = seed.split(SeedShareIdx.max_val)
|
||||
s = shares.format()
|
||||
|
|
@ -120,16 +130,16 @@ class unit_test:
|
|||
|
||||
msg('OK')
|
||||
|
||||
def collisions(seed_hex,ss_count,last_sid,collisions_chk,master_idx):
|
||||
def collisions(seed_hex, ss_count, last_sid, collisions_chk, master_idx):
|
||||
|
||||
msg_r(f'Testing Seed ID collisions ({ss_count} seed shares, master_idx={master_idx})...')
|
||||
vmsg('')
|
||||
|
||||
seed_bin = bytes.fromhex(seed_hex)
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
|
||||
SeedShareIdx.max_val = ss_count
|
||||
shares = seed.split(ss_count,master_idx=master_idx)
|
||||
shares = seed.split(ss_count, master_idx=master_idx)
|
||||
A = shares.get_share_by_idx(ss_count).sid
|
||||
B = shares.get_share_by_seed_id(last_sid).sid
|
||||
assert A == last_sid, A
|
||||
|
|
@ -149,10 +159,10 @@ class unit_test:
|
|||
msg_r('Testing last share collisions with shortened Seed IDs')
|
||||
vmsg('')
|
||||
seed_bin = bytes.fromhex('2eadbeef'*8)
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
ssm_save = SeedShareIdx.max_val
|
||||
ssm = SeedShareIdx.max_val = 2048
|
||||
shares = SeedShareList(seed,count=ssm,id_str='foo',master_idx=1,debug_last_share=True)
|
||||
shares = SeedShareList(seed, count=ssm, id_str='foo', master_idx=1, debug_last_share=True)
|
||||
lsid = shares.last_share.sid
|
||||
collisions = shares.data['long'][lsid][1]
|
||||
assert collisions == 2, collisions
|
||||
|
|
@ -166,7 +176,7 @@ class unit_test:
|
|||
basic_ops(master_idx=5)
|
||||
defaults_and_limits()
|
||||
last_share_collisions()
|
||||
collisions('1dabcdef'*4,65535,'B5CBCE0A',3,master_idx=None)
|
||||
collisions('18abcdef'*4,65535,'FF03CE82',3,master_idx=1)
|
||||
collisions('1dabcdef'*4, 65535, 'B5CBCE0A', 3, master_idx=None)
|
||||
collisions('18abcdef'*4, 65535, 'FF03CE82', 3, master_idx=1)
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -4,28 +4,28 @@
|
|||
test/unit_tests_d/ut_subseed: subseed unit test for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.util import msg,msg_r
|
||||
from mmgen.util import msg, msg_r
|
||||
|
||||
from ..include.common import cfg,vmsg_r
|
||||
from ..include.common import cfg, vmsg_r
|
||||
|
||||
class unit_test:
|
||||
|
||||
def run_test(self,name,ut):
|
||||
def run_test(self, name, ut):
|
||||
from mmgen.seed import Seed
|
||||
from mmgen.subseed import SubSeedList,SubSeedIdxRange
|
||||
from mmgen.subseed import SubSeedList, SubSeedIdxRange
|
||||
|
||||
nSubseeds = SubSeedList.dfl_len
|
||||
|
||||
def basic_ops():
|
||||
msg_r('Testing basic ops...')
|
||||
for a,b,c,d,e,f,h in (
|
||||
(8,'4710FBF0','0C1B0615','803B165C','2669AC64',256,'10L'),
|
||||
(6,'9D07ABBD','EBA9C33F','20787E6A','192E2AA2',192,'10L'),
|
||||
(4,'43670520','04A4CCB3','B5F21D7B','C1934CFF',128,'10L'),
|
||||
for a, b, c, d, e, f, h in (
|
||||
(8, '4710FBF0', '0C1B0615', '803B165C', '2669AC64', 256, '10L'),
|
||||
(6, '9D07ABBD', 'EBA9C33F', '20787E6A', '192E2AA2', 192, '10L'),
|
||||
(4, '43670520', '04A4CCB3', 'B5F21D7B', 'C1934CFF', 128, '10L'),
|
||||
):
|
||||
|
||||
seed_bin = bytes.fromhex('deadbeef' * a)
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
assert seed.sid == b, seed.sid
|
||||
|
||||
subseed = seed.subseed('2s')
|
||||
|
|
@ -40,7 +40,7 @@ class unit_test:
|
|||
assert subseed.idx == 10, subseed.idx
|
||||
assert subseed.ss_idx == h, subseed.ss_idx
|
||||
|
||||
seed2 = Seed( cfg, seed_bin )
|
||||
seed2 = Seed(cfg, seed_bin)
|
||||
ss2_list = seed2.subseeds
|
||||
|
||||
seed2.subseeds._generate(1)
|
||||
|
|
@ -61,7 +61,7 @@ class unit_test:
|
|||
assert seed.pfmt() == seed2.pfmt()
|
||||
assert seed.subseeds.pfmt() == seed2.subseeds.pfmt()
|
||||
|
||||
s = seed.subseeds.format(1,nSubseeds)
|
||||
s = seed.subseeds.format(1, nSubseeds)
|
||||
s_lines = s.strip().split('\n')
|
||||
assert len(s_lines) == nSubseeds + 4, s
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ class unit_test:
|
|||
b = [e for e in s_lines if ' 5S:' in e][0].strip().split()[3]
|
||||
assert a == b, b
|
||||
|
||||
s = seed.subseeds.format(nSubseeds+1,nSubseeds+2)
|
||||
s = seed.subseeds.format(nSubseeds+1, nSubseeds+2)
|
||||
s_lines = s.strip().split('\n')
|
||||
assert len(s_lines) == 6, s
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ class unit_test:
|
|||
b = [e for e in s_lines if f' {ss_idx}:' in e][0].strip().split()[3]
|
||||
assert a == b, b
|
||||
|
||||
s = seed.subseeds.format(1,10)
|
||||
s = seed.subseeds.format(1, 10)
|
||||
s_lines = s.strip().split('\n')
|
||||
assert len(s_lines) == 14, s
|
||||
|
||||
|
|
@ -98,48 +98,48 @@ class unit_test:
|
|||
|
||||
seed_bin = bytes.fromhex('deadbeef' * 8)
|
||||
|
||||
seed = Seed( cfg, seed_bin, nSubseeds=11 )
|
||||
seed = Seed(cfg, seed_bin, nSubseeds=11)
|
||||
seed.subseeds._generate()
|
||||
ss = seed.subseeds
|
||||
assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
|
||||
assert len(ss) == 11, len(ss)
|
||||
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
seed.subseeds._generate()
|
||||
ss = seed.subseeds
|
||||
assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
|
||||
assert len(ss) == nSubseeds, len(ss)
|
||||
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
seed.subseed_by_seed_id('EEEEEEEE')
|
||||
ss = seed.subseeds
|
||||
assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
|
||||
assert len(ss) == nSubseeds, len(ss)
|
||||
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
subseed = seed.subseed_by_seed_id('803B165C')
|
||||
assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
|
||||
assert subseed.sid == '803B165C', subseed.sid
|
||||
assert subseed.idx == 3, subseed.idx
|
||||
|
||||
seed = Seed( cfg, seed_bin )
|
||||
subseed = seed.subseed_by_seed_id('803B165C',last_idx=1)
|
||||
seed = Seed(cfg, seed_bin)
|
||||
subseed = seed.subseed_by_seed_id('803B165C', last_idx=1)
|
||||
assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
|
||||
assert subseed is None, subseed
|
||||
|
||||
r = SubSeedIdxRange('1-5')
|
||||
r2 = SubSeedIdxRange(1,5)
|
||||
r2 = SubSeedIdxRange(1, 5)
|
||||
assert r2 == r, r2
|
||||
assert r == (r.first,r.last), r
|
||||
assert r == (r.first, r.last), r
|
||||
assert r.first == 1, r.first
|
||||
assert r.last == 5, r.last
|
||||
assert r.items == [1,2,3,4,5], r.items
|
||||
assert r.items == [1, 2, 3, 4, 5], r.items
|
||||
assert list(r.iterate()) == r.items, list(r.iterate())
|
||||
|
||||
r = SubSeedIdxRange('22')
|
||||
r2 = SubSeedIdxRange(22,22)
|
||||
r2 = SubSeedIdxRange(22, 22)
|
||||
assert r2 == r, r2
|
||||
assert r == (r.first,r.last), r
|
||||
assert r == (r.first, r.last), r
|
||||
assert r.first == 22, r.first
|
||||
assert r.last == 22, r.last
|
||||
assert r.items == [22], r
|
||||
|
|
@ -149,9 +149,9 @@ class unit_test:
|
|||
assert r.items == [3], r.items
|
||||
|
||||
r = SubSeedIdxRange(f'{nSubseeds-1}-{nSubseeds}')
|
||||
assert r.items == [nSubseeds-1,nSubseeds], r.items
|
||||
assert r.items == [nSubseeds-1, nSubseeds], r.items
|
||||
|
||||
for n,e in enumerate(SubSeedIdxRange('1-5').iterate(),1):
|
||||
for n, e in enumerate(SubSeedIdxRange('1-5').iterate(), 1):
|
||||
assert n == e, e
|
||||
|
||||
assert n == 5, n
|
||||
|
|
@ -159,9 +159,9 @@ class unit_test:
|
|||
msg('OK')
|
||||
|
||||
def collisions():
|
||||
ss_count,ltr,last_sid,collisions_chk = (
|
||||
(SubSeedIdxRange.max_idx,'S','2788F26B',470),
|
||||
(49509,'L','8D1FE500',2)
|
||||
ss_count, ltr, last_sid, collisions_chk = (
|
||||
(SubSeedIdxRange.max_idx, 'S', '2788F26B', 470),
|
||||
(49509, 'L', '8D1FE500', 2)
|
||||
)[bool(cfg.fast)]
|
||||
|
||||
last_idx = str(ss_count) + ltr
|
||||
|
|
@ -169,7 +169,7 @@ class unit_test:
|
|||
msg_r(f'Testing Seed ID collisions ({ss_count} subseed pairs)...')
|
||||
|
||||
seed_bin = bytes.fromhex('12abcdef' * 8) # 95B3D78D
|
||||
seed = Seed( cfg, seed_bin )
|
||||
seed = Seed(cfg, seed_bin)
|
||||
|
||||
seed.subseeds._generate(ss_count)
|
||||
ss = seed.subseeds
|
||||
|
|
@ -181,7 +181,7 @@ class unit_test:
|
|||
assert sid not in ss.data['short']
|
||||
|
||||
collisions = 0
|
||||
for k in ('short','long'):
|
||||
for k in ('short', 'long'):
|
||||
for sid in ss.data[k]:
|
||||
collisions += ss.data[k][sid][1]
|
||||
|
||||
|
|
|
|||
|
|
@ -4,64 +4,64 @@
|
|||
test.unit_tests_d.ut_testdep: test dependency unit tests for the MMGen suite
|
||||
"""
|
||||
|
||||
import sys,os
|
||||
from subprocess import run,DEVNULL
|
||||
import sys, os
|
||||
from subprocess import run, DEVNULL
|
||||
|
||||
from mmgen.util import ymsg,bmsg
|
||||
from mmgen.util import ymsg, bmsg
|
||||
from ..include.common import cfg
|
||||
|
||||
sec = 'deadbeef' * 8
|
||||
|
||||
class unit_tests:
|
||||
|
||||
altcoin_deps = ('pycoin','monero_python','keyconv','zcash_mini','ethkey','ssh_socks_proxy')
|
||||
altcoin_deps = ('pycoin', 'monero_python', 'keyconv', 'zcash_mini', 'ethkey', 'ssh_socks_proxy')
|
||||
win_skip = ('losetup', 'zcash_mini', 'sudo')
|
||||
mac_skip = ('losetup',)
|
||||
|
||||
def pylint(self,name,ut):
|
||||
def pylint(self, name, ut):
|
||||
try:
|
||||
return run(['pylint','--version'],stdout=None if cfg.verbose else DEVNULL).returncode == 0
|
||||
return run(['pylint', '--version'], stdout=None if cfg.verbose else DEVNULL).returncode == 0
|
||||
except OSError as e:
|
||||
ymsg(' ' + str(e))
|
||||
bmsg(" Install pylint with 'python3 -m pip install pylint'")
|
||||
return False
|
||||
|
||||
def core_repo(self,name,ut):
|
||||
def core_repo(self, name, ut):
|
||||
crr = os.getenv('CORE_REPO_ROOT')
|
||||
if not crr or not os.path.exists(os.path.join(crr,'src/test/data/tx_valid.json')):
|
||||
if not crr or not os.path.exists(os.path.join(crr, 'src/test/data/tx_valid.json')):
|
||||
ymsg('CORE_REPO_ROOT not set, or does not point to Bitcoin Core repository')
|
||||
return False
|
||||
return True
|
||||
|
||||
def losetup(self,name,ut):
|
||||
def losetup(self, name, ut):
|
||||
os.stat('/dev/loop0')
|
||||
run(['/sbin/losetup','-f'],check=True,stdout=DEVNULL)
|
||||
run(['/sbin/losetup', '-f'], check=True, stdout=DEVNULL)
|
||||
return True
|
||||
|
||||
def pycoin(self,name,ut):
|
||||
def pycoin(self, name, ut):
|
||||
from pycoin.networks.registry import network_for_netcode as nfnc
|
||||
network = nfnc('btc')
|
||||
key = network.keys.private(secret_exponent=int(sec,16),is_compressed=True)
|
||||
key = network.keys.private(secret_exponent=int(sec, 16), is_compressed=True)
|
||||
hash160_c = key.hash160(is_compressed=True)
|
||||
network.address.for_p2pkh_wit(hash160_c)
|
||||
return True
|
||||
|
||||
def monero_python(self,name,ut):
|
||||
def monero_python(self, name, ut):
|
||||
from mmgen.util2 import load_cryptodomex
|
||||
load_cryptodomex()
|
||||
from monero.seed import Seed
|
||||
Seed('deadbeef' * 8).public_address()
|
||||
return True
|
||||
|
||||
def keyconv(self,name,ut):
|
||||
run(['keyconv','-G','ltc'],stdout=DEVNULL,stderr=DEVNULL,check=True)
|
||||
def keyconv(self, name, ut):
|
||||
run(['keyconv', '-G', 'ltc'], stdout=DEVNULL, stderr=DEVNULL, check=True)
|
||||
return True
|
||||
|
||||
def zcash_mini(self,name,ut):
|
||||
run(['zcash-mini'],stdout=DEVNULL,check=True)
|
||||
def zcash_mini(self, name, ut):
|
||||
run(['zcash-mini'], stdout=DEVNULL, check=True)
|
||||
return True
|
||||
|
||||
def ethkey(self,name,ut):
|
||||
def ethkey(self, name, ut):
|
||||
if sys.platform == 'linux' and os.uname().machine != 'x86_64':
|
||||
distro = [l for l in open('/etc/os-release').read().split('\n') if l.startswith('ID=')][0][3:]
|
||||
if distro != 'archarm':
|
||||
|
|
@ -71,11 +71,11 @@ class unit_tests:
|
|||
get_ethkey()
|
||||
return True
|
||||
|
||||
def ssh_socks_proxy(self,name,ut):
|
||||
def ssh_socks_proxy(self, name, ut):
|
||||
from test.cmdtest_py_d.ct_xmrwallet import CmdTestXMRWallet
|
||||
return CmdTestXMRWallet.init_proxy(external_call=True)
|
||||
|
||||
def sudo(self,name,ut):
|
||||
def sudo(self, name, ut):
|
||||
from mmgen.util import have_sudo
|
||||
if have_sudo():
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
test.unit_tests_d.ut_tx: TX unit tests for the MMGen suite
|
||||
"""
|
||||
|
||||
import os,re
|
||||
import os, re
|
||||
|
||||
from mmgen.devtools import get_diff,get_ndiff
|
||||
from mmgen.tx import NewTX,CompletedTX,UnsignedTX
|
||||
from mmgen.devtools import get_diff, get_ndiff
|
||||
from mmgen.tx import NewTX, CompletedTX, UnsignedTX
|
||||
from mmgen.tx.file import MMGenTxFile
|
||||
from mmgen.daemon import CoinDaemon
|
||||
from mmgen.protocol import init_proto
|
||||
|
|
@ -19,7 +19,7 @@ async def do_txfile_test(desc, fns, cfg=cfg, check=False):
|
|||
qmsg(f' Testing CompletedTX initializer ({desc})')
|
||||
for fn in fns:
|
||||
qmsg(f' parsing: {os.path.basename(fn)}')
|
||||
fpath = os.path.join('test','ref',fn)
|
||||
fpath = os.path.join('test', 'ref', fn)
|
||||
tx = await CompletedTX(cfg=cfg, filename=fpath, quiet_open=True)
|
||||
|
||||
vmsg('\n' + tx.info.format())
|
||||
|
|
@ -28,7 +28,7 @@ async def do_txfile_test(desc, fns, cfg=cfg, check=False):
|
|||
fn_gen = f.make_filename()
|
||||
|
||||
if cfg.debug_utf8:
|
||||
fn_gen = fn_gen.replace('-α','')
|
||||
fn_gen = fn_gen.replace('-α', '')
|
||||
|
||||
assert fn_gen == os.path.basename(fn), f'{fn_gen} != {fn}'
|
||||
|
||||
|
|
@ -45,13 +45,13 @@ class unit_tests:
|
|||
|
||||
altcoin_deps = ('txfile_alt', 'txfile_alt_legacy')
|
||||
|
||||
async def tx(self,name,ut):
|
||||
async def tx(self, name, ut):
|
||||
qmsg(' Testing NewTX initializer')
|
||||
d = CoinDaemon( cfg, 'btc', test_suite=True )
|
||||
d = CoinDaemon(cfg, 'btc', test_suite=True)
|
||||
d.start()
|
||||
|
||||
proto = init_proto( cfg, 'btc', need_amt=True )
|
||||
await NewTX( cfg=cfg, proto=proto )
|
||||
proto = init_proto(cfg, 'btc', need_amt=True)
|
||||
await NewTX(cfg=cfg, proto=proto)
|
||||
|
||||
d.stop()
|
||||
d.remove_datadir()
|
||||
|
|
@ -108,7 +108,7 @@ class unit_tests:
|
|||
)
|
||||
)
|
||||
|
||||
def errors(self,name,ut):
|
||||
def errors(self, name, ut):
|
||||
async def bad1():
|
||||
await CompletedTX(cfg, filename='foo')
|
||||
def bad2():
|
||||
|
|
|
|||
|
|
@ -4,19 +4,19 @@
|
|||
test/unit_tests_d/ut_tx_deserialize: TX deserialization unit tests for the MMGen suite
|
||||
"""
|
||||
|
||||
import os,json
|
||||
import os, json
|
||||
|
||||
from mmgen.color import purple,cyan
|
||||
from mmgen.util import msg,Msg,Msg_r
|
||||
from mmgen.color import purple, cyan
|
||||
from mmgen.util import msg, Msg, Msg_r
|
||||
from mmgen.devtools import Pmsg
|
||||
from mmgen.protocol import init_proto
|
||||
from mmgen.tx import CompletedTX
|
||||
from mmgen.proto.btc.tx.base import DeserializeTX
|
||||
from mmgen.rpc import rpc_init
|
||||
|
||||
from ..include.common import cfg,start_test_daemons,stop_test_daemons
|
||||
from ..include.common import cfg, start_test_daemons, stop_test_daemons
|
||||
|
||||
def print_info(name,extra_desc):
|
||||
def print_info(name, extra_desc):
|
||||
if cfg.names:
|
||||
Msg_r('{} {} {}'.format(
|
||||
purple('Testing'),
|
||||
|
|
@ -27,22 +27,22 @@ def print_info(name,extra_desc):
|
|||
if not cfg.quiet:
|
||||
Msg('')
|
||||
|
||||
async def test_tx(tx_proto,tx_hex,desc,n):
|
||||
async def test_tx(tx_proto, tx_hex, desc, n):
|
||||
|
||||
def has_nonstandard_outputs(outputs):
|
||||
for o in outputs:
|
||||
t = o['scriptPubKey']['type']
|
||||
if t in ('nonstandard','pubkey','nulldata'):
|
||||
if t in ('nonstandard', 'pubkey', 'nulldata'):
|
||||
return True
|
||||
return False
|
||||
|
||||
rpc = await rpc_init( cfg, proto=tx_proto, ignore_wallet=True )
|
||||
d = await rpc.call('decoderawtransaction',tx_hex)
|
||||
rpc = await rpc_init(cfg, proto=tx_proto, ignore_wallet=True)
|
||||
d = await rpc.call('decoderawtransaction', tx_hex)
|
||||
|
||||
if has_nonstandard_outputs(d['vout']):
|
||||
return False
|
||||
|
||||
dt = DeserializeTX(tx_proto,tx_hex)
|
||||
dt = DeserializeTX(tx_proto, tx_hex)
|
||||
|
||||
if cfg.verbose:
|
||||
Msg('\n\n================================ Core vector: ==================================')
|
||||
|
|
@ -53,51 +53,51 @@ async def test_tx(tx_proto,tx_hex,desc,n):
|
|||
Pmsg(dt._asdict())
|
||||
|
||||
# metadata
|
||||
assert dt.txid == d['txid'],'TXID does not match'
|
||||
assert dt.locktime == d['locktime'],'Locktime does not match'
|
||||
assert dt.version == d['version'],'Version does not match'
|
||||
assert dt.txid == d['txid'], 'TXID does not match'
|
||||
assert dt.locktime == d['locktime'], 'Locktime does not match'
|
||||
assert dt.version == d['version'], 'Version does not match'
|
||||
|
||||
# inputs
|
||||
a,b = d['vin'],dt.txins
|
||||
a, b = d['vin'], dt.txins
|
||||
for i in range(len(a)):
|
||||
assert a[i]['txid'] == b[i]['txid'],f'TxID of input {i} does not match'
|
||||
assert a[i]['vout'] == b[i]['vout'],f'vout of input {i} does not match'
|
||||
assert a[i]['sequence'] == int(b[i]['nSeq'],16),(
|
||||
assert a[i]['txid'] == b[i]['txid'], f'TxID of input {i} does not match'
|
||||
assert a[i]['vout'] == b[i]['vout'], f'vout of input {i} does not match'
|
||||
assert a[i]['sequence'] == int(b[i]['nSeq'], 16), (
|
||||
f'nSeq of input {i} does not match')
|
||||
if 'txinwitness' in a[i]:
|
||||
assert a[i]['txinwitness'] == b[i]['witness'],(
|
||||
assert a[i]['txinwitness'] == b[i]['witness'], (
|
||||
f'witness of input {i} does not match')
|
||||
|
||||
# outputs
|
||||
a,b = d['vout'],dt.txouts
|
||||
a, b = d['vout'], dt.txouts
|
||||
for i in range(len(a)):
|
||||
if 'addresses' in a[i]['scriptPubKey']:
|
||||
A = a[i]['scriptPubKey']['addresses'][0]
|
||||
B = b[i]['address']
|
||||
fs = 'address of output {} does not match\nA: {}\nB: {}'
|
||||
assert A == B, fs.format(i,A,B)
|
||||
assert A == B, fs.format(i, A, B)
|
||||
|
||||
A = tx_proto.coin_amt(a[i]['value'])
|
||||
B = b[i]['amt']
|
||||
fs = 'value of output {} does not match\nA: {}\nB: {}'
|
||||
assert A == B, fs.format(i,A,B)
|
||||
assert A == B, fs.format(i, A, B)
|
||||
|
||||
A = a[i]['scriptPubKey']['hex']
|
||||
B = b[i]['scriptPubKey']
|
||||
fs = 'scriptPubKey of output {} does not match\nA: {}\nB: {}'
|
||||
assert A == B, fs.format(i,A,B)
|
||||
assert A == B, fs.format(i, A, B)
|
||||
|
||||
async def do_mmgen_ref(daemons,fns,name,desc):
|
||||
async def do_mmgen_ref(daemons, fns, name, desc):
|
||||
# NB: remove_datadir is required here for some reason (seems to be Bitcoin Core version-dependent)
|
||||
start_test_daemons(*daemons,remove_datadir=True)
|
||||
print_info(name,desc)
|
||||
for n,fn in enumerate(fns):
|
||||
tx = await CompletedTX( cfg=cfg, filename=fn, quiet_open=True )
|
||||
start_test_daemons(*daemons, remove_datadir=True)
|
||||
print_info(name, desc)
|
||||
for n, fn in enumerate(fns):
|
||||
tx = await CompletedTX(cfg=cfg, filename=fn, quiet_open=True)
|
||||
await test_tx(
|
||||
tx_proto = tx.proto,
|
||||
tx_hex = tx.serialized,
|
||||
desc = fn,
|
||||
n = n+1 )
|
||||
n = n + 1)
|
||||
stop_test_daemons(*daemons, remove_datadir=True)
|
||||
Msg('OK')
|
||||
return True
|
||||
|
|
@ -106,7 +106,7 @@ class unit_tests:
|
|||
|
||||
altcoin_deps = ('mmgen_ref_alt',)
|
||||
|
||||
async def core_vectors(self,name,ut):
|
||||
async def core_vectors(self, name, ut):
|
||||
|
||||
core_repo_root = os.getenv('CORE_REPO_ROOT')
|
||||
if not core_repo_root:
|
||||
|
|
@ -116,18 +116,18 @@ class unit_tests:
|
|||
start_test_daemons('btc')
|
||||
|
||||
fn_b = 'src/test/data/tx_valid.json'
|
||||
fn = os.path.join(core_repo_root,fn_b)
|
||||
fn = os.path.join(core_repo_root, fn_b)
|
||||
with open(fn) as fp:
|
||||
core_data = json.loads(fp.read())
|
||||
print_info(name,'Bitcoin Core test vectors')
|
||||
print_info(name, 'Bitcoin Core test vectors')
|
||||
n = 1
|
||||
for e in core_data:
|
||||
if isinstance(e[0],list):
|
||||
if isinstance(e[0], list):
|
||||
await test_tx(
|
||||
tx_proto = init_proto( cfg, 'btc', need_amt=True ),
|
||||
tx_proto = init_proto(cfg, 'btc', need_amt=True),
|
||||
tx_hex = e[1],
|
||||
desc = desc,
|
||||
n = n )
|
||||
n = n)
|
||||
n += 1
|
||||
else:
|
||||
desc = e[0]
|
||||
|
|
@ -136,24 +136,24 @@ class unit_tests:
|
|||
stop_test_daemons('btc', remove_datadir=True)
|
||||
return True
|
||||
|
||||
async def mmgen_ref(self,name,ut):
|
||||
async def mmgen_ref(self, name, ut):
|
||||
return await do_mmgen_ref(
|
||||
('btc','btc_tn'),
|
||||
('btc', 'btc_tn'),
|
||||
(
|
||||
'test/ref/0B8D5A[15.31789,14,tl=1320969600].rawtx',
|
||||
'test/ref/0C7115[15.86255,14,tl=1320969600].testnet.rawtx',
|
||||
'test/ref/542169[5.68152,34].sigtx',
|
||||
),
|
||||
name,
|
||||
'MMGen reference transactions [Bitcoin]' )
|
||||
'MMGen reference transactions [Bitcoin]')
|
||||
|
||||
async def mmgen_ref_alt(self,name,ut):
|
||||
async def mmgen_ref_alt(self, name, ut):
|
||||
return await do_mmgen_ref(
|
||||
('ltc','ltc_tn','bch'),
|
||||
('ltc', 'ltc_tn', 'bch'),
|
||||
(
|
||||
'test/ref/litecoin/AF3CDF-LTC[620.76194,1453,tl=1320969600].rawtx',
|
||||
'test/ref/litecoin/A5A1E0-LTC[1454.64322,1453,tl=1320969600].testnet.rawtx',
|
||||
'test/ref/460D4D-BCH[10.19764,tl=1320969600].rawtx'
|
||||
),
|
||||
name,
|
||||
'MMGen reference transactions [Altcoin]' )
|
||||
'MMGen reference transactions [Altcoin]')
|
||||
|
|
|
|||
|
|
@ -5,17 +5,17 @@ test.unit_tests_d.ut_misc: utility unit tests for the MMGen suite
|
|||
"""
|
||||
|
||||
from mmgen.color import cyan
|
||||
from mmgen.util import fmt_list,fmt_dict,list_gen
|
||||
from mmgen.util import fmt_list, fmt_dict, list_gen
|
||||
|
||||
from ..include.common import vmsg
|
||||
|
||||
class unit_tests:
|
||||
|
||||
def fmt_list(self,name,ut):
|
||||
def fmt_list(self, name, ut):
|
||||
|
||||
samples = {
|
||||
'pids': [18234,18444,19324],
|
||||
'vardata': [None,True,1234,'sample string'],
|
||||
'pids': [18234, 18444, 19324],
|
||||
'vardata': [None, True, 1234, 'sample string'],
|
||||
}
|
||||
chks = {
|
||||
'vardata': {
|
||||
|
|
@ -38,9 +38,9 @@ class unit_tests:
|
|||
for _name, sample in samples.items():
|
||||
vmsg(cyan(f'Input: {sample}'))
|
||||
for fmt in list(chks.values())[0]:
|
||||
spc = '\n' if fmt in ('col','list') else ' '
|
||||
spc = '\n' if fmt in ('col', 'list') else ' '
|
||||
indent = ' + ' if fmt == 'col' else ''
|
||||
res = fmt_list(sample,fmt=fmt,indent=indent) if fmt else fmt_list(sample,indent=indent)
|
||||
res = fmt_list(sample, fmt=fmt, indent=indent) if fmt else fmt_list(sample, indent=indent)
|
||||
vmsg(f' {str(fmt)+":":{col1_w}}{spc}{res}')
|
||||
if _name in chks:
|
||||
assert res == chks[_name][fmt], f'{res} != {chks[_name][fmt]}'
|
||||
|
|
@ -48,14 +48,14 @@ class unit_tests:
|
|||
vmsg('')
|
||||
return True
|
||||
|
||||
def fmt_dict(self,name,ut):
|
||||
def fmt_dict(self, name, ut):
|
||||
samples = {
|
||||
'url': {
|
||||
'name':'Example',
|
||||
'desc':'Sample URL',
|
||||
'name': 'Example',
|
||||
'desc': 'Sample URL',
|
||||
'rank': 1,
|
||||
'error': None,
|
||||
'url':'https://example.com/foobar.html',
|
||||
'url': 'https://example.com/foobar.html',
|
||||
},
|
||||
'choice': {
|
||||
'c': 'curl',
|
||||
|
|
@ -63,7 +63,7 @@ class unit_tests:
|
|||
'r': 'requests',
|
||||
},
|
||||
'cmdline': {
|
||||
'cmd': ["ls","-l"],
|
||||
'cmd': ['ls', '-l'],
|
||||
'text': 'foo bar',
|
||||
'stdin': None,
|
||||
'offset': 123,
|
||||
|
|
@ -87,7 +87,7 @@ class unit_tests:
|
|||
for _name, sample in samples.items():
|
||||
vmsg(cyan(f'Input: {sample}'))
|
||||
for fmt in list(chks.values())[0]:
|
||||
res = fmt_dict(sample,fmt=fmt) if fmt else fmt_dict(sample)
|
||||
res = fmt_dict(sample, fmt=fmt) if fmt else fmt_dict(sample)
|
||||
vmsg(f' {str(fmt)+":":{col1_w}} {res}')
|
||||
if _name in chks:
|
||||
assert res == chks[_name][fmt], f'{res} != {chks[_name][fmt]}'
|
||||
|
|
@ -95,13 +95,13 @@ class unit_tests:
|
|||
vmsg('')
|
||||
return True
|
||||
|
||||
def list_gen(self,name,ut):
|
||||
def list_gen(self, name, ut):
|
||||
res = list_gen(
|
||||
['a'],
|
||||
['b', False],
|
||||
['c', 'x'],
|
||||
['d', int],
|
||||
['e', None, 1, 'f', isinstance(7,int)],
|
||||
['e', None, 1, 'f', isinstance(7, int)],
|
||||
['g', 'h', 0],
|
||||
[None],
|
||||
[0],
|
||||
|
|
|
|||
|
|
@ -13,43 +13,44 @@ from ..include.common import cfg, vmsg
|
|||
class unit_tests:
|
||||
|
||||
vectors = ( # private keys are reduced
|
||||
( '148d78d2aba7dbca5cd8f6abcfb0b3c009ffbdbea1ff373d50ed94d78286640e', # Monero repo
|
||||
(
|
||||
'148d78d2aba7dbca5cd8f6abcfb0b3c009ffbdbea1ff373d50ed94d78286640e', # Monero repo
|
||||
'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches ' +
|
||||
'lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted',
|
||||
),
|
||||
( 'e8164dda6d42bd1e261a3406b2038dcbddadbeefdeadbeefdeadbeefdeadbe0f',
|
||||
), (
|
||||
'e8164dda6d42bd1e261a3406b2038dcbddadbeefdeadbeefdeadbeefdeadbe0f',
|
||||
'viewpoint donuts ardent template unveil agile meant unafraid urgent athlete rustled mime azure ' +
|
||||
'jaded hawk baby jagged haystack baby jagged haystack ramped oncoming point template'
|
||||
),
|
||||
( '6900dea9753f5c7ced87b53bdcfb109a8417bca6a2797a708194157b227fb60b',
|
||||
), (
|
||||
'6900dea9753f5c7ced87b53bdcfb109a8417bca6a2797a708194157b227fb60b',
|
||||
'criminal bamboo scamper gnaw limits womanly wrong tuition birth mundane donuts square cohesive ' +
|
||||
'dolphin titans narrate fuel saved wrap aloof magically mirror together update wrap'
|
||||
),
|
||||
( '0000000000000000000000000000000000000000000000000000000000000001',
|
||||
), (
|
||||
'0000000000000000000000000000000000000000000000000000000000000001',
|
||||
'abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey abbey ' +
|
||||
'abbey abbey abbey abbey abbey bamboo jaws jerseys abbey'
|
||||
),
|
||||
( '1c95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
|
||||
), (
|
||||
'1c95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
|
||||
'powder directed sayings enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying ' +
|
||||
'soil software foamy solved soggy foamy solved soggy jury yawning ankle solved'
|
||||
),
|
||||
( '2c94988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
|
||||
), (
|
||||
'2c94988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0f',
|
||||
'memoir apart olive enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying soil ' +
|
||||
'software foamy solved soggy foamy solved soggy jury yawning ankle foamy'
|
||||
),
|
||||
( '4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364102',
|
||||
), (
|
||||
'4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364102',
|
||||
'rated bicycle pheasants dejected pouch fizzle shipped rash citadel queen avatar sample muzzle mews ' +
|
||||
'jagged origin yeti dunes obtains godfather unbending pastry vortex washing citadel'
|
||||
),
|
||||
( '4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364100',
|
||||
), (
|
||||
'4bb0288c9673b69fa68c2174851884abbaaedce6af48a03bbfd25e8cd0364100',
|
||||
'rated bicycle pheasants dejected pouch fizzle shipped rash citadel queen avatar sample muzzle mews ' +
|
||||
'jagged origin yeti dunes obtains godfather unbending kangaroo auctions audio citadel'
|
||||
),
|
||||
( '1d95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0e',
|
||||
), (
|
||||
'1d95988d7431ecd670cf7d73f45befc6feffffffffffffffffffffffffffff0e',
|
||||
'pram distance scamper enmity bacon vapidly entrance bumper noodles iguana sleepless nasty flying ' +
|
||||
'soil software foamy solved soggy foamy solved soggy hashing mullet onboard solved'
|
||||
),
|
||||
( 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0f',
|
||||
), (
|
||||
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0f',
|
||||
'foamy solved soggy foamy solved soggy foamy solved soggy foamy solved soggy foamy solved soggy ' +
|
||||
'foamy solved soggy foamy solved soggy jury yawning ankle soggy'
|
||||
),
|
||||
|
|
@ -57,7 +58,7 @@ class unit_tests:
|
|||
|
||||
@property
|
||||
def _use_monero_python(self):
|
||||
if not hasattr(self,'_use_monero_python_'):
|
||||
if not hasattr(self, '_use_monero_python_'):
|
||||
try:
|
||||
from monero.wordlists.english import English
|
||||
self.wl = English()
|
||||
|
|
@ -80,7 +81,7 @@ class unit_tests:
|
|||
chk = tuple(chk.split())
|
||||
res = b.fromhex(privhex)
|
||||
if self._use_monero_python:
|
||||
mp_chk = tuple( self.wl.encode(privhex).split() )
|
||||
mp_chk = tuple(self.wl.encode(privhex).split())
|
||||
assert res == mp_chk, f'check failed:\nres: {res}\nchk: {chk}'
|
||||
assert res == chk, f'check failed:\nres: {res}\nchk: {chk}'
|
||||
return True
|
||||
|
|
@ -90,9 +91,9 @@ class unit_tests:
|
|||
vmsg('Checking mnemonic to seed conversion:')
|
||||
for chk, words in self.vectors:
|
||||
vmsg(f' {chk}')
|
||||
res = b.tohex( words.split() )
|
||||
res = b.tohex(words.split())
|
||||
if self._use_monero_python:
|
||||
mp_chk = self.wl.decode( words )
|
||||
mp_chk = self.wl.decode(words)
|
||||
assert res == mp_chk, f'check failed:\nres: {res}\nchk: {mp_chk}'
|
||||
assert res == chk, f'check failed:\nres: {res}\nchk: {chk}'
|
||||
return True
|
||||
|
|
@ -119,8 +120,8 @@ class unit_tests:
|
|||
('hex', hse, 'not a hexadecimal', lambda: fh('xx')),
|
||||
('seed len', sle, 'invalid seed byte len', lambda: fh(bad_seed)),
|
||||
('mnemonic type', ase, 'must be list', lambda: th('string')),
|
||||
('pad arg (fromhex)', ase, "invalid 'pad' arg", lambda: fh(good_hex,pad=23)),
|
||||
('pad arg (tohex)', ase, "invalid 'pad' arg", lambda: th(good_mn,pad=23)),
|
||||
('pad arg (fromhex)', ase, "invalid 'pad' arg", lambda: fh(good_hex, pad=23)),
|
||||
('pad arg (tohex)', ase, "invalid 'pad' arg", lambda: th(good_mn, pad=23)),
|
||||
('word', mne, "not in Monero", lambda: th(bad_word_mn)),
|
||||
('checksum', mne, "checksum", lambda: th(bad_chksum_mn)),
|
||||
('seed phrase len', mne, "phrase len", lambda: th(bad_len_mn)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue