Browse Source

self.proto.pubhash2addr(): return `CoinAddr` instance

The MMGen Project 2 months ago
parent
commit
15b94038a4

+ 1 - 1
mmgen/addr.py

@@ -50,7 +50,7 @@ class MMGenAddrType(HiliteStr,InitErrors,MMGenObject):
 		'C': ati('compressed','std', True, 'p2pkh',   'p2pkh',   'wif', (), 'Compressed P2PKH address'),
 		'S': ati('segwit',    'std', True, 'segwit',  'p2sh',    'wif', (), 'Segwit P2SH-P2WPKH address'),
 		'B': ati('bech32',    'std', True, 'bech32',  'bech32',  'wif', (), 'Native Segwit (Bech32) address'),
-		'E': ati('ethereum',  'std', False,'ethereum','ethereum','privkey', ('wallet_passwd',),'Ethereum address'),
+		'E': ati('ethereum',  'std', False,'ethereum','p2pkh',   'privkey', ('wallet_passwd',),'Ethereum address'),
 		'Z': ati('zcash_z','zcash_z',False,'zcash_z', 'zcash_z', 'wif',     ('viewkey',),      'Zcash z-address'),
 		'M': ati('monero', 'monero', False,'monero',  'monero',  'spendkey',('viewkey','wallet_passwd'),'Monero address'),
 	}

+ 5 - 12
mmgen/proto/btc/addrgen.py

@@ -13,16 +13,13 @@ proto.btc.addrgen: Bitcoin address generation classes for the MMGen suite
 """
 
 from ...addrgen import addr_generator, check_data
-from ...addr import CoinAddr
 from .common import hash160
 
 class p2pkh(addr_generator.base):
 
 	@check_data
-	def to_addr(self,data):
-		return CoinAddr(
-			self.proto,
-			self.proto.pubhash2addr( hash160(data.pubkey), p2sh=False ))
+	def to_addr(self, data):
+		return self.proto.pubhash2addr(hash160(data.pubkey), 'p2pkh')
 
 class legacy(p2pkh):
 	pass
@@ -34,17 +31,13 @@ class segwit(addr_generator.base):
 
 	@check_data
 	def to_addr(self,data):
-		return CoinAddr(
-			self.proto,
-			self.proto.pubhash2segwitaddr( hash160(data.pubkey)) )
+		return self.proto.pubhash2segwitaddr(hash160(data.pubkey))
 
 	def to_segwit_redeem_script(self,data): # NB: returns hex
-		return self.proto.pubhash2redeem_script( hash160(data.pubkey) ).hex()
+		return self.proto.pubhash2redeem_script(hash160(data.pubkey)).hex()
 
 class bech32(addr_generator.base):
 
 	@check_data
 	def to_addr(self,data):
-		return CoinAddr(
-			self.proto,
-			self.proto.pubhash2bech32addr( hash160(data.pubkey) ))
+		return self.proto.pubhash2bech32addr(hash160(data.pubkey))

+ 13 - 10
mmgen/proto/btc/params.py

@@ -13,6 +13,7 @@ proto.btc.params: Bitcoin protocol
 """
 
 from ...protocol import CoinProtocol, decoded_wif, decoded_addr, _finfo, _nw
+from ...addr import CoinAddr
 from .common import b58chk_decode, b58chk_encode, hash160
 
 class mainnet(CoinProtocol.Secp256k1): # chainparams.cpp
@@ -90,11 +91,11 @@ class mainnet(CoinProtocol.Secp256k1): # chainparams.cpp
 
 		return self.decode_addr_bytes(b58chk_decode(addr))
 
-	def pubhash2addr(self, pubhash, p2sh):
+	def pubhash2addr(self, pubhash, addr_type):
 		assert len(pubhash) == self.addr_len, f'{len(pubhash)}: invalid length for pubkey hash'
-		return b58chk_encode(
-			self.addr_fmt_to_ver_bytes[('p2pkh','p2sh')[p2sh]] + pubhash
-		)
+		return CoinAddr(
+			self,
+			b58chk_encode(self.addr_fmt_to_ver_bytes[addr_type] + pubhash))
 
 	# Segwit:
 	def pubhash2redeem_script(self, pubhash):
@@ -104,15 +105,17 @@ class mainnet(CoinProtocol.Secp256k1): # chainparams.cpp
 		return bytes.fromhex(self.witness_vernum_hex + '14') + pubhash
 
 	def pubhash2segwitaddr(self, pubhash):
-		return self.pubhash2addr(
-			hash160( self.pubhash2redeem_script(pubhash) ),
-			p2sh = True )
+		return CoinAddr(
+			self,
+			self.pubhash2addr(hash160(self.pubhash2redeem_script(pubhash)), 'p2sh'))
 
 	def pubhash2bech32addr(self, pubhash):
 		from ...contrib import bech32
-		return bech32.bech32_encode(
-			hrp  = self.bech32_hrp,
-			data = [self.witness_vernum] + bech32.convertbits(list(pubhash),8,5) )
+		return CoinAddr(
+			self,
+			bech32.bech32_encode(
+				hrp  = self.bech32_hrp,
+				data = [self.witness_vernum] + bech32.convertbits(list(pubhash),8,5)))
 
 class testnet(mainnet):
 	addr_ver_info       = { '6f': 'p2pkh', 'c4': 'p2sh' }

+ 2 - 2
mmgen/proto/btc/tx/base.py

@@ -33,9 +33,9 @@ def addr2scriptPubKey(proto,addr):
 
 def scriptPubKey2addr(proto,s):
 	if len(s) == 50 and s[:6] == '76a914' and s[-4:] == '88ac':
-		return proto.pubhash2addr(bytes.fromhex(s[6:-4]), p2sh=False), 'p2pkh'
+		return proto.pubhash2addr(bytes.fromhex(s[6:-4]), 'p2pkh'), 'p2pkh'
 	elif len(s) == 46 and s[:4] == 'a914' and s[-2:] == '87':
-		return proto.pubhash2addr(bytes.fromhex(s[4:-2]), p2sh=True), 'p2sh'
+		return proto.pubhash2addr(bytes.fromhex(s[4:-2]), 'p2sh'), 'p2sh'
 	elif len(s) == 44 and s[:4] == proto.witness_vernum_hex + '14':
 		return proto.pubhash2bech32addr(bytes.fromhex(s[4:])), 'bech32'
 	else:

+ 3 - 6
mmgen/proto/eth/addrgen.py

@@ -12,13 +12,10 @@
 proto.eth.addrgen: Ethereum address generation class for the MMGen suite
 """
 
-from ...addrgen import addr_generator,check_data
-from ...addr import CoinAddr
+from ...addrgen import addr_generator, check_data
 
 class ethereum(addr_generator.keccak):
 
 	@check_data
-	def to_addr(self,data):
-		return CoinAddr(
-			self.proto,
-			self.keccak_256(data.pubkey[1:]).hexdigest()[24:] )
+	def to_addr(self, data):
+		return self.proto.pubhash2addr(self.keccak_256(data.pubkey[1:]).digest()[12:], 'p2pkh')

+ 6 - 4
mmgen/proto/eth/params.py

@@ -13,6 +13,7 @@ proto.eth.params: Ethereum protocol
 """
 
 from ...protocol import CoinProtocol,_nw,decoded_addr
+from ...addr import CoinAddr
 from ...util import is_hex_str_lc,Msg
 
 class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Secp256k1):
@@ -56,7 +57,7 @@ class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Secp256k1):
 
 	def decode_addr(self, addr):
 		if is_hex_str_lc(addr) and len(addr) == self.addr_len * 2:
-			return decoded_addr(bytes.fromhex(addr), None, 'ethereum')
+			return decoded_addr(bytes.fromhex(addr), None, 'p2pkh')
 		if self.cfg.debug:
 			Msg(f'Invalid address: {addr}')
 		return False
@@ -65,10 +66,11 @@ class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Secp256k1):
 		h = self.keccak_256(addr.encode()).digest().hex()
 		return ''.join(addr[i].upper() if int(h[i],16) > 7 else addr[i] for i in range(len(addr)))
 
-	def pubhash2addr(self,pubhash,p2sh):
+	def pubhash2addr(self, pubhash, addr_type):
 		assert len(pubhash) == 20, f'{len(pubhash)}: invalid length for {self.name} pubkey hash'
-		assert not p2sh, f'{self.name} protocol has no P2SH address format'
-		return pubhash.hex()
+		assert addr_type == 'p2pkh', (
+				f'{addr_type}: bad addr type - {self.name} protocol supports P2PKH address format only')
+		return CoinAddr(self, pubhash.hex())
 
 class testnet(mainnet):
 	chain_names = ['kovan','goerli','rinkeby']

+ 2 - 2
mmgen/proto/zec/params.py

@@ -63,10 +63,10 @@ class mainnet(mainnet):
 		else:
 			return super().preprocess_key(sec,pubkey_type)
 
-	def pubhash2addr(self,pubhash,p2sh):
+	def pubhash2addr(self,pubhash, addr_type):
 		hash_len = len(pubhash)
 		if hash_len == 20:
-			return super().pubhash2addr(pubhash,p2sh)
+			return super().pubhash2addr(pubhash, addr_type)
 		elif hash_len == 64:
 			raise NotImplementedError('Zcash z-addresses do not support pubhash2addr()')
 		else:

+ 2 - 2
mmgen/tool/coin.py

@@ -156,7 +156,7 @@ class tool_cmd(tool_cmd_base):
 		assert redeem_script_hex[:4] == '0014', f'{redeem_script_hex!r}: invalid redeem script'
 		assert len(redeem_script_hex) == 44, f'{len(redeem_script_hex)//2} bytes: invalid redeem script length'
 		from ..proto.btc.common import hash160
-		return self.proto.pubhash2addr(hash160(bytes.fromhex(redeem_script_hex)), p2sh=True)
+		return self.proto.pubhash2addr(hash160(bytes.fromhex(redeem_script_hex)), 'p2sh')
 
 	def pubhash2addr(self,pubhashhex:'sstr'):
 		"convert public key hash to address"
@@ -166,7 +166,7 @@ class tool_cmd(tool_cmd_base):
 		elif self.mmtype.name == 'bech32':
 			return self.proto.pubhash2bech32addr(pubhash)
 		else:
-			return self.proto.pubhash2addr(pubhash, self.mmtype.addr_fmt=='p2sh')
+			return self.proto.pubhash2addr(pubhash, self.mmtype.addr_fmt)
 
 	def addr2pubhash(self,addr:'sstr'):
 		"convert coin address to public key hash"

+ 2 - 2
test/cmdtest_py_d/ct_regtest.py

@@ -1591,7 +1591,7 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 
 	def alice_add_comment_badaddr2(self):
 		# mainnet zero address:
-		addr = init_proto( cfg, self.proto.coin, network='mainnet' ).pubhash2addr(bytes(20),False)
+		addr = init_proto(cfg, self.proto.coin, network='mainnet').pubhash2addr(bytes(20), 'p2pkh')
 		return self.alice_add_comment_badaddr( addr, 'invalid address', 2 )
 
 	def alice_add_comment_badaddr3(self):
@@ -1599,7 +1599,7 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 		return self.alice_add_comment_badaddr( addr, f'MMGen address {addr!r} not found in tracking wallet', 2 )
 
 	def alice_add_comment_badaddr4(self):
-		addr = self.proto.pubhash2addr(bytes(20),False) # regtest (testnet) zero address
+		addr = self.proto.pubhash2addr(bytes(20), 'p2pkh') # regtest (testnet) zero address
 		return self.alice_add_comment_badaddr( addr, f'Coin address {addr!r} not found in tracking wallet', 2 )
 
 	def alice_remove_comment1(self):