py3port: make hexadecimal values be strings instead of bytes type
- binascii.hexlify(b'foo') -> b'foo'.hex()
- binascii.unhexlify('aabb') -> bytes.fromhex('aabb')
- replace HexBytes class with HexStr
This change has led to a ≈10% speedup in the full test-release.sh run
This commit is contained in:
parent
d7913524b2
commit
b5f1ebc640
24 changed files with 222 additions and 263 deletions
|
|
@ -21,7 +21,6 @@ addr.py: Address generation/display routines for the MMGen suite
|
|||
"""
|
||||
|
||||
from hashlib import sha256,sha512
|
||||
from binascii import hexlify,unhexlify
|
||||
from mmgen.common import *
|
||||
from mmgen.obj import *
|
||||
|
||||
|
|
@ -67,7 +66,7 @@ class AddrGeneratorSegwit(AddrGenerator):
|
|||
|
||||
def to_segwit_redeem_script(self,pubhex):
|
||||
assert pubhex.compressed,'Uncompressed public keys incompatible with Segwit'
|
||||
return HexBytes(g.proto.pubhex2redeem_script(pubhex))
|
||||
return HexStr(g.proto.pubhex2redeem_script(pubhex))
|
||||
|
||||
class AddrGeneratorBech32(AddrGenerator):
|
||||
def to_addr(self,pubhex):
|
||||
|
|
@ -82,7 +81,7 @@ class AddrGeneratorEthereum(AddrGenerator):
|
|||
def to_addr(self,pubhex):
|
||||
assert type(pubhex) == PubKey
|
||||
import sha3
|
||||
return CoinAddr(hexlify(sha3.keccak_256(unhexlify(pubhex[2:])).digest()[12:]).decode())
|
||||
return CoinAddr(sha3.keccak_256(bytes.fromhex(pubhex[2:])).hexdigest()[24:])
|
||||
|
||||
def to_wallet_passwd(self,sk_hex):
|
||||
from mmgen.protocol import hash256
|
||||
|
|
@ -105,26 +104,26 @@ class AddrGeneratorZcashZ(AddrGenerator):
|
|||
return Sha256(s,preprocess=False).digest()
|
||||
|
||||
def to_addr(self,pubhex): # pubhex is really privhex
|
||||
key = unhexlify(pubhex)
|
||||
key = bytes.fromhex(pubhex)
|
||||
assert len(key) == 32,'{}: incorrect privkey length'.format(len(key))
|
||||
if g.platform == 'win':
|
||||
ydie(1,'Zcash z-addresses not supported on Windows platform')
|
||||
from nacl.bindings import crypto_scalarmult_base
|
||||
p2 = crypto_scalarmult_base(self.zhash256(key,1))
|
||||
from mmgen.protocol import _b58chk_encode
|
||||
ret = _b58chk_encode(g.proto.addr_ver_num['zcash_z'][0] + hexlify(self.zhash256(key,0)+p2))
|
||||
ret = _b58chk_encode(g.proto.addr_ver_num['zcash_z'][0] + (self.zhash256(key,0)+p2).hex())
|
||||
assert len(ret) == self.addr_width,'Invalid Zcash z-address length'
|
||||
return CoinAddr(ret)
|
||||
|
||||
def to_viewkey(self,pubhex): # pubhex is really privhex
|
||||
key = unhexlify(pubhex)
|
||||
key = bytes.fromhex(pubhex)
|
||||
assert len(key) == 32,'{}: incorrect privkey length'.format(len(key))
|
||||
vk = bytearray(self.zhash256(key,0)+self.zhash256(key,1))
|
||||
vk[32] &= 0xf8
|
||||
vk[63] &= 0x7f
|
||||
vk[63] |= 0x40
|
||||
from mmgen.protocol import _b58chk_encode
|
||||
ret = _b58chk_encode(g.proto.addr_ver_num['viewkey'][0] + hexlify(vk))
|
||||
ret = _b58chk_encode(g.proto.addr_ver_num['viewkey'][0] + vk.hex())
|
||||
assert len(ret) == self.vk_width,'Invalid Zcash view key length'
|
||||
return ZcashViewKey(ret)
|
||||
|
||||
|
|
@ -133,10 +132,11 @@ class AddrGeneratorZcashZ(AddrGenerator):
|
|||
|
||||
class AddrGeneratorMonero(AddrGenerator):
|
||||
|
||||
def b58enc(self,addr_str):
|
||||
enc,l = baseconv.fromhex,len(addr_str)
|
||||
a = ''.join([enc(hexlify(addr_str[i*8:i*8+8]),'b58',pad=11,tostr=True) for i in range(l//8)])
|
||||
b = enc(hexlify(addr_str[l-l%8:]),'b58',pad=7,tostr=True)
|
||||
def b58enc(self,addr_bytes):
|
||||
enc = baseconv.fromhex
|
||||
l = len(addr_bytes)
|
||||
a = ''.join([enc((addr_bytes[i*8:i*8+8]).hex(),'b58',pad=11,tostr=True) for i in range(l//8)])
|
||||
b = enc((addr_bytes[l-l%8:]).hex(),'b58',pad=7,tostr=True)
|
||||
return a + b
|
||||
|
||||
def to_addr(self,sk_hex): # sk_hex instead of pubhex
|
||||
|
|
@ -159,12 +159,12 @@ class AddrGeneratorMonero(AddrGenerator):
|
|||
return Q
|
||||
|
||||
def hex2int_le(hexstr):
|
||||
return int(hexlify(unhexlify(hexstr)[::-1]),16)
|
||||
return int((bytes.fromhex(hexstr)[::-1]).hex(),16)
|
||||
|
||||
vk_hex = self.to_viewkey(sk_hex)
|
||||
pk_str = encodepoint(scalarmultbase(hex2int_le(sk_hex)))
|
||||
pvk_str = encodepoint(scalarmultbase(hex2int_le(vk_hex)))
|
||||
addr_p1 = unhexlify(g.proto.addr_ver_num['monero'][0]) + pk_str + pvk_str
|
||||
addr_p1 = bytes.fromhex(g.proto.addr_ver_num['monero'][0]) + pk_str + pvk_str
|
||||
|
||||
import sha3
|
||||
return CoinAddr(self.b58enc(addr_p1 + sha3.keccak_256(addr_p1).digest()[:4]))
|
||||
|
|
@ -176,7 +176,7 @@ class AddrGeneratorMonero(AddrGenerator):
|
|||
def to_viewkey(self,sk_hex):
|
||||
assert len(sk_hex) == 64,'{}: incorrect privkey length'.format(len(sk_hex))
|
||||
import sha3
|
||||
return MoneroViewKey(g.proto.preprocess_key(sha3.keccak_256(unhexlify(sk_hex)).hexdigest(),None))
|
||||
return MoneroViewKey(g.proto.preprocess_key(sha3.keccak_256(bytes.fromhex(sk_hex)).hexdigest(),None))
|
||||
|
||||
def to_segwit_redeem_script(self,sk_hex):
|
||||
raise NotImplementedError('Monero addresses incompatible with Segwit')
|
||||
|
|
@ -210,7 +210,7 @@ class KeyGenerator(MMGenObject):
|
|||
try:
|
||||
from mmgen.secp256k1 import priv2pub
|
||||
m = 'Unable to execute priv2pub() from secp256k1 extension module'
|
||||
assert priv2pub(unhexlify('deadbeef'*8),1),m
|
||||
assert priv2pub(bytes.fromhex('deadbeef'*8),1),m
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
|
@ -239,12 +239,12 @@ class KeyGeneratorPython(KeyGenerator):
|
|||
def privnum2pubhex(self,numpriv,compressed=False):
|
||||
pko = ecdsa.SigningKey.from_secret_exponent(numpriv,self.secp256k1)
|
||||
# pubkey = x (32 bytes) + y (32 bytes) (unsigned big-endian)
|
||||
pubkey = hexlify(pko.get_verifying_key().to_string())
|
||||
pubkey = (pko.get_verifying_key().to_string()).hex()
|
||||
if compressed: # discard Y coord, replace with appropriate version byte
|
||||
# even y: <0, odd y: >0 -- https://bitcointalk.org/index.php?topic=129652.0
|
||||
return (b'03',b'02')[pubkey[-1] in b'02468ace'] + pubkey[:64]
|
||||
return ('03','02')[pubkey[-1] in '02468ace'] + pubkey[:64]
|
||||
else:
|
||||
return b'04' + pubkey
|
||||
return '04' + pubkey
|
||||
|
||||
def to_pubhex(self,privhex):
|
||||
assert type(privhex) == PrivKey
|
||||
|
|
@ -256,13 +256,13 @@ class KeyGeneratorSecp256k1(KeyGenerator):
|
|||
def to_pubhex(self,privhex):
|
||||
assert type(privhex) == PrivKey
|
||||
from mmgen.secp256k1 import priv2pub
|
||||
return PubKey(hexlify(priv2pub(unhexlify(privhex),int(privhex.compressed))),compressed=privhex.compressed)
|
||||
return PubKey(priv2pub(bytes.fromhex(privhex),int(privhex.compressed)).hex(),compressed=privhex.compressed)
|
||||
|
||||
class KeyGeneratorDummy(KeyGenerator):
|
||||
desc = 'mmgen-dummy'
|
||||
def to_pubhex(self,privhex):
|
||||
assert type(privhex) == PrivKey
|
||||
return PubKey(privhex.decode(),compressed=privhex.compressed)
|
||||
return PubKey(privhex,compressed=privhex.compressed)
|
||||
|
||||
class AddrListEntry(MMGenListItem):
|
||||
addr = MMGenListItemAttr('addr','CoinAddr')
|
||||
|
|
@ -404,7 +404,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
|
|||
|
||||
seed = seed.get_data()
|
||||
seed = self.scramble_seed(seed)
|
||||
dmsg_sc('seed',hexlify(seed[:8]).decode())
|
||||
dmsg_sc('seed',seed[:8].hex())
|
||||
|
||||
compressed = self.al_id.mmtype.compressed
|
||||
pubkey_type = self.al_id.mmtype.pubkey_type
|
||||
|
|
@ -838,7 +838,7 @@ Record this checksum: it will be used to verify the password file in the future
|
|||
def make_passwd(self,hex_sec):
|
||||
assert self.pw_fmt in self.pw_info
|
||||
if self.pw_fmt == 'hex':
|
||||
return hex_sec.decode()
|
||||
return hex_sec
|
||||
else:
|
||||
# we take least significant part
|
||||
return baseconv.fromhex(hex_sec,self.pw_fmt,pad=self.pw_len,tostr=True)[-self.pw_len:]
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ class Token(MMGenObject): # ERC20
|
|||
except:
|
||||
"RPC call to decimals() failed (returned '{}')".format(ret)
|
||||
return int(b,16) if b else None
|
||||
def name(self): return self.strip(unhexlify(self.do_call('name()')[2:]))
|
||||
def symbol(self): return self.strip(unhexlify(self.do_call('symbol()')[2:]))
|
||||
def name(self): return self.strip(bytes.fromhex(self.do_call('name()')[2:]))
|
||||
def symbol(self): return self.strip(bytes.fromhex(self.do_call('symbol()')[2:]))
|
||||
|
||||
def info(self):
|
||||
fs = '{:15}{}\n' * 5
|
||||
|
|
@ -95,12 +95,12 @@ class Token(MMGenObject): # ERC20
|
|||
if nonce is None:
|
||||
nonce = int(g.rpch.parity_nextNonce('0x'+from_addr),16)
|
||||
data = self.create_data(to_addr,amt,method_sig=method_sig,from_addr=from_addr2)
|
||||
return {'to': unhexlify(self.addr),
|
||||
return {'to': bytes.fromhex(self.addr),
|
||||
'startgas': start_gas.toWei(),
|
||||
'gasprice': gasPrice.toWei(),
|
||||
'value': 0,
|
||||
'nonce': nonce,
|
||||
'data': unhexlify(data) }
|
||||
'data': bytes.fromhex(data) }
|
||||
|
||||
def txsign(self,tx_in,key,from_addr,chain_id=None):
|
||||
from ethereum.transactions import Transaction
|
||||
|
|
@ -108,11 +108,11 @@ class Token(MMGenObject): # ERC20
|
|||
chain_id_method = ('parity_chainId','eth_chainId')['eth_chainId' in g.rpch.caps]
|
||||
chain_id = int(g.rpch.request(chain_id_method),16)
|
||||
tx = Transaction(**tx_in).sign(key,chain_id)
|
||||
hex_tx = hexlify(rlp.encode(tx))
|
||||
coin_txid = CoinTxID(hexlify(tx.hash))
|
||||
if hexlify(tx.sender).decode() != from_addr:
|
||||
hex_tx = rlp.encode(tx).hex()
|
||||
coin_txid = CoinTxID(tx.hash.hex())
|
||||
if tx.sender.hex() != from_addr:
|
||||
m = "Sender address '{}' does not match address of key '{}'!"
|
||||
die(3,m.format(from_addr,hexlify(tx.sender).decode()))
|
||||
die(3,m.format(from_addr,tx.sender.hex()))
|
||||
if g.debug:
|
||||
msg('{}'.format('\n '.join(parse_abi(data))))
|
||||
pmsg(tx.to_dict())
|
||||
|
|
@ -121,7 +121,7 @@ class Token(MMGenObject): # ERC20
|
|||
# The following are used for token deployment only:
|
||||
|
||||
def txsend(self,hex_tx):
|
||||
return g.rpch.eth_sendRawTransaction('0x'+hex_tx.decode()).replace('0x','',1).encode()
|
||||
return g.rpch.eth_sendRawTransaction('0x'+hex_tx).replace('0x','',1)
|
||||
|
||||
def transfer( self,from_addr,to_addr,amt,key,start_gas,gasPrice,
|
||||
method_sig='transfer(address,uint256)',
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class EthereumMMGenTX(MMGenTX):
|
|||
usr_rel_fee = None # not in MMGenTX
|
||||
disable_fee_check = False
|
||||
txobj = None # ""
|
||||
data = HexBytes('')
|
||||
data = HexStr('')
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
super(EthereumMMGenTX,self).__init__(*args,**kwargs)
|
||||
|
|
@ -53,16 +53,16 @@ class EthereumMMGenTX(MMGenTX):
|
|||
if hasattr(opt,'contract_data') and opt.contract_data:
|
||||
m = "'--contract-data' option may not be used with token transaction"
|
||||
assert not 'Token' in type(self).__name__, m
|
||||
self.data = HexBytes(open(opt.contract_data).read().strip())
|
||||
self.data = HexStr(open(opt.contract_data).read().strip())
|
||||
self.disable_fee_check = True
|
||||
|
||||
@classmethod
|
||||
def get_receipt(cls,txid):
|
||||
return g.rpch.eth_getTransactionReceipt('0x'+txid.decode())
|
||||
return g.rpch.eth_getTransactionReceipt('0x'+txid)
|
||||
|
||||
@classmethod
|
||||
def get_exec_status(cls,txid,silent=False):
|
||||
d = g.rpch.eth_getTransactionReceipt('0x'+txid.decode())
|
||||
d = g.rpch.eth_getTransactionReceipt('0x'+txid)
|
||||
if not silent:
|
||||
if 'contractAddress' in d and d['contractAddress']:
|
||||
msg('Contract address: {}'.format(d['contractAddress'].replace('0x','')))
|
||||
|
|
@ -82,18 +82,17 @@ class EthereumMMGenTX(MMGenTX):
|
|||
def check_pubkey_scripts(self): pass
|
||||
|
||||
def check_sigs(self,deserial_tx=None):
|
||||
if is_hex_bytes(self.hex):
|
||||
if is_hex_str(self.hex):
|
||||
self.mark_signed()
|
||||
return True
|
||||
return False
|
||||
|
||||
# hex data if signed, json if unsigned: see create_raw()
|
||||
def check_txfile_hex_data(self):
|
||||
if type(self.hex) == str: self.hex = self.hex.encode()
|
||||
if self.check_sigs():
|
||||
from ethereum.transactions import Transaction
|
||||
import rlp
|
||||
etx = rlp.decode(unhexlify(self.hex),Transaction)
|
||||
etx = rlp.decode(bytes.fromhex(self.hex),Transaction)
|
||||
d = etx.to_dict() # ==> hex values have '0x' prefix, 0 is '0x'
|
||||
for k in ('sender','to','data'):
|
||||
if k in d: d[k] = d[k].replace('0x','',1)
|
||||
|
|
@ -103,13 +102,13 @@ class EthereumMMGenTX(MMGenTX):
|
|||
'gasPrice': ETHAmt(d['gasprice'],'wei'),
|
||||
'startGas': ETHAmt(d['startgas'],'wei'),
|
||||
'nonce': ETHNonce(d['nonce']),
|
||||
'data': HexBytes(d['data']) }
|
||||
'data': HexStr(d['data']) }
|
||||
if o['data'] and not o['to']:
|
||||
self.token_addr = TokenAddr(hexlify(etx.creates).decode())
|
||||
txid = CoinTxID(hexlify(etx.hash))
|
||||
self.token_addr = TokenAddr(etx.creates.hex())
|
||||
txid = CoinTxID(etx.hash.hex())
|
||||
assert txid == self.coin_txid,"txid in tx.hex doesn't match value in MMGen transaction file"
|
||||
else:
|
||||
d = json.loads(self.hex.decode())
|
||||
d = json.loads(self.hex)
|
||||
o = { 'from': CoinAddr(d['from']),
|
||||
'to': CoinAddr(d['to']) if d['to'] else Str(''),
|
||||
'amt': ETHAmt(d['amt']),
|
||||
|
|
@ -117,7 +116,7 @@ class EthereumMMGenTX(MMGenTX):
|
|||
'startGas': ETHAmt(d['startGas']),
|
||||
'nonce': ETHNonce(d['nonce']),
|
||||
'chainId': Int(d['chainId']),
|
||||
'data': HexBytes(d['data']) }
|
||||
'data': HexStr(d['data']) }
|
||||
self.tx_gas = o['startGas'] # approximate, but better than nothing
|
||||
self.data = o['data']
|
||||
if o['data'] and not o['to']: self.disable_fee_check = True
|
||||
|
|
@ -151,7 +150,7 @@ class EthereumMMGenTX(MMGenTX):
|
|||
assert o_num in o_ok,'Transaction has invalid number of outputs!'.format(o_num)
|
||||
self.make_txobj()
|
||||
ol = {k: (v.decode() if issubclass(type(v),bytes) else str(v)) for k,v in self.txobj.items()}
|
||||
self.hex = json.dumps(ol).encode()
|
||||
self.hex = json.dumps(ol)
|
||||
self.update_txid()
|
||||
|
||||
def del_output(self,idx): pass
|
||||
|
|
@ -278,22 +277,22 @@ class EthereumMMGenTX(MMGenTX):
|
|||
return m.format(ETHAmt(chg).hl(),g.coin)
|
||||
|
||||
def do_sign(self,d,wif,tx_num_str):
|
||||
d_in = {'to': unhexlify(d['to']),
|
||||
d_in = {'to': bytes.fromhex(d['to']),
|
||||
'startgas': d['startGas'].toWei(),
|
||||
'gasprice': d['gasPrice'].toWei(),
|
||||
'value': d['amt'].toWei() if d['amt'] else 0,
|
||||
'nonce': d['nonce'],
|
||||
'data': unhexlify(d['data'])}
|
||||
'data': bytes.fromhex(d['data'])}
|
||||
|
||||
from ethereum.transactions import Transaction
|
||||
etx = Transaction(**d_in).sign(wif,d['chainId'])
|
||||
assert hexlify(etx.sender).decode() == d['from'],(
|
||||
assert etx.sender.hex() == d['from'],(
|
||||
'Sender address recovered from signature does not match true sender')
|
||||
import rlp
|
||||
self.hex = hexlify(rlp.encode(etx))
|
||||
self.coin_txid = CoinTxID(hexlify(etx.hash))
|
||||
self.hex = rlp.encode(etx).hex()
|
||||
self.coin_txid = CoinTxID(etx.hash.hex())
|
||||
if d['data']:
|
||||
self.token_addr = TokenAddr(hexlify(etx.creates).decode())
|
||||
self.token_addr = TokenAddr(etx.creates.hex())
|
||||
assert self.check_sigs(),'Signature check failed'
|
||||
|
||||
def sign(self,tx_num_str,keys): # return True or False; don't exit or raise exception
|
||||
|
|
@ -320,10 +319,10 @@ class EthereumMMGenTX(MMGenTX):
|
|||
return False
|
||||
|
||||
def is_in_mempool(self):
|
||||
return '0x'+self.coin_txid.decode() in [x['hash'] for x in g.rpch.parity_pendingTransactions()]
|
||||
return '0x'+self.coin_txid in [x['hash'] for x in g.rpch.parity_pendingTransactions()]
|
||||
|
||||
def is_in_wallet(self):
|
||||
d = g.rpch.eth_getTransactionReceipt('0x'+self.coin_txid.decode())
|
||||
d = g.rpch.eth_getTransactionReceipt('0x'+self.coin_txid)
|
||||
if d and 'blockNumber' in d and d['blockNumber'] is not None:
|
||||
return 1 + int(g.rpch.eth_blockNumber(),16) - int(d['blockNumber'],16)
|
||||
return False
|
||||
|
|
@ -365,7 +364,7 @@ class EthereumMMGenTX(MMGenTX):
|
|||
|
||||
if prompt_user: self.confirm_send()
|
||||
|
||||
ret = None if bogus_send else g.rpch.eth_sendRawTransaction('0x'+self.hex.decode(),on_fail='return')
|
||||
ret = None if bogus_send else g.rpch.eth_sendRawTransaction('0x'+self.hex,on_fail='return')
|
||||
|
||||
from mmgen.rpc import rpc_error,rpc_errmsg
|
||||
if rpc_error(ret):
|
||||
|
|
@ -376,7 +375,7 @@ class EthereumMMGenTX(MMGenTX):
|
|||
else:
|
||||
m = 'BOGUS transaction NOT sent: {}' if bogus_send else 'Transaction sent: {}'
|
||||
if not bogus_send:
|
||||
assert ret == '0x'+self.coin_txid.decode(),'txid mismatch (after sending)'
|
||||
assert ret == '0x'+self.coin_txid,'txid mismatch (after sending)'
|
||||
self.desc = 'sent transaction'
|
||||
msg(m.format(self.coin_txid.hl()))
|
||||
self.add_timestamp()
|
||||
|
|
@ -418,8 +417,8 @@ class EthereumTokenMMGenTX(EthereumMMGenTX):
|
|||
|
||||
def set_g_token(self):
|
||||
g.dcoin = self.dcoin
|
||||
if is_hex_bytes(self.hex): return # for txsend we can leave g.token uninitialized
|
||||
d = json.loads(self.hex.decode())
|
||||
if is_hex_str(self.hex): return # for txsend we can leave g.token uninitialized
|
||||
d = json.loads(self.hex)
|
||||
if g.token.upper() == self.dcoin:
|
||||
g.token = d['token_addr']
|
||||
elif g.token != d['token_addr']:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
crypto.py: Cryptographic and related routines for the MMGen suite
|
||||
"""
|
||||
|
||||
from binascii import hexlify
|
||||
from hashlib import sha256
|
||||
|
||||
from mmgen.common import *
|
||||
|
|
@ -46,7 +45,7 @@ def scramble_seed(seed,scramble_key,hash_rounds):
|
|||
import hmac
|
||||
scr_seed = hmac.new(seed,scramble_key,sha256).digest()
|
||||
fs = 'Seed: {}\nScramble key: {}\nScrambled seed: {}'
|
||||
dmsg(fs.format(hexlify(seed),scramble_key.decode('utf8'),hexlify(scr_seed)))
|
||||
dmsg(fs.format(seed.hex(),scramble_key.decode(),scr_seed.hex()))
|
||||
return sha256_rounds(scr_seed,hash_rounds)
|
||||
|
||||
def encrypt_seed(seed,key):
|
||||
|
|
@ -77,7 +76,7 @@ def decrypt_seed(enc_seed,key,seed_id,key_id):
|
|||
# else:
|
||||
# qmsg('Generated IDs (Seed/Key): {}/{}'.format(chk2,chk1))
|
||||
|
||||
dmsg('Decrypted seed: {}'.format(hexlify(dec_seed)))
|
||||
dmsg('Decrypted seed: {}'.format(dec_seed.hex()))
|
||||
return dec_seed
|
||||
|
||||
def encrypt_data(data,key,iv=1,desc='data',verify=True):
|
||||
|
|
@ -120,7 +119,7 @@ def make_key(passwd,salt,hash_preset,desc='encryption key',from_what='passphrase
|
|||
msg_r('Generating {}{}...'.format(desc,from_what))
|
||||
key = scrypt_hash_passphrase(passwd,salt,hash_preset)
|
||||
if opt.verbose or verbose: msg('done')
|
||||
dmsg('Key: {}'.format(hexlify(key)))
|
||||
dmsg('Key: {}'.format(key.hex()))
|
||||
return key
|
||||
|
||||
def _get_random_data_from_user(uchars):
|
||||
|
|
@ -189,7 +188,7 @@ def mmgen_encrypt(data,desc='data',hash_preset=''):
|
|||
qmsg("Using {} hash preset of '{}'".format(m,hp))
|
||||
passwd = get_new_passphrase(desc,{})
|
||||
key = make_key(passwd,salt,hp)
|
||||
enc_d = encrypt_data(sha256(nonce+data).digest()+nonce+data,key,int(hexlify(iv),16),desc=desc)
|
||||
enc_d = encrypt_data(sha256(nonce+data).digest()+nonce+data,key,int(iv.hex(),16),desc=desc)
|
||||
return salt+iv+enc_d
|
||||
|
||||
def mmgen_decrypt(data,desc='data',hash_preset=''):
|
||||
|
|
@ -204,7 +203,7 @@ def mmgen_decrypt(data,desc='data',hash_preset=''):
|
|||
qmsg("Using {} hash preset of '{}'".format(m,hp))
|
||||
passwd = get_mmgen_passphrase(desc)
|
||||
key = make_key(passwd,salt,hp)
|
||||
dec_d = decrypt_data(enc_d,key,int(hexlify(iv),16),desc)
|
||||
dec_d = decrypt_data(enc_d,key,int(iv.hex(),16),desc)
|
||||
if dec_d[:_sha256_len] == sha256(dec_d[_sha256_len:]).digest():
|
||||
vmsg('OK')
|
||||
return dec_d[_sha256_len+_nonce_len:]
|
||||
|
|
|
|||
|
|
@ -269,13 +269,12 @@ def wipe_existing_key():
|
|||
subprocess.call(['wipe','-cf',fn])
|
||||
|
||||
def create_key():
|
||||
from binascii import hexlify
|
||||
kdata = hexlify(os.urandom(32)).decode()
|
||||
kdata = os.urandom(32).hex()
|
||||
fn = os.path.join(tx_dir,key_fn)
|
||||
desc = 'key file {}'.format(fn)
|
||||
msg('Creating ' + desc)
|
||||
try:
|
||||
with open(fn,'w') as f: f.write(kdata+'\n')
|
||||
open(fn,'w').write(kdata+'\n')
|
||||
os.chmod(fn,0o400)
|
||||
msg('Wrote ' + desc)
|
||||
except:
|
||||
|
|
|
|||
46
mmgen/obj.py
46
mmgen/obj.py
|
|
@ -24,7 +24,6 @@ import sys,os,unicodedata
|
|||
from decimal import *
|
||||
from mmgen.color import *
|
||||
from string import hexdigits,ascii_letters,digits
|
||||
from binascii import hexlify
|
||||
|
||||
def is_mmgen_seed_id(s): return SeedID(sid=s,on_fail='silent')
|
||||
def is_mmgen_idx(s): return AddrIdx(s,on_fail='silent')
|
||||
|
|
@ -562,20 +561,19 @@ class TwLabel(str,InitErrors,MMGenObject):
|
|||
m = "{}\n{!r}: value cannot be converted to TwLabel"
|
||||
return cls.init_fail(m.format(e.args[0],s),on_fail)
|
||||
|
||||
class HexBytes(bytes,Hilite,InitErrors):
|
||||
class HexStr(str,Hilite,InitErrors):
|
||||
color = 'red'
|
||||
trunc_ok = False
|
||||
dtype = bytes
|
||||
dtype = str
|
||||
def __new__(cls,s,on_fail='die',case='lower'):
|
||||
if type(s) == cls: return s
|
||||
assert case in ('upper','lower')
|
||||
cls.arg_chk(cls,on_fail)
|
||||
if issubclass(type(s),bytes): s = s.decode()
|
||||
try:
|
||||
assert type(s) == str,'not a string'
|
||||
assert issubclass(type(s),str),'not a string or string subclass'
|
||||
assert set(s) <= set(getattr(hexdigits,case)()),'not {}case hexadecimal symbols'.format(case)
|
||||
assert not len(s) % 2,'odd-length string'
|
||||
return cls.dtype.__new__(cls,s.encode() if cls.dtype == bytes else s)
|
||||
return cls.dtype.__new__(cls,s)
|
||||
except Exception as e:
|
||||
m = "{!r}: value cannot be converted to {} (value is {})"
|
||||
return cls.init_fail(m.format(s,cls.__name__,e.args[0]),on_fail)
|
||||
|
|
@ -583,11 +581,11 @@ class HexBytes(bytes,Hilite,InitErrors):
|
|||
class Str(str,Hilite): pass
|
||||
class Int(int,Hilite): pass
|
||||
|
||||
class HexBytesWithWidth(HexBytes):
|
||||
class HexStrWithWidth(HexStr):
|
||||
color = 'nocolor'
|
||||
hexcase = 'lower'
|
||||
width = None
|
||||
parent_cls = HexBytes
|
||||
parent_cls = HexStr
|
||||
def __new__(cls,s,on_fail='die'):
|
||||
cls.arg_chk(cls,on_fail)
|
||||
try:
|
||||
|
|
@ -598,23 +596,7 @@ class HexBytesWithWidth(HexBytes):
|
|||
m = "{}\n{!r}: value cannot be converted to {}"
|
||||
return cls.init_fail(m.format(e.args[0],s,cls.__name__),on_fail)
|
||||
|
||||
class CoinTxID(HexBytesWithWidth): color,width,hexcase = 'purple',64,'lower'
|
||||
|
||||
class HexStr(str,Hilite,InitErrors):
|
||||
color = 'red'
|
||||
trunc_ok = False
|
||||
dtype = str
|
||||
def __new__(cls,s,on_fail='die',case='lower'):
|
||||
return HexBytes.__new__(cls,s,on_fail=on_fail,case=case)
|
||||
|
||||
class HexStrWithWidth(HexStr):
|
||||
color = 'nocolor'
|
||||
hexcase = 'lower'
|
||||
width = None
|
||||
parent_cls = HexStr
|
||||
def __new__(cls,s,on_fail='die'):
|
||||
return HexBytesWithWidth.__new__(cls,s,on_fail=on_fail)
|
||||
|
||||
class CoinTxID(HexStrWithWidth): color,width,hexcase = 'purple',64,'lower'
|
||||
class WalletPassword(HexStrWithWidth): color,width,hexcase = 'blue',32,'lower'
|
||||
class MoneroViewKey(HexStrWithWidth): color,width,hexcase = 'cyan',64,'lower'
|
||||
class MMGenTxID(HexStrWithWidth): color,width,hexcase = 'red',6,'upper'
|
||||
|
|
@ -634,18 +616,18 @@ class WifKey(str,Hilite,InitErrors):
|
|||
m = '{!r}: invalid value for WIF key ({})'.format(s,e.args[0])
|
||||
return cls.init_fail(m,on_fail)
|
||||
|
||||
class PubKey(HexBytes,MMGenObject): # TODO: add some real checks
|
||||
class PubKey(HexStr,MMGenObject): # TODO: add some real checks
|
||||
def __new__(cls,s,compressed,on_fail='die'):
|
||||
try:
|
||||
assert type(compressed) == bool,"'compressed' must be of type bool"
|
||||
me = HexBytes.__new__(cls,s,case='lower',on_fail='raise')
|
||||
me = HexStr.__new__(cls,s,case='lower',on_fail='raise')
|
||||
me.compressed = compressed
|
||||
return me
|
||||
except Exception as e:
|
||||
m = '{!r}: invalid value for pubkey ({})'.format(s,e.args[0])
|
||||
return cls.init_fail(m,on_fail)
|
||||
|
||||
class PrivKey(bytes,Hilite,InitErrors,MMGenObject):
|
||||
class PrivKey(str,Hilite,InitErrors,MMGenObject):
|
||||
|
||||
color = 'red'
|
||||
width = 64
|
||||
|
|
@ -666,7 +648,7 @@ class PrivKey(bytes,Hilite,InitErrors,MMGenObject):
|
|||
assert s == None
|
||||
assert set(wif) <= set(ascii_letters+digits),'not an ascii alphanumeric string'
|
||||
w2h = g.proto.wif2hex(wif) # raises exception on error
|
||||
me = bytes.__new__(cls,w2h['hex'])
|
||||
me = str.__new__(cls,w2h['hex'])
|
||||
me.compressed = w2h['compressed']
|
||||
me.pubkey_type = w2h['pubkey_type']
|
||||
me.wif = str.__new__(WifKey,wif) # check has been done
|
||||
|
|
@ -680,13 +662,13 @@ class PrivKey(bytes,Hilite,InitErrors,MMGenObject):
|
|||
assert s and type(compressed) == bool and pubkey_type,'Incorrect args for PrivKey()'
|
||||
assert len(s) == cls.width // 2,'Key length must be {}'.format(cls.width//2)
|
||||
if pubkey_type == 'password': # skip WIF creation and pre-processing for passwds
|
||||
me = bytes.__new__(cls,hexlify(s))
|
||||
me = str.__new__(cls,s.hex())
|
||||
else:
|
||||
me = bytes.__new__(cls,g.proto.preprocess_key(hexlify(s),pubkey_type))
|
||||
me = str.__new__(cls,g.proto.preprocess_key(s.hex(),pubkey_type))
|
||||
me.wif = WifKey(g.proto.hex2wif(me,pubkey_type,compressed),on_fail='raise')
|
||||
me.compressed = compressed
|
||||
me.pubkey_type = pubkey_type
|
||||
me.orig_hex = hexlify(s) # save the non-preprocessed key
|
||||
me.orig_hex = s.hex() # save the non-preprocessed key
|
||||
return me
|
||||
except Exception as e:
|
||||
fs = "Key={!r}\nCompressed={}\nValue pair cannot be converted to PrivKey\n({})"
|
||||
|
|
|
|||
|
|
@ -21,17 +21,16 @@ protocol.py: Coin protocol functions, classes and methods
|
|||
"""
|
||||
|
||||
import sys,os,hashlib
|
||||
from binascii import hexlify,unhexlify
|
||||
from mmgen.util import msg,pmsg,ymsg,Msg,pdie,ydie
|
||||
from mmgen.obj import MMGenObject,BTCAmt,LTCAmt,BCHAmt,B2XAmt,ETHAmt
|
||||
from mmgen.globalvars import g
|
||||
import mmgen.bech32 as bech32
|
||||
|
||||
def hash160(hexnum): # take hex, return hex - OP_HASH160
|
||||
return hashlib.new('ripemd160',hashlib.sha256(unhexlify(hexnum)).digest()).hexdigest().encode()
|
||||
return hashlib.new('ripemd160',hashlib.sha256(bytes.fromhex(hexnum)).digest()).hexdigest()
|
||||
|
||||
def hash256(hexnum): # take hex, return hex - OP_HASH256
|
||||
return hashlib.sha256(hashlib.sha256(unhexlify(hexnum)).digest()).hexdigest().encode()
|
||||
return hashlib.sha256(hashlib.sha256(bytes.fromhex(hexnum)).digest()).hexdigest()
|
||||
|
||||
_b58a='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||
|
||||
|
|
@ -43,7 +42,7 @@ _b58a='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
|||
# 1111111111111111111114oLvT2 (pubkeyhash = '\0'*20)
|
||||
|
||||
def _b58chk_encode(hexstr):
|
||||
lzeroes = (len(hexstr) - len(hexstr.lstrip(b'0'))) // 2
|
||||
lzeroes = (len(hexstr) - len(hexstr.lstrip('0'))) // 2
|
||||
def b58enc(n):
|
||||
while n:
|
||||
yield _b58a[n % 58]
|
||||
|
|
@ -53,10 +52,9 @@ def _b58chk_encode(hexstr):
|
|||
def _b58chk_decode(s):
|
||||
lzeroes = len(s) - len(s.lstrip('1'))
|
||||
hexstr = '{}{:x}'.format(
|
||||
'00' * lzeroes,
|
||||
sum(_b58a.index(ch) * 58**n for n,ch in enumerate(s[::-1]))
|
||||
).encode()
|
||||
if len(hexstr) % 2: hexstr = b'0' + hexstr
|
||||
'00' * lzeroes,
|
||||
sum(_b58a.index(ch) * 58**n for n,ch in enumerate(s[::-1])) )
|
||||
if len(hexstr) % 2: hexstr = '0' + hexstr
|
||||
if hexstr[-8:] != hash256(hexstr[:-8])[:8]:
|
||||
raise ValueError('_b58chk_decode(): {}: incorrect checksum for {}, expected {}'.format(
|
||||
hexstr[-8:],hexstr[:-8],hash256(hexstr[:-8])[:8]))
|
||||
|
|
@ -67,8 +65,8 @@ class BitcoinProtocol(MMGenObject):
|
|||
name = 'bitcoin'
|
||||
daemon_name = 'bitcoind'
|
||||
daemon_family = 'bitcoind'
|
||||
addr_ver_num = { 'p2pkh': (b'00','1'), 'p2sh': (b'05','3') }
|
||||
wif_ver_num = { 'std': b'80' }
|
||||
addr_ver_num = { 'p2pkh': ('00','1'), 'p2sh': ('05','3') }
|
||||
wif_ver_num = { 'std': '80' }
|
||||
mmtypes = ('L','C','S','B')
|
||||
dfl_mmtype = 'L'
|
||||
data_subdir = ''
|
||||
|
|
@ -90,7 +88,7 @@ class BitcoinProtocol(MMGenObject):
|
|||
base_coin = 'BTC'
|
||||
# From BIP173: witness version 'n' is stored as 'OP_n'. OP_0 is encoded as 0x00,
|
||||
# but OP_1 through OP_16 are encoded as 0x51 though 0x60 (81 to 96 in decimal).
|
||||
witness_vernum_hex = b'00'
|
||||
witness_vernum_hex = '00'
|
||||
witness_vernum = int(witness_vernum_hex,16)
|
||||
bech32_hrp = 'bc'
|
||||
sign_mode = 'daemon'
|
||||
|
|
@ -126,7 +124,7 @@ class BitcoinProtocol(MMGenObject):
|
|||
@classmethod
|
||||
def hex2wif(cls,hexpriv,pubkey_type,compressed): # PrivKey
|
||||
assert len(hexpriv) == cls.privkey_len*2, '{} bytes: incorrect private key length!'.format(len(hexpriv)//2)
|
||||
return _b58chk_encode(cls.wif_ver_num[pubkey_type] + hexpriv + (b'',b'01')[bool(compressed)])
|
||||
return _b58chk_encode(cls.wif_ver_num[pubkey_type] + hexpriv + ('','01')[bool(compressed)])
|
||||
|
||||
@classmethod
|
||||
def wif2hex(cls,wif):
|
||||
|
|
@ -138,7 +136,7 @@ class BitcoinProtocol(MMGenObject):
|
|||
key = key[len(v):]
|
||||
assert pubkey_type,'invalid WIF version number'
|
||||
if len(key) == 66:
|
||||
assert key[-2:] == b'01','invalid compressed key suffix'
|
||||
assert key[-2:] == '01','invalid compressed key suffix'
|
||||
compressed = True
|
||||
else:
|
||||
assert len(key) == 64,'invalid key length'
|
||||
|
|
@ -156,7 +154,7 @@ class BitcoinProtocol(MMGenObject):
|
|||
msg('{}: Invalid witness version number'.format(ret[0]))
|
||||
elif ret[1]:
|
||||
return {
|
||||
'hex': hexlify(bytes(ret[1])),
|
||||
'hex': bytes(ret[1]).hex(),
|
||||
'format': 'bech32'
|
||||
} if return_dict else True
|
||||
return False
|
||||
|
|
@ -191,7 +189,7 @@ class BitcoinProtocol(MMGenObject):
|
|||
# https://bitcoincore.org/en/segwit_wallet_dev/
|
||||
# The P2SH redeemScript is always 22 bytes. It starts with a OP_0, followed
|
||||
# by a canonical push of the keyhash (i.e. 0x0014{20-byte keyhash})
|
||||
return cls.witness_vernum_hex + b'14' + hash160(pubhex)
|
||||
return cls.witness_vernum_hex + '14' + hash160(pubhex)
|
||||
|
||||
@classmethod
|
||||
def pubhex2segwitaddr(cls,pubhex):
|
||||
|
|
@ -199,12 +197,12 @@ class BitcoinProtocol(MMGenObject):
|
|||
|
||||
@classmethod
|
||||
def pubhash2bech32addr(cls,pubhash):
|
||||
d = list(unhexlify(pubhash))
|
||||
d = list(bytes.fromhex(pubhash))
|
||||
return bech32.bech32_encode(cls.bech32_hrp,[cls.witness_vernum]+bech32.convertbits(d,8,5))
|
||||
|
||||
class BitcoinTestnetProtocol(BitcoinProtocol):
|
||||
addr_ver_num = { 'p2pkh': (b'6f',('m','n')), 'p2sh': (b'c4','2') }
|
||||
wif_ver_num = { 'std': b'ef' }
|
||||
addr_ver_num = { 'p2pkh': ('6f',('m','n')), 'p2sh': ('c4','2') }
|
||||
wif_ver_num = { 'std': 'ef' }
|
||||
data_subdir = 'testnet'
|
||||
daemon_data_subdir = 'testnet3'
|
||||
rpc_port = 18332
|
||||
|
|
@ -233,8 +231,8 @@ class BitcoinCashProtocol(BitcoinProtocol):
|
|||
|
||||
class BitcoinCashTestnetProtocol(BitcoinCashProtocol):
|
||||
rpc_port = 18442
|
||||
addr_ver_num = { 'p2pkh': (b'6f',('m','n')), 'p2sh': (b'c4','2') }
|
||||
wif_ver_num = { 'std': b'ef' }
|
||||
addr_ver_num = { 'p2pkh': ('6f',('m','n')), 'p2sh': ('c4','2') }
|
||||
wif_ver_num = { 'std': 'ef' }
|
||||
data_subdir = 'testnet'
|
||||
daemon_data_subdir = 'testnet3'
|
||||
|
||||
|
|
@ -250,8 +248,8 @@ class B2XProtocol(BitcoinProtocol):
|
|||
]
|
||||
|
||||
class B2XTestnetProtocol(B2XProtocol):
|
||||
addr_ver_num = { 'p2pkh': (b'6f',('m','n')), 'p2sh': (b'c4','2') }
|
||||
wif_ver_num = { 'std': b'ef' }
|
||||
addr_ver_num = { 'p2pkh': ('6f',('m','n')), 'p2sh': ('c4','2') }
|
||||
wif_ver_num = { 'std': 'ef' }
|
||||
data_subdir = 'testnet'
|
||||
daemon_data_subdir = 'testnet5'
|
||||
rpc_port = 18338
|
||||
|
|
@ -262,8 +260,8 @@ class LitecoinProtocol(BitcoinProtocol):
|
|||
daemon_name = 'litecoind'
|
||||
daemon_data_dir = os.path.join(os.getenv('APPDATA'),'Litecoin') if g.platform == 'win' \
|
||||
else os.path.join(g.home_dir,'.litecoin')
|
||||
addr_ver_num = { 'p2pkh': (b'30','L'), 'p2sh': (b'32','M'), 'p2sh2': (b'05','3') } # 'p2sh' is new fmt
|
||||
wif_ver_num = { 'std': b'b0' }
|
||||
addr_ver_num = { 'p2pkh': ('30','L'), 'p2sh': ('32','M'), 'p2sh2': ('05','3') } # 'p2sh' is new fmt
|
||||
wif_ver_num = { 'std': 'b0' }
|
||||
mmtypes = ('L','C','S','B')
|
||||
secs_per_block = 150
|
||||
rpc_port = 9332
|
||||
|
|
@ -275,8 +273,8 @@ class LitecoinProtocol(BitcoinProtocol):
|
|||
|
||||
class LitecoinTestnetProtocol(LitecoinProtocol):
|
||||
# addr ver nums same as Bitcoin testnet, except for 'p2sh'
|
||||
addr_ver_num = { 'p2pkh': (b'6f',('m','n')), 'p2sh': (b'3a','Q'), 'p2sh2': (b'c4','2') }
|
||||
wif_ver_num = { 'std': b'ef' } # same as Bitcoin testnet
|
||||
addr_ver_num = { 'p2pkh': ('6f',('m','n')), 'p2sh': ('3a','Q'), 'p2sh2': ('c4','2') }
|
||||
wif_ver_num = { 'std': 'ef' } # same as Bitcoin testnet
|
||||
data_subdir = 'testnet'
|
||||
daemon_data_subdir = 'testnet4'
|
||||
rpc_port = 19332
|
||||
|
|
@ -293,11 +291,11 @@ class DummyWIF(object):
|
|||
n = cls.name.capitalize()
|
||||
assert pubkey_type == cls.pubkey_type,'{}: invalid pubkey_type for {}!'.format(pubkey_type,n)
|
||||
assert compressed == False,'{} does not support compressed pubkeys!'.format(n)
|
||||
return hexpriv.decode()
|
||||
return hexpriv
|
||||
|
||||
@classmethod
|
||||
def wif2hex(cls,wif):
|
||||
return { 'hex':wif.encode(), 'pubkey_type':cls.pubkey_type, 'compressed':False }
|
||||
return { 'hex':wif, 'pubkey_type':cls.pubkey_type, 'compressed':False }
|
||||
|
||||
class EthereumProtocol(DummyWIF,BitcoinProtocol):
|
||||
|
||||
|
|
@ -323,7 +321,7 @@ class EthereumProtocol(DummyWIF,BitcoinProtocol):
|
|||
def verify_addr(cls,addr,hex_width,return_dict=False):
|
||||
from mmgen.util import is_hex_str_lc
|
||||
if is_hex_str_lc(addr) and len(addr) == cls.addr_width:
|
||||
return { 'hex': addr.encode(), 'format': 'ethereum' } if return_dict else True
|
||||
return { 'hex': addr, 'format': 'ethereum' } if return_dict else True
|
||||
if g.debug: Msg("Invalid address '{}'".format(addr))
|
||||
return False
|
||||
|
||||
|
|
@ -331,7 +329,7 @@ class EthereumProtocol(DummyWIF,BitcoinProtocol):
|
|||
def pubhash2addr(cls,pubkey_hash,p2sh):
|
||||
assert len(pubkey_hash) == 40,'{}: invalid length for pubkey hash'.format(len(pubkey_hash))
|
||||
assert not p2sh,'Ethereum has no P2SH address format'
|
||||
return pubkey_hash.decode()
|
||||
return pubkey_hash
|
||||
|
||||
class EthereumTestnetProtocol(EthereumProtocol):
|
||||
data_subdir = 'testnet'
|
||||
|
|
@ -352,18 +350,18 @@ class ZcashProtocol(BitcoinProtocolAddrgen):
|
|||
name = 'zcash'
|
||||
base_coin = 'ZEC'
|
||||
addr_ver_num = {
|
||||
'p2pkh': (b'1cb8','t1'),
|
||||
'p2sh': (b'1cbd','t3'),
|
||||
'zcash_z': (b'169a','zc'),
|
||||
'viewkey': (b'a8abd3','ZiVK') }
|
||||
wif_ver_num = { 'std': b'80', 'zcash_z': b'ab36' }
|
||||
'p2pkh': ('1cb8','t1'),
|
||||
'p2sh': ('1cbd','t3'),
|
||||
'zcash_z': ('169a','zc'),
|
||||
'viewkey': ('a8abd3','ZiVK') }
|
||||
wif_ver_num = { 'std': '80', 'zcash_z': 'ab36' }
|
||||
mmtypes = ('L','C','Z')
|
||||
dfl_mmtype = 'L'
|
||||
|
||||
@classmethod
|
||||
def preprocess_key(cls,hexpriv,pubkey_type): # zero the first four bits
|
||||
if pubkey_type == 'zcash_z':
|
||||
return '{:02x}'.format(int(hexpriv[:2],16) & 0x0f).encode() + hexpriv[2:]
|
||||
return '{:02x}'.format(int(hexpriv[:2],16) & 0x0f) + hexpriv[2:]
|
||||
else:
|
||||
return hexpriv
|
||||
|
||||
|
|
@ -378,18 +376,18 @@ class ZcashProtocol(BitcoinProtocolAddrgen):
|
|||
raise ValueError('{}: incorrect pubkey_hash length'.format(hl))
|
||||
|
||||
class ZcashTestnetProtocol(ZcashProtocol):
|
||||
wif_ver_num = { 'std': b'ef', 'zcash_z': b'ac08' }
|
||||
wif_ver_num = { 'std': 'ef', 'zcash_z': 'ac08' }
|
||||
addr_ver_num = {
|
||||
'p2pkh': (b'1d25','tm'),
|
||||
'p2sh': (b'1cba','t2'),
|
||||
'zcash_z': (b'16b6','zt'),
|
||||
'viewkey': (b'a8ac0c','ZiVt') }
|
||||
'p2pkh': ('1d25','tm'),
|
||||
'p2sh': ('1cba','t2'),
|
||||
'zcash_z': ('16b6','zt'),
|
||||
'viewkey': ('a8ac0c','ZiVt') }
|
||||
|
||||
# https://github.com/monero-project/monero/blob/master/src/cryptonote_config.h
|
||||
class MoneroProtocol(DummyWIF,BitcoinProtocolAddrgen):
|
||||
name = 'monero'
|
||||
base_coin = 'XMR'
|
||||
addr_ver_num = { 'monero': (b'12','4'), 'monero_sub': (b'2a','8') } # 18,42
|
||||
addr_ver_num = { 'monero': ('12','4'), 'monero_sub': ('2a','8') } # 18,42
|
||||
wif_ver_num = {}
|
||||
mmtypes = ('M',)
|
||||
dfl_mmtype = 'M'
|
||||
|
|
@ -399,8 +397,8 @@ class MoneroProtocol(DummyWIF,BitcoinProtocolAddrgen):
|
|||
@classmethod
|
||||
def preprocess_key(cls,hexpriv,pubkey_type): # reduce key
|
||||
from mmgen.ed25519 import l
|
||||
n = int(hexlify(unhexlify(hexpriv)[::-1]),16) % l
|
||||
return hexlify(unhexlify('{:064x}'.format(n))[::-1])
|
||||
n = int(bytes.fromhex(hexpriv)[::-1].hex(),16) % l
|
||||
return bytes.fromhex('{:064x}'.format(n))[::-1].hex()
|
||||
|
||||
@classmethod
|
||||
def verify_addr(cls,addr,hex_width,return_dict=False):
|
||||
|
|
@ -408,7 +406,7 @@ class MoneroProtocol(DummyWIF,BitcoinProtocolAddrgen):
|
|||
def b58dec(addr_str):
|
||||
from mmgen.util import baseconv
|
||||
l = len(addr_str)
|
||||
a = b''.join([baseconv.tohex(addr_str[i*11:i*11+11],'b58',pad=16) for i in range(l//11)])
|
||||
a = ''.join([baseconv.tohex(addr_str[i*11:i*11+11],'b58',pad=16) for i in range(l//11)])
|
||||
b = baseconv.tohex(addr_str[-(l%11):],'b58',pad=10)
|
||||
return a + b
|
||||
|
||||
|
|
@ -418,13 +416,13 @@ class MoneroProtocol(DummyWIF,BitcoinProtocolAddrgen):
|
|||
|
||||
ret = b58dec(addr)
|
||||
import sha3
|
||||
chk = sha3.keccak_256(unhexlify(ret)[:-4]).hexdigest()[:8]
|
||||
assert chk.encode() == ret[-8:],'Incorrect checksum'
|
||||
chk = sha3.keccak_256(bytes.fromhex(ret)[:-4]).hexdigest()[:8]
|
||||
assert chk == ret[-8:],'{}: incorrect checksum. Correct value: {}'.format(ret[-8:],chk)
|
||||
|
||||
return { 'hex': ret, 'format': 'monero' } if return_dict else True
|
||||
|
||||
class MoneroTestnetProtocol(MoneroProtocol):
|
||||
addr_ver_num = { 'monero': (b'35','4'), 'monero_sub': (b'3f','8') } # 53,63
|
||||
addr_ver_num = { 'monero': ('35','4'), 'monero_sub': ('3f','8') } # 53,63
|
||||
|
||||
class CoinProtocol(MMGenObject):
|
||||
coins = {
|
||||
|
|
@ -484,17 +482,17 @@ def make_init_genonly_altcoins_str(data):
|
|||
if proto in globals(): return ''
|
||||
if coin.lower() in CoinProtocol.coins: return ''
|
||||
|
||||
def num2hexbytes(n):
|
||||
return "b'{:0{}x}'".format(n,(4,2)[n < 256])
|
||||
def num2hexstr(n):
|
||||
return "'{:0{}x}'".format(n,(4,2)[n < 256])
|
||||
|
||||
o = ['class {}(Bitcoin{}ProtocolAddrgen):'.format(proto,tn_str)]
|
||||
o += ["base_coin = '{}'".format(coin)]
|
||||
o += ["name = '{}'".format(e[0].lower())]
|
||||
o += ["nameCaps = '{}'".format(e[0])]
|
||||
a = "addr_ver_num = {{ 'p2pkh': ({},{!r})".format(num2hexbytes(e[3][0]),e[3][1])
|
||||
b = ", 'p2sh': ({},{!r})".format(num2hexbytes(e[4][0]),e[4][1]) if e[4] else ''
|
||||
a = "addr_ver_num = {{ 'p2pkh': ({},{!r})".format(num2hexstr(e[3][0]),e[3][1])
|
||||
b = ", 'p2sh': ({},{!r})".format(num2hexstr(e[4][0]),e[4][1]) if e[4] else ''
|
||||
o += [a+b+' }']
|
||||
o += ["wif_ver_num = {{ 'std': {} }}".format(num2hexbytes(e[2]))]
|
||||
o += ["wif_ver_num = {{ 'std': {} }}".format(num2hexstr(e[2]))]
|
||||
o += ["mmtypes = ('L','C'{})".format(",'S'" if e[5] else '')]
|
||||
o += ["dfl_mmtype = '{}'".format('L')]
|
||||
return '\n\t'.join(o) + '\n'
|
||||
|
|
|
|||
|
|
@ -110,13 +110,13 @@ class CoinDaemonRPCConnection(object):
|
|||
dmsg_rpc(' RPC POST data ==> {}\n'.format(p))
|
||||
|
||||
ca_type = self.coin_amt_type if hasattr(self,'coin_amt_type') else str
|
||||
from mmgen.obj import CoinTxID,HexBytes
|
||||
from mmgen.obj import HexStr
|
||||
class MyJSONEncoder(json.JSONEncoder):
|
||||
def default(self,obj):
|
||||
if isinstance(obj,g.proto.coin_amt):
|
||||
return ca_type(obj)
|
||||
elif isinstance(obj,CoinTxID) or isinstance(obj,HexBytes):
|
||||
return obj.decode()
|
||||
elif isinstance(obj,HexStr):
|
||||
return obj
|
||||
else:
|
||||
return json.JSONEncoder.default(self,obj)
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ seed.py: Seed-related classes and methods for the MMGen suite
|
|||
"""
|
||||
|
||||
import os
|
||||
from binascii import hexlify,unhexlify
|
||||
|
||||
from mmgen.common import *
|
||||
from mmgen.obj import *
|
||||
|
|
@ -55,7 +54,7 @@ class Seed(MMGenObject):
|
|||
die(3,'{}: invalid seed length'.format(len(seed_bin)))
|
||||
|
||||
self.data = seed_bin
|
||||
self.hexdata = hexlify(seed_bin)
|
||||
self.hexdata = seed_bin.hex()
|
||||
self.sid = SeedID(seed=self)
|
||||
self.length = len(seed_bin) * 8
|
||||
|
||||
|
|
@ -485,7 +484,7 @@ class Mnemonic (SeedSourceUnenc):
|
|||
# Internal error, so just die
|
||||
compare_or_die(' '.join(ret),'recomputed mnemonic',' '.join(mn),'original',e='Internal error')
|
||||
|
||||
self.seed = Seed(unhexlify(hexseed))
|
||||
self.seed = Seed(bytes.fromhex(hexseed))
|
||||
self.ssdata.mnemonic = mn
|
||||
|
||||
check_usr_seed_len(self.seed.length)
|
||||
|
|
@ -542,7 +541,7 @@ class SeedFile (SeedSourceUnenc):
|
|||
|
||||
return True
|
||||
|
||||
class HexSeedFile (SeedSourceUnenc):
|
||||
class HexSeedFile(SeedSourceUnenc):
|
||||
|
||||
stdin_ok = True
|
||||
fmt_codes = 'seedhex','hexseed','hex','mmhex'
|
||||
|
|
@ -553,7 +552,7 @@ class HexSeedFile (SeedSourceUnenc):
|
|||
h = self.seed.hexdata
|
||||
self.ssdata.chksum = make_chksum_6(h)
|
||||
self.ssdata.hexseed = h
|
||||
self.fmt_data = '{} {}\n'.format(self.ssdata.chksum, split_into_cols(4,h.decode()))
|
||||
self.fmt_data = '{} {}\n'.format(self.ssdata.chksum, split_into_cols(4,h))
|
||||
|
||||
def _deformat(self):
|
||||
desc = self.desc
|
||||
|
|
@ -582,7 +581,7 @@ class HexSeedFile (SeedSourceUnenc):
|
|||
if not compare_chksums(chk,'file',make_chksum_6(hstr),'computed',verbose=True):
|
||||
return False
|
||||
|
||||
self.seed = Seed(unhexlify(hstr))
|
||||
self.seed = Seed(bytes.fromhex(hstr))
|
||||
self.ssdata.chksum = chk
|
||||
self.ssdata.hexseed = hstr
|
||||
|
||||
|
|
@ -869,7 +868,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
|
|||
self.fmt_data = d.iv + encrypt_data(
|
||||
d.salt + d.enc_seed,
|
||||
d.wrapper_key,
|
||||
int(hexlify(d.iv),16),
|
||||
int(d.iv.hex(),16),
|
||||
self.desc)
|
||||
# print len(self.fmt_data)
|
||||
|
||||
|
|
@ -923,7 +922,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
|
|||
# IV is used BOTH to initialize counter and to salt password!
|
||||
key = make_key(d.passwd, d.iv, d.hash_preset, 'wrapper key')
|
||||
dd = decrypt_data(d.enc_incog_data, key,
|
||||
int(hexlify(d.iv),16), 'incog data')
|
||||
int(d.iv.hex(),16), 'incog data')
|
||||
|
||||
d.salt = dd[0:g.salt_len]
|
||||
d.enc_seed = dd[g.salt_len:]
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ sha2.py: A non-optimized but very compact implementation of the SHA2 hash
|
|||
SHA256Compress (unpadded SHA256, required for Zcash addresses)
|
||||
"""
|
||||
|
||||
from binascii import hexlify
|
||||
from struct import pack,unpack
|
||||
|
||||
class Sha2(object):
|
||||
|
|
@ -103,7 +102,7 @@ class Sha2(object):
|
|||
return b''.join((pack(self.word_fmt,w) for w in self.H))
|
||||
|
||||
def hexdigest(self):
|
||||
return hexlify(self.digest())
|
||||
return self.digest().hex()
|
||||
|
||||
def compute(self):
|
||||
for i in range(0,len(self.M),16):
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
tool.py: Routines for the 'mmgen-tool' utility
|
||||
"""
|
||||
|
||||
from binascii import hexlify,unhexlify
|
||||
|
||||
from mmgen.protocol import hash160
|
||||
from mmgen.common import *
|
||||
from mmgen.crypto import *
|
||||
|
|
@ -248,20 +246,20 @@ class MMGenToolCmdUtil(MMGenToolCmdBase):
|
|||
|
||||
def randhex(self,nbytes='32'):
|
||||
"print 'n' bytes (default 32) of random data in hex format"
|
||||
return hexlify(get_random(int(nbytes)))
|
||||
return get_random(int(nbytes)).hex()
|
||||
|
||||
def hexreverse(self,hexstr:'sstr'):
|
||||
"reverse bytes of a hexadecimal string"
|
||||
return hexlify(unhexlify(hexstr.strip())[::-1])
|
||||
return bytes.fromhex(hexstr.strip())[::-1].hex()
|
||||
|
||||
def hexlify(self,infile:str):
|
||||
"convert bytes in file to hexadecimal (use '-' for stdin)"
|
||||
data = get_data_from_file(infile,dash=True,silent=True,binary=True)
|
||||
return hexlify(data)
|
||||
return data.hex()
|
||||
|
||||
def unhexlify(self,hexstr:'sstr'):
|
||||
"convert hexadecimal value to bytes (warning: outputs binary data)"
|
||||
return unhexlify(hexstr.encode())
|
||||
return bytes.fromhex(hexstr)
|
||||
|
||||
def hexdump(self,infile:str,cols=8,line_nums=True):
|
||||
"create hexdump of data from file (use '-' for stdin)"
|
||||
|
|
@ -286,7 +284,7 @@ class MMGenToolCmdUtil(MMGenToolCmdBase):
|
|||
if file_input: b = get_data_from_file(string_or_bytes,binary=True)
|
||||
elif hex_input: b = decode_pretty_hexdump(string_or_bytes)
|
||||
else: b = string_or_bytes
|
||||
return sha256(sha256(b.encode()).digest()).hexdigest().encode()
|
||||
return sha256(sha256(b.encode()).digest()).hexdigest()
|
||||
|
||||
def id6(self,infile:str):
|
||||
"generate 6-character MMGen ID for a file (use '-' for stdin)"
|
||||
|
|
@ -309,15 +307,15 @@ class MMGenToolCmdUtil(MMGenToolCmdBase):
|
|||
def bytestob58(self,infile:str,pad=0):
|
||||
"convert bytes to base 58 (supply data via STDIN)"
|
||||
data = get_data_from_file(infile,dash=True,silent=True,binary=True)
|
||||
return baseconv.fromhex(hexlify(data),'b58',pad=pad,tostr=True)
|
||||
return baseconv.fromhex(data.hex(),'b58',pad=pad,tostr=True)
|
||||
|
||||
def b58tobytes(self,b58num:'sstr',pad=0):
|
||||
"convert a base 58 number to bytes (warning: outputs binary data)"
|
||||
return unhexlify(baseconv.tohex(b58num,'b58',pad=pad))
|
||||
return bytes.fromhex(baseconv.tohex(b58num,'b58',pad=pad))
|
||||
|
||||
def hextob58(self,hexstr:'sstr',pad=0):
|
||||
"convert a hexadecimal number to base 58"
|
||||
return baseconv.fromhex(hexstr.encode(),'b58',pad=pad,tostr=True)
|
||||
return baseconv.fromhex(hexstr,'b58',pad=pad,tostr=True)
|
||||
|
||||
def b58tohex(self,b58num:'sstr',pad=0):
|
||||
"convert a base 58 number to hexadecimal"
|
||||
|
|
@ -326,7 +324,7 @@ class MMGenToolCmdUtil(MMGenToolCmdBase):
|
|||
def hextob58chk(self,hexstr:'sstr'):
|
||||
"convert a hexadecimal number to base58-check encoding"
|
||||
from mmgen.protocol import _b58chk_encode
|
||||
return _b58chk_encode(hexstr.encode())
|
||||
return _b58chk_encode(hexstr)
|
||||
|
||||
def b58chktohex(self,b58chk_num:'sstr'):
|
||||
"convert a base58-check encoded number to hexadecimal"
|
||||
|
|
@ -335,7 +333,7 @@ class MMGenToolCmdUtil(MMGenToolCmdBase):
|
|||
|
||||
def hextob32(self,hexstr:'sstr',pad=0):
|
||||
"convert a hexadecimal number to MMGen's flavor of base 32"
|
||||
return baseconv.fromhex(hexstr.encode(),'b32',pad,tostr=True)
|
||||
return baseconv.fromhex(hexstr,'b32',pad,tostr=True)
|
||||
|
||||
def b32tohex(self,b32num:'sstr',pad=0):
|
||||
"convert an MMGen-flavor base 32 number to hexadecimal"
|
||||
|
|
@ -370,7 +368,7 @@ class MMGenToolCmdCoin(MMGenToolCmdBase):
|
|||
def hex2wif(self,privhex:'sstr'):
|
||||
"convert a private key from hex to WIF format"
|
||||
init_generators('at')
|
||||
return g.proto.hex2wif(privhex.encode(),pubkey_type=at.pubkey_type,compressed=at.compressed)
|
||||
return g.proto.hex2wif(privhex,pubkey_type=at.pubkey_type,compressed=at.compressed)
|
||||
|
||||
def wif2addr(self,wifkey:'sstr'):
|
||||
"generate a coin address from a key in WIF format"
|
||||
|
|
@ -398,7 +396,7 @@ class MMGenToolCmdCoin(MMGenToolCmdBase):
|
|||
def privhex2addr(self,privhex:'sstr',output_pubhex=False):
|
||||
"generate coin address from private key in hex format"
|
||||
init_generators()
|
||||
pk = PrivKey(unhexlify(privhex),compressed=at.compressed,pubkey_type=at.pubkey_type)
|
||||
pk = PrivKey(bytes.fromhex(privhex),compressed=at.compressed,pubkey_type=at.pubkey_type)
|
||||
ph = kg.to_pubhex(pk)
|
||||
return ph if output_pubhex else ag.to_addr(ph)
|
||||
|
||||
|
|
@ -409,9 +407,9 @@ class MMGenToolCmdCoin(MMGenToolCmdBase):
|
|||
def pubhex2addr(self,pubkeyhex:'sstr'):
|
||||
"convert a hex pubkey to an address"
|
||||
if opt.type == 'segwit':
|
||||
return g.proto.pubhex2segwitaddr(pubkeyhex.encode())
|
||||
return g.proto.pubhex2segwitaddr(pubkeyhex)
|
||||
else:
|
||||
return self.pubhash2addr(hash160(pubkeyhex.encode()).decode())
|
||||
return self.pubhash2addr(hash160(pubkeyhex))
|
||||
|
||||
def pubhex2redeem_script(self,pubkeyhex:'sstr'): # new
|
||||
"convert a hex pubkey to a Segwit P2SH-P2WPKH redeem script"
|
||||
|
|
@ -423,15 +421,15 @@ class MMGenToolCmdCoin(MMGenToolCmdBase):
|
|||
assert opt.type == 'segwit','This command is meaningful only for --type=segwit'
|
||||
assert redeem_scripthex[:4] == '0014','{!r}: invalid redeem script'.format(redeem_scripthex)
|
||||
assert len(redeem_scripthex) == 44,'{} bytes: invalid redeem script length'.format(len(redeem_scripthex)//2)
|
||||
return self.pubhash2addr(self.hash160(redeem_scripthex).decode())
|
||||
return self.pubhash2addr(self.hash160(redeem_scripthex))
|
||||
|
||||
def pubhash2addr(self,pubhashhex:'sstr'):
|
||||
"convert public key hash to address"
|
||||
if opt.type == 'bech32':
|
||||
return g.proto.pubhash2bech32addr(pubhashhex.encode())
|
||||
return g.proto.pubhash2bech32addr(pubhashhex)
|
||||
else:
|
||||
init_generators('at')
|
||||
return g.proto.pubhash2addr(pubhashhex.encode(),at.addr_fmt=='p2sh')
|
||||
return g.proto.pubhash2addr(pubhashhex,at.addr_fmt=='p2sh')
|
||||
|
||||
def addr2pubhash(self,addr:'sstr'):
|
||||
"convert coin address to public key hash"
|
||||
|
|
@ -446,7 +444,7 @@ class MMGenToolCmdMnemonic(MMGenToolCmdBase):
|
|||
"""
|
||||
def _do_random_mn(self,nbytes:int,wordlist_id:str):
|
||||
assert nbytes in (16,24,32), 'nbytes must be 16, 24 or 32'
|
||||
hexrand = hexlify(get_random(nbytes))
|
||||
hexrand = get_random(nbytes).hex()
|
||||
Vmsg('Seed: {}'.format(hexrand))
|
||||
return self.hex2mn(hexrand,wordlist_id=wordlist_id)
|
||||
|
||||
|
|
@ -466,7 +464,7 @@ class MMGenToolCmdMnemonic(MMGenToolCmdBase):
|
|||
"convert a 16, 24 or 32-byte hexadecimal number to a mnemonic"
|
||||
opt.out_fmt = 'words'
|
||||
from mmgen.seed import SeedSource
|
||||
s = SeedSource(seed=unhexlify(hexstr))
|
||||
s = SeedSource(seed=bytes.fromhex(hexstr))
|
||||
s._format()
|
||||
return ' '.join(s.ssdata.mnemonic)
|
||||
|
||||
|
|
@ -820,7 +818,7 @@ class MMGenToolCmdMonero(MMGenToolCmdBase):
|
|||
p = pexpect.spawn('monero-wallet-cli --generate-from-spend-key {}'.format(fn))
|
||||
if g.debug: p.logfile = sys.stdout
|
||||
my_expect(p,'Awaiting initial prompt','Secret spend key: ')
|
||||
my_sendline(p,'',d.sec.decode(),65)
|
||||
my_sendline(p,'',d.sec,65)
|
||||
my_expect(p,'','Enter.* new.* password.*: ',regex=True)
|
||||
my_sendline(p,'Sending password',d.wallet_passwd,33)
|
||||
my_expect(p,'','Confirm password: ')
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ Actions: [q]uit view, [p]rint to file, pager [v]iew, [w]ide view, add [l]abel:
|
|||
twmmid = MMGenImmutableAttr('twmmid','TwMMGenID')
|
||||
addr = MMGenImmutableAttr('addr','CoinAddr')
|
||||
confs = MMGenImmutableAttr('confs',int,typeconv=False)
|
||||
scriptPubKey = MMGenImmutableAttr('scriptPubKey','HexBytes')
|
||||
scriptPubKey = MMGenImmutableAttr('scriptPubKey','HexStr')
|
||||
days = MMGenListItemAttr('days',int,typeconv=False)
|
||||
skip = MMGenListItemAttr('skip',str,typeconv=False,reassign_ok=True)
|
||||
|
||||
|
|
@ -231,7 +231,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
|
|||
out.append(fs.format( n=str(n+1)+')',
|
||||
t='' if not i.txid else \
|
||||
' ' * (tx_w-4) + '|...' if i.skip == 'txid' \
|
||||
else i.txid.decode()[:tx_w-len(txdots)]+txdots,
|
||||
else i.txid[:tx_w-len(txdots)] + txdots,
|
||||
v=i.vout,
|
||||
a=addr_out,
|
||||
A=i.amt.fmt(color=True,prec=self.disp_prec),
|
||||
|
|
|
|||
59
mmgen/tx.py
59
mmgen/tx.py
|
|
@ -22,7 +22,6 @@ tx.py: Transaction routines for the MMGen suite
|
|||
|
||||
import sys,os,json
|
||||
from stat import *
|
||||
from binascii import unhexlify
|
||||
from mmgen.common import *
|
||||
from mmgen.obj import *
|
||||
|
||||
|
|
@ -98,8 +97,8 @@ def segwit_is_active(exit_on_error=False):
|
|||
return False
|
||||
|
||||
def bytes2int(hex_bytes):
|
||||
r = hexlify(unhexlify(hex_bytes)[::-1])
|
||||
if hexlify(bytes([r[0]])) in b'89abcdef':
|
||||
r = bytes.fromhex(hex_bytes)[::-1].hex()
|
||||
if r[0] in '89abcdef': # sign bit is set
|
||||
die(3,"{}: Negative values not permitted in transaction!".format(hex_bytes))
|
||||
return int(r,16)
|
||||
|
||||
|
|
@ -107,11 +106,11 @@ def bytes2coin_amt(hex_bytes):
|
|||
return g.proto.coin_amt(bytes2int(hex_bytes) * g.proto.coin_amt.min_coin_unit)
|
||||
|
||||
def scriptPubKey2addr(s):
|
||||
if len(s) == 50 and s[:6] == b'76a914' and s[-4:] == b'88ac':
|
||||
if len(s) == 50 and s[:6] == '76a914' and s[-4:] == '88ac':
|
||||
return g.proto.pubhash2addr(s[6:-4],p2sh=False),'p2pkh'
|
||||
elif len(s) == 46 and s[:4] == b'a914' and s[-2:] == b'87':
|
||||
elif len(s) == 46 and s[:4] == 'a914' and s[-2:] == '87':
|
||||
return g.proto.pubhash2addr(s[4:-2],p2sh=True),'p2sh'
|
||||
elif len(s) == 44 and s[:4] == g.proto.witness_vernum_hex + b'14':
|
||||
elif len(s) == 44 and s[:4] == g.proto.witness_vernum_hex + '14':
|
||||
return g.proto.pubhash2bech32addr(s[4:]),'bech32'
|
||||
else:
|
||||
raise NotImplementedError('Unknown scriptPubKey ({})'.format(s))
|
||||
|
|
@ -119,7 +118,7 @@ def scriptPubKey2addr(s):
|
|||
from collections import OrderedDict
|
||||
class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
|
||||
def __init__(self,txhex):
|
||||
tx = list(unhexlify(txhex))
|
||||
tx = list(bytes.fromhex(txhex))
|
||||
tx_copy = tx[:]
|
||||
d = { 'raw_tx': [] }
|
||||
|
||||
|
|
@ -127,7 +126,7 @@ class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
|
|||
ret = l[:n]
|
||||
if not skip: d['raw_tx'] += ret
|
||||
del l[:n]
|
||||
return hexlify(bytes(ret[::-1] if reverse else ret))
|
||||
return bytes(ret[::-1] if reverse else ret).hex()
|
||||
|
||||
# https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers
|
||||
# For example, the number 515 is encoded as 0xfd0302.
|
||||
|
|
@ -135,8 +134,8 @@ class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
|
|||
s = l[0]
|
||||
bytes_len = 1 if s < 0xfd else 2 if s == 0xfd else 4 if s == 0xfe else 8
|
||||
if bytes_len != 1: del l[0]
|
||||
ret = int(hexlify(bytes(l[:bytes_len][::-1])),16)
|
||||
if sub_null: d['raw_tx'] += b'\0'
|
||||
ret = int(bytes(l[:bytes_len][::-1]).hex(),16)
|
||||
if sub_null: d['raw_tx'] += b'\x00'
|
||||
elif not skip: d['raw_tx'] += l[:bytes_len]
|
||||
del l[:bytes_len]
|
||||
return ret
|
||||
|
|
@ -145,7 +144,7 @@ class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
|
|||
has_witness = tx[0] == 0
|
||||
if has_witness:
|
||||
u = hshift(tx,2,skip=True)
|
||||
if u != b'0001':
|
||||
if u != '0001':
|
||||
raise IllegalWitnessFlagValue("'{}': Illegal value for flag in transaction!".format(u))
|
||||
del tx_copy[-len(tx)-2:-len(tx)]
|
||||
|
||||
|
|
@ -186,8 +185,8 @@ class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
|
|||
raise WitnessSizeMismatch('More witness data than inputs with witnesses!')
|
||||
|
||||
d['lock_time'] = bytes2int(hshift(tx,4))
|
||||
d['txid'] = hexlify(sha256(sha256(bytes(tx_copy)).digest()).digest()[::-1])
|
||||
d['unsigned_hex'] = hexlify(bytes(d['raw_tx']))
|
||||
d['txid'] = sha256(sha256(bytes(tx_copy)).digest()).digest()[::-1].hex()
|
||||
d['unsigned_hex'] = bytes(d['raw_tx']).hex()
|
||||
del d['raw_tx']
|
||||
|
||||
keys = 'txid','version','lock_time','witness_size','num_txins','txins','num_txouts','txouts','unsigned_hex'
|
||||
|
|
@ -240,7 +239,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
|
||||
class MMGenTxInput(MMGenListItem):
|
||||
for k in txio_attrs: locals()[k] = txio_attrs[k] # in lieu of inheritance
|
||||
scriptPubKey = MMGenListItemAttr('scriptPubKey','HexBytes')
|
||||
scriptPubKey = MMGenListItemAttr('scriptPubKey','HexStr')
|
||||
sequence = MMGenListItemAttr('sequence',int,typeconv=False)
|
||||
|
||||
class MMGenTxOutput(MMGenListItem):
|
||||
|
|
@ -279,7 +278,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
self.outputs = self.MMGenTxOutputList()
|
||||
self.send_amt = g.proto.coin_amt('0') # total amt minus change
|
||||
self.fee = g.proto.coin_amt('0')
|
||||
self.hex = b'' # raw serialized hex transaction
|
||||
self.hex = '' # raw serialized hex transaction
|
||||
self.label = MMGenTXLabel('')
|
||||
self.txid = ''
|
||||
self.coin_txid = ''
|
||||
|
|
@ -362,14 +361,14 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
die(2,'{}: duplicate address in transaction {}'.format(attr,io_str))
|
||||
|
||||
def update_txid(self):
|
||||
self.txid = MMGenTxID(make_chksum_6(unhexlify(self.hex)).upper())
|
||||
self.txid = MMGenTxID(make_chksum_6(bytes.fromhex(self.hex)).upper())
|
||||
|
||||
def create_raw(self):
|
||||
i = [{'txid':e.txid,'vout':e.vout} for e in self.inputs]
|
||||
if self.inputs[0].sequence:
|
||||
i[0]['sequence'] = self.inputs[0].sequence
|
||||
o = {e.addr:e.amt for e in self.outputs}
|
||||
self.hex = HexBytes(g.rpch.createrawtransaction(i,o))
|
||||
self.hex = HexStr(g.rpch.createrawtransaction(i,o))
|
||||
self.update_txid()
|
||||
|
||||
# returns true if comment added or changed
|
||||
|
|
@ -625,11 +624,11 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
self.timestamp = make_timestamp()
|
||||
|
||||
def get_hex_locktime(self):
|
||||
return int(hexlify(unhexlify(self.hex[-8:])[::-1]),16)
|
||||
return int(bytes.fromhex(self.hex[-8:])[::-1].hex(),16)
|
||||
|
||||
def set_hex_locktime(self,val):
|
||||
assert type(val) == int,'locktime value not an integer'
|
||||
self.hex = self.hex[:-8] + hexlify(unhexlify('{:08x}'.format(val))[::-1])
|
||||
self.hex = self.hex[:-8] + bytes.fromhex('{:08x}'.format(val))[::-1].hex()
|
||||
|
||||
def get_blockcount(self):
|
||||
return int(g.rpch.getblockcount())
|
||||
|
|
@ -653,7 +652,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
self.blockcount,
|
||||
('',' LT={}'.format(self.locktime))[bool(self.locktime)]
|
||||
),
|
||||
self.hex.decode(),
|
||||
self.hex,
|
||||
repr([amt_to_str(e.__dict__) for e in self.inputs]),
|
||||
repr([amt_to_str(e.__dict__) for e in self.outputs])
|
||||
]
|
||||
|
|
@ -661,7 +660,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
lines.append(baseconv.b58encode(self.label.encode()))
|
||||
if self.coin_txid:
|
||||
if not self.label: lines.append('-') # keep old tx files backwards compatible
|
||||
lines.append(self.coin_txid.decode())
|
||||
lines.append(self.coin_txid)
|
||||
self.chksum = make_chksum_6(' '.join(lines))
|
||||
self.fmt_data = '\n'.join([self.chksum] + lines)+'\n'
|
||||
|
||||
|
|
@ -721,13 +720,13 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
return False
|
||||
|
||||
try:
|
||||
self.hex = HexBytes(ret['hex'])
|
||||
self.hex = HexStr(ret['hex'])
|
||||
self.compare_size_and_estimated_size()
|
||||
dt = DeserializedTX(self.hex)
|
||||
self.check_hex_tx_matches_mmgen_tx(dt)
|
||||
self.coin_txid = CoinTxID(dt['txid'],on_fail='raise')
|
||||
self.check_sigs(dt)
|
||||
if not self.coin_txid.decode() == g.rpch.decoderawtransaction(ret['hex'])['txid']:
|
||||
if not self.coin_txid == g.rpch.decoderawtransaction(ret['hex'])['txid']:
|
||||
raise BadMMGenTxID('txid mismatch (after signing)')
|
||||
msg('OK')
|
||||
return True
|
||||
|
|
@ -782,7 +781,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
check_equal('outputs',d_hex,d_mmgen)
|
||||
|
||||
uh = deserial_tx['unsigned_hex']
|
||||
if str(self.txid) != make_chksum_6(unhexlify(uh)).upper():
|
||||
if str(self.txid) != make_chksum_6(bytes.fromhex(uh)).upper():
|
||||
raise TxHexMismatch('MMGen TxID ({}) does not match hex transaction data!\n{}'.format(self.txid,m))
|
||||
|
||||
def check_pubkey_scripts(self):
|
||||
|
|
@ -807,13 +806,13 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
fs = "Hex TX has {} scriptSig but input is of type '{}'!"
|
||||
for n in range(len(txins)):
|
||||
ti,mmti = txins[n],self.inputs[n]
|
||||
if ti['scriptSig'] == b'' or ( len(ti['scriptSig']) == 46 and # native P2WPKH or P2SH-P2WPKH
|
||||
ti['scriptSig'][:6] == b'16' + g.proto.witness_vernum_hex + b'14' ):
|
||||
if ti['scriptSig'] == '' or ( len(ti['scriptSig']) == 46 and # native P2WPKH or P2SH-P2WPKH
|
||||
ti['scriptSig'][:6] == '16' + g.proto.witness_vernum_hex + '14' ):
|
||||
assert 'witness' in ti, 'missing witness'
|
||||
assert type(ti['witness']) == list and len(ti['witness']) == 2, 'malformed witness'
|
||||
assert len(ti['witness'][1]) == 66, 'incorrect witness pubkey length'
|
||||
assert mmti.mmid, fs.format('witness-type','non-MMGen')
|
||||
assert mmti.mmid.mmtype == ('S','B')[ti['scriptSig']==b''],(
|
||||
assert mmti.mmid.mmtype == ('S','B')[ti['scriptSig']==''],(
|
||||
fs.format('witness-type',mmti.mmid.mmtype))
|
||||
else: # non-witness
|
||||
if mmti.mmid:
|
||||
|
|
@ -936,7 +935,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
if bogus_send:
|
||||
m = 'BOGUS transaction NOT sent: {}'
|
||||
else:
|
||||
assert ret.encode() == self.coin_txid, 'txid mismatch (after sending)'
|
||||
assert ret == self.coin_txid, 'txid mismatch (after sending)'
|
||||
m = 'Transaction sent: {}'
|
||||
self.desc = 'sent transaction'
|
||||
msg(m.format(self.coin_txid.hl()))
|
||||
|
|
@ -1034,7 +1033,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
((n+1,'')[ip],'address:',e.addr.fmt(color=True,width=addr_w) + ' '+mmid_fmt),
|
||||
('','comment:',e.label.hl() if e.label else ''),
|
||||
('','amount:','{} {}'.format(e.amt.hl(),g.dcoin))]
|
||||
items = [(n+1, 'tx,vout:','{},{}'.format(e.txid.decode(),e.vout))] + icommon + [
|
||||
items = [(n+1, 'tx,vout:','{},{}'.format(e.txid,e.vout))] + icommon + [
|
||||
('','confirmations:','{} (around {} days)'.format(confs,days) if blockcount else '')
|
||||
] if ip else icommon + [
|
||||
('','change:',green('True') if e.is_chg else '')]
|
||||
|
|
@ -1110,7 +1109,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
return out # TX label might contain non-ascii chars
|
||||
|
||||
def check_txfile_hex_data(self):
|
||||
self.hex = HexBytes(self.hex,on_fail='raise')
|
||||
self.hex = HexStr(self.hex,on_fail='raise')
|
||||
|
||||
def parse_tx_file(self,infile,metadata_only=False,silent_open=False):
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ util.py: Low-level routines imported by other modules in the MMGen suite
|
|||
|
||||
import sys,os,time,stat,re,unicodedata
|
||||
from hashlib import sha256
|
||||
from binascii import hexlify,unhexlify
|
||||
from string import hexdigits,digits
|
||||
from mmgen.color import *
|
||||
from mmgen.exception import *
|
||||
|
|
@ -260,8 +259,6 @@ def is_int(s):
|
|||
|
||||
# https://en.wikipedia.org/wiki/Base32#RFC_4648_Base32_alphabet
|
||||
# https://tools.ietf.org/html/rfc4648
|
||||
def is_hex_bytes(s): return set(list(s.lower())) <= set(list(hexdigits.lower().encode()))
|
||||
|
||||
def is_hex_str(s): return set(list(s.lower())) <= set(list(hexdigits.lower()))
|
||||
def is_hex_str_lc(s): return set(list(s)) <= set(list(hexdigits.lower()))
|
||||
def is_hex_str_uc(s): return set(list(s)) <= set(list(hexdigits.upper()))
|
||||
|
|
@ -298,12 +295,12 @@ class baseconv(object):
|
|||
@classmethod
|
||||
def b58encode(cls,s,pad=None):
|
||||
pad = cls.get_pad(s,pad,'en',cls.b58pad_lens,[bytes])
|
||||
return cls.fromhex(hexlify(s),'b58',pad=pad,tostr=True)
|
||||
return cls.fromhex(s.hex(),'b58',pad=pad,tostr=True)
|
||||
|
||||
@classmethod
|
||||
def b58decode(cls,s,pad=None):
|
||||
pad = cls.get_pad(s,pad,'de',cls.b58pad_lens_rev,[bytes,str])
|
||||
return unhexlify(cls.tohex(s,'b58',pad=pad*2 if pad else None))
|
||||
return bytes.fromhex(cls.tohex(s,'b58',pad=pad*2 if pad else None))
|
||||
|
||||
@staticmethod
|
||||
def get_pad(s,pad,op,pad_map,ok_types):
|
||||
|
|
@ -353,13 +350,13 @@ class baseconv(object):
|
|||
|
||||
deconv = [wl.index(words[::-1][i])*(base**i) for i in range(len(words))]
|
||||
ret = ('{:0{w}x}'.format(sum(deconv),w=pad or 0))
|
||||
return (('','0')[len(ret) % 2] + ret).encode() # return bytes, for consistency with hexlify()
|
||||
return (('','0')[len(ret) % 2] + ret)
|
||||
|
||||
@classmethod
|
||||
def fromhex(cls,hexnum,wl_id,pad=None,tostr=False):
|
||||
|
||||
if not is_hex_str(hexnum.decode()):
|
||||
die(2,"'{}': not a hexadecimal number".format(hexnum.decode()))
|
||||
if not is_hex_str(hexnum):
|
||||
die(2,"{!r}: not a hexadecimal number".format(hexnum))
|
||||
|
||||
wl = cls.digits[wl_id]
|
||||
base = len(wl)
|
||||
|
|
@ -411,7 +408,7 @@ def pretty_hexdump(data,gw=2,cols=8,line_nums=False):
|
|||
return ''.join(
|
||||
[
|
||||
('' if (line_nums == False or i % cols) else '{:06x}: '.format(i*gw)) +
|
||||
hexlify(data[i*gw:i*gw+gw]).decode() + ('\n',' ')[bool((i+1) % cols)]
|
||||
data[i*gw:i*gw+gw].hex() + ('\n',' ')[bool((i+1) % cols)]
|
||||
for i in range(len(data)//gw + r)
|
||||
]
|
||||
).rstrip() + '\n'
|
||||
|
|
@ -421,7 +418,7 @@ def decode_pretty_hexdump(data):
|
|||
pat = r'^[{}]+:\s+'.format(hexdigits)
|
||||
lines = [re.sub(pat,'',l) for l in data.splitlines()]
|
||||
try:
|
||||
return unhexlify(''.join((''.join(lines).split())))
|
||||
return bytes.fromhex(''.join((''.join(lines).split())))
|
||||
except:
|
||||
msg('Data not in hexdump format')
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -29,14 +29,13 @@ class TestSuiteException(Exception): pass
|
|||
class TestSuiteFatalException(Exception): pass
|
||||
|
||||
import os
|
||||
from binascii import hexlify
|
||||
from mmgen.common import *
|
||||
|
||||
def getrandnum(n): return int(hexlify(os.urandom(n)),16)
|
||||
def getrandhex(n): return hexlify(os.urandom(n)).decode()
|
||||
def getrandnum(n): return int(os.urandom(n).hex(),16)
|
||||
def getrandhex(n): return os.urandom(n).hex()
|
||||
def getrandnum_range(nbytes,rn_max):
|
||||
while True:
|
||||
rn = int(hexlify(os.urandom(nbytes)),16)
|
||||
rn = int(os.urandom(nbytes).hex(),16)
|
||||
if rn < rn_max: return rn
|
||||
|
||||
def getrandstr(num_chars,no_space=False):
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@ os.chdir(os.path.join(pn,os.pardir))
|
|||
sys.path.__setitem__(0,os.path.abspath(os.curdir))
|
||||
os.environ['MMGEN_TEST_SUITE'] = '1'
|
||||
|
||||
from binascii import hexlify
|
||||
|
||||
# Import these _after_ local path's been added to sys.path
|
||||
from mmgen.common import *
|
||||
from mmgen.obj import MMGenAddrType
|
||||
|
|
@ -81,7 +79,7 @@ if not 1 <= len(cmd_args) <= 2: opts.usage()
|
|||
addr_type = MMGenAddrType(opt.type or g.proto.dfl_mmtype)
|
||||
|
||||
def pyethereum_sec2addr(sec):
|
||||
return sec.decode(),hexlify(eth.privtoaddr(sec.decode())).decode()
|
||||
return sec,eth.privtoaddr(sec).hex()
|
||||
|
||||
def keyconv_sec2addr(sec):
|
||||
p = sp.Popen(['keyconv','-C',g.coin,sec.wif],stderr=sp.PIPE,stdout=sp.PIPE)
|
||||
|
|
@ -95,7 +93,7 @@ def zcash_mini_sec2addr(sec):
|
|||
|
||||
def pycoin_sec2addr(sec):
|
||||
coin = ci.external_tests['testnet']['pycoin'][g.coin] if g.testnet else g.coin
|
||||
key = pcku.parse_key(sec.decode(),[network_for_netcode(coin)])[1]
|
||||
key = pcku.parse_key(sec,[network_for_netcode(coin)])[1]
|
||||
if key is None: die(1,"can't parse {}".format(sec))
|
||||
d = {
|
||||
'legacy': ('wif_uncompressed','address_uncompressed'),
|
||||
|
|
@ -205,7 +203,7 @@ def speed_test():
|
|||
from struct import pack,unpack
|
||||
seed = os.urandom(28)
|
||||
print('Incrementing key with each round')
|
||||
print('Starting key:', hexlify(seed+pack('I',0)))
|
||||
print('Starting key:', (seed + pack('I',0)).hex())
|
||||
import time
|
||||
start = last_t = time.time()
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@ pn = os.path.dirname(sys.argv[0])
|
|||
os.chdir(os.path.join(pn,os.pardir))
|
||||
sys.path.__setitem__(0,os.path.abspath(os.curdir))
|
||||
|
||||
from binascii import hexlify
|
||||
|
||||
# Import these _after_ local path's been added to sys.path
|
||||
from mmgen.common import *
|
||||
from mmgen.obj import *
|
||||
|
|
@ -162,20 +160,16 @@ tests = OrderedDict([
|
|||
'F00BAA12:S:9999999 comment',
|
||||
tw_pfx+'x comment')
|
||||
}),
|
||||
('HexBytes', {
|
||||
'bad': (1,[],'\0','\1','я','g','gg','FF','f00'),
|
||||
'good': ('deadbeef','f00baa12')
|
||||
}),
|
||||
('MMGenTxID', {
|
||||
'bad': (1,[],'\0','\1','я','g','gg','FF','f00','F00F0012'),
|
||||
'good': ('DEADBE','F00BAA')
|
||||
}),
|
||||
('CoinTxID',{
|
||||
'bad': (1,[],'\0','\1','я','g','gg','FF','f00','F00F0012',hexlify(r16),hexlify(r32)+b'ee'),
|
||||
'good': (hexlify(r32),)
|
||||
'bad': (1,[],'\0','\1','я','g','gg','FF','f00','F00F0012',r16.hex(),r32.hex()+'ee'),
|
||||
'good': (r32.hex(),)
|
||||
}),
|
||||
('WifKey', {
|
||||
'bad': (1,[],'\0','\1','я','g','gg','FF','f00',hexlify(r16),'2MspvWFjBbkv2wzQGqhxJUYPCk3Y2jMaxLN'),
|
||||
'bad': (1,[],'\0','\1','я','g','gg','FF','f00',r16.hex(),'2MspvWFjBbkv2wzQGqhxJUYPCk3Y2jMaxLN'),
|
||||
'good': {
|
||||
'btc': (('5KXEpVzjWreTcQoG5hX357s1969MUKNLuSfcszF6yu84kpsNZKb',
|
||||
'KwWr9rDh8KK5TtDa3HLChEvQXNYcUXpwhRFUPc5uSNnMtqNKLFhk'),
|
||||
|
|
@ -211,8 +205,8 @@ tests = OrderedDict([
|
|||
{'wif':'cSaJAXBAm9ooHpVJgoxqjDG3AcareFy29Cz8mhnNTRijjv2HLgta',
|
||||
'ret':'94fa8b90c11fea8fb907c9376b919534b0a75b9a9621edf71a78753544b4101c'})),
|
||||
}[g.coin.lower()][bool(g.testnet)],
|
||||
{'s':r32,'compressed':False,'pubkey_type':'std','ret':hexlify(r32)},
|
||||
{'s':r32,'compressed':True,'pubkey_type':'std','ret':hexlify(r32)}
|
||||
{'s':r32,'compressed':False,'pubkey_type':'std','ret':r32.hex()},
|
||||
{'s':r32,'compressed':True,'pubkey_type':'std','ret':r32.hex()}
|
||||
)
|
||||
}),
|
||||
('AddrListID', { # a rather pointless test, but do it anyway
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ test/sha2test.py: Test MMGen's SHA256 and SHA512 implementations
|
|||
"""
|
||||
|
||||
import sys,os
|
||||
from binascii import hexlify
|
||||
from mmgen.sha2 import Sha256,Sha512
|
||||
from mmgen.util import die
|
||||
|
||||
|
|
@ -47,10 +46,11 @@ class TestSha2(object):
|
|||
|
||||
def compare_hashes(self,dlen,data):
|
||||
import hashlib
|
||||
sha2 = getattr(hashlib,self.desc)(data).hexdigest().encode()
|
||||
my_sha2 = self.t_cls(data).hexdigest()
|
||||
if my_sha2 != sha2:
|
||||
die(3,'Hashes do not match!\nmy_sha2: {}\nsha2: {}\n'.format(my_sha2,sha2))
|
||||
sha2_ref = getattr(hashlib,self.desc)(data).hexdigest()
|
||||
ret = self.t_cls(data).hexdigest()
|
||||
if ret != sha2_ref:
|
||||
m ='\nHashes do not match!\nReference {d}: {}\nMMGen {d}: {}'
|
||||
die(3,m.format(sha2_ref,ret,d=self.desc.upper()))
|
||||
|
||||
def test_ref(self,input_n=None):
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ class TestSha2(object):
|
|||
for i in range(rounds):
|
||||
if i+1 in (1,rounds) or not (i+1) % 10:
|
||||
msg('\rTesting random input data: {:4}/{} '.format(i+1,rounds))
|
||||
dlen = int(hexlify(os.urandom(4)),16) >> 18
|
||||
dlen = int(os.urandom(4).hex(),16) >> 18
|
||||
self.compare_hashes(dlen,os.urandom(dlen))
|
||||
msg('OK\n')
|
||||
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ def list_cmds():
|
|||
def do_between():
|
||||
if opt.pause:
|
||||
confirm_continue()
|
||||
elif opt.verbose or opt.exact_output:
|
||||
elif (opt.verbose or opt.exact_output) and not opt.skip_deps:
|
||||
sys.stderr.write('\n')
|
||||
|
||||
def list_tmpdirs():
|
||||
|
|
@ -747,7 +747,6 @@ class TestSuiteRunner(object):
|
|||
# delete files depended on by this cmd
|
||||
arg_list = [get_file_with_ext(cfgs[num]['tmpdir'],ext) for num,ext in d]
|
||||
|
||||
|
||||
if opt.resume:
|
||||
if cmd == opt.resume:
|
||||
bmsg('Resuming at {!r}'.format(cmd))
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ def end_silence():
|
|||
g.stdout_fileno = 1
|
||||
|
||||
def randbool():
|
||||
return hexlify(os.urandom(1))[1] in b'12345678'
|
||||
return os.urandom(1).hex()[0] in '13579ace'
|
||||
|
||||
def disable_debug():
|
||||
global save_debug
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class TestSuiteAutosign(TestSuiteBase):
|
|||
def get_pad_chars(n):
|
||||
ret = ''
|
||||
for i in range(n):
|
||||
m = int(hexlify(os.urandom(1)),16) % 32
|
||||
m = int(os.urandom(1).hex(),16) % 32
|
||||
ret += r'123579!@#$%^&*()_+-=[]{}"?/,.<>|'[m]
|
||||
return ret
|
||||
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
|
|||
txid = self.txsend_ui_common(t,caller=mmgen_cmd,quiet=True,bogus_send=False)
|
||||
addr = t.expect_getend('Contract address: ')
|
||||
from mmgen.altcoins.eth.tx import EthereumMMGenTX as etx
|
||||
assert etx.get_exec_status(txid.encode(),True) != 0,(
|
||||
assert etx.get_exec_status(txid,True) != 0,(
|
||||
"Contract '{}:{}' failed to execute. Aborting".format(num,key))
|
||||
if key == 'Token':
|
||||
self.write_to_tmpfile('token_addr{}'.format(num),addr+'\n')
|
||||
|
|
|
|||
|
|
@ -258,17 +258,17 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
|
|||
if not segwit and k == 'p2sh': k = 'p2pkh'
|
||||
s_beg,s_end = { 'p2pkh': ('76a914','88ac'),
|
||||
'p2sh': ('a914','87'),
|
||||
'bech32': (g.proto.witness_vernum_hex.decode()+'14','') }[k]
|
||||
'bech32': (g.proto.witness_vernum_hex + '14','') }[k]
|
||||
amt1,amt2 = {'btc':(10,40),'bch':(10,40),'ltc':(1000,4000)}[g.coin.lower()]
|
||||
ret = {
|
||||
self.lbl_id: '{}:{}'.format(g.proto.base_coin.lower(),coinaddr) if non_mmgen \
|
||||
else ('{}:{}{}'.format(al_id,idx,lbl)),
|
||||
'vout': int(getrandnum(4) % 8),
|
||||
'txid': hexlify(os.urandom(32)),
|
||||
'txid': os.urandom(32).hex(),
|
||||
'amount': g.proto.coin_amt('{}.{}'.format(amt1 + getrandnum(4) % amt2, getrandnum(4) % 100000000)),
|
||||
'address': coinaddr,
|
||||
'spendable': False,
|
||||
'scriptPubKey': '{}{}{}'.format(s_beg,coinaddr.hex.decode(),s_end).encode(),
|
||||
'scriptPubKey': '{}{}{}'.format(s_beg,coinaddr.hex,s_end),
|
||||
'confirmations': getrandnum(3) // 2 # max: 8388608 (7 digits)
|
||||
}
|
||||
return ret
|
||||
|
|
|
|||
|
|
@ -530,7 +530,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
|
|||
return self.alice_add_label_badaddr(rt_pw,'Invalid coin address for this chain: '+rt_pw)
|
||||
|
||||
def alice_add_label_badaddr2(self):
|
||||
addr = g.proto.pubhash2addr(b'00'*20,False) # mainnet zero address
|
||||
addr = g.proto.pubhash2addr('00'*20,False) # mainnet zero address
|
||||
return self.alice_add_label_badaddr(addr,'Invalid coin address for this chain: '+addr)
|
||||
|
||||
def alice_add_label_badaddr3(self):
|
||||
|
|
@ -539,7 +539,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
|
|||
"MMGen address '{}' not found in tracking wallet".format(addr))
|
||||
|
||||
def alice_add_label_badaddr4(self):
|
||||
addr = CoinProtocol(g.coin,True).pubhash2addr(b'00'*20,False) # testnet zero address
|
||||
addr = CoinProtocol(g.coin,True).pubhash2addr('00'*20,False) # testnet zero address
|
||||
return self.alice_add_label_badaddr(addr,
|
||||
"Address '{}' not found in tracking wallet".format(addr))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue