Browse Source

addrgen.py: modularize protocol-specific code

The MMGen Project 2 years ago
parent
commit
94680db67d
6 changed files with 174 additions and 98 deletions
  1. 1 15
      mmgen/addr.py
  2. 29 83
      mmgen/addrgen.py
  3. 50 0
      mmgen/proto/btc/addrgen.py
  4. 24 0
      mmgen/proto/eth/addrgen.py
  5. 37 0
      mmgen/proto/xmr/addrgen.py
  6. 33 0
      mmgen/proto/zec/addrgen.py

+ 1 - 15
mmgen/addr.py

@@ -26,6 +26,7 @@ from .objmethods import Hilite,InitErrors,MMGenObject
 from .obj import ImmutableAttr,MMGenIdx,HexStr,get_obj
 from .seed import SeedID
 from .keygen import KeyGenerator # stub
+from .addrgen import AddrGenerator # stub
 
 ati = namedtuple('addrtype_info',
 	['name','pubkey_type','compressed','gen_method','addr_fmt','wif_label','extra_attrs','desc'])
@@ -186,18 +187,3 @@ class MoneroViewKey(HexStr):
 
 class ZcashViewKey(CoinAddr):
 	hex_width = 128
-
-def AddrGenerator(proto,addr_type):
-	"""
-	factory function returning an address generator for the specified address type
-	"""
-	if type(addr_type) == str:
-		addr_type = MMGenAddrType(proto=proto,id_str=addr_type)
-	elif type(addr_type) == MMGenAddrType:
-		assert addr_type in proto.mmtypes, f'{addr_type}: invalid address type for coin {proto.coin}'
-	else:
-		raise TypeError(f'{type(addr_type)}: incorrect argument type for {cls.__name__}()')
-
-	from .addrgen import addr_generator
-
-	return getattr(addr_generator,addr_type.name)(proto,addr_type)

+ 29 - 83
mmgen/addrgen.py

@@ -17,12 +17,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-addrgen.py: Address and view key generation classes for the MMGen suite
+addrgen.py: Address generation initialization code for the MMGen suite
 """
 
-from .proto.common import hash160,b58chk_encode
-from .addr import CoinAddr,MMGenAddrType,MoneroViewKey,ZcashViewKey
-
 # decorator for to_addr() and to_viewkey()
 def check_data(orig_func):
 	def f(self,data):
@@ -34,9 +31,7 @@ def check_data(orig_func):
 	return f
 
 class addr_generator:
-	"""
-	provide a generator for each supported address format
-	"""
+
 	class base:
 
 		def __init__(self,proto,addr_type):
@@ -45,39 +40,6 @@ class addr_generator:
 			self.compressed = addr_type.compressed
 			desc = f'AddrGenerator {type(self).__name__!r}'
 
-		def to_segwit_redeem_script(self,data):
-			raise NotImplementedError('Segwit redeem script not supported by this address type')
-
-	class p2pkh(base):
-
-		@check_data
-		def to_addr(self,data):
-			return CoinAddr(
-				self.proto,
-				self.proto.pubhash2addr( hash160(data.pubkey), p2sh=False ))
-
-	class legacy(p2pkh): pass
-	class compressed(p2pkh): pass
-
-	class segwit(base):
-
-		@check_data
-		def to_addr(self,data):
-			return CoinAddr(
-				self.proto,
-				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()
-
-	class bech32(base):
-
-		@check_data
-		def to_addr(self,data):
-			return CoinAddr(
-				self.proto,
-				self.proto.pubhash2bech32addr( hash160(data.pubkey) ))
-
 	class keccak(base):
 
 		def __init__(self,proto,addr_type):
@@ -85,47 +47,31 @@ class addr_generator:
 			from .util import get_keccak
 			self.keccak_256 = get_keccak()
 
-	class ethereum(keccak):
-
-		@check_data
-		def to_addr(self,data):
-			return CoinAddr(
-				self.proto,
-				self.keccak_256(data.pubkey[1:]).hexdigest()[24:] )
-
-	class monero(keccak):
-
-		def b58enc(self,addr_bytes):
-			from .baseconv import baseconv
-			enc = baseconv('b58').frombytes
-			l = len(addr_bytes)
-			a = ''.join([enc( addr_bytes[i*8:i*8+8], pad=11, tostr=True ) for i in range(l//8)])
-			b = enc( addr_bytes[l-l%8:], pad=7, tostr=True )
-			return a + b
-
-		@check_data
-		def to_addr(self,data):
-			step1 = self.proto.addr_fmt_to_ver_bytes['monero'] + data.pubkey
-			return CoinAddr(
-				proto = self.proto,
-				addr = self.b58enc( step1 + self.keccak_256(step1).digest()[:4]) )
-
-		@check_data
-		def to_viewkey(self,data):
-			return MoneroViewKey( data.viewkey_bytes.hex() )
-
-	class zcash_z(base):
-
-		@check_data
-		def to_addr(self,data):
-			ret = b58chk_encode(
-				self.proto.addr_fmt_to_ver_bytes['zcash_z']
-				+ data.pubkey )
-			return CoinAddr( self.proto, ret )
+def AddrGenerator(proto,addr_type):
+	"""
+	factory function returning an address generator for the specified address type
+	"""
 
-		@check_data
-		def to_viewkey(self,data):
-			ret = b58chk_encode(
-				self.proto.addr_fmt_to_ver_bytes['viewkey']
-				+ data.viewkey_bytes )
-			return ZcashViewKey( self.proto, ret )
+	package_map = {
+		'legacy':     'btc',
+		'compressed': 'btc',
+		'segwit':     'btc',
+		'bech32':     'btc',
+		'monero':     'xmr',
+		'ethereum':   'eth',
+		'zcash_z':    'zec',
+	}
+
+	from .addr import MMGenAddrType
+
+	if type(addr_type) == str:
+		addr_type = MMGenAddrType(proto=proto,id_str=addr_type)
+	elif type(addr_type) == MMGenAddrType:
+		assert addr_type in proto.mmtypes, f'{addr_type}: invalid address type for coin {proto.coin}'
+	else:
+		raise TypeError(f'{type(addr_type)}: incorrect argument type for {cls.__name__}()')
+
+	import importlib
+	return getattr(
+		importlib.import_module(f'mmgen.proto.{package_map[addr_type.name]}.addrgen'),
+		addr_type.name )(proto,addr_type)

+ 50 - 0
mmgen/proto/btc/addrgen.py

@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+#
+# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
+# Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
+# Licensed under the GNU General Public License, Version 3:
+#   https://www.gnu.org/licenses
+# Public project repositories:
+#   https://github.com/mmgen/mmgen
+#   https://gitlab.com/mmgen/mmgen
+
+"""
+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 ))
+
+class legacy(p2pkh):
+	pass
+
+class compressed(p2pkh):
+	pass
+
+class segwit(addr_generator.base):
+
+	@check_data
+	def to_addr(self,data):
+		return CoinAddr(
+			self.proto,
+			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()
+
+class bech32(addr_generator.base):
+
+	@check_data
+	def to_addr(self,data):
+		return CoinAddr(
+			self.proto,
+			self.proto.pubhash2bech32addr( hash160(data.pubkey) ))

+ 24 - 0
mmgen/proto/eth/addrgen.py

@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+#
+# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
+# Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
+# Licensed under the GNU General Public License, Version 3:
+#   https://www.gnu.org/licenses
+# Public project repositories:
+#   https://github.com/mmgen/mmgen
+#   https://gitlab.com/mmgen/mmgen
+
+"""
+proto.eth.addrgen: Ethereum address generation class for the MMGen suite
+"""
+
+from ...addrgen import addr_generator,check_data
+from ...addr import CoinAddr
+
+class ethereum(addr_generator.keccak):
+
+	@check_data
+	def to_addr(self,data):
+		return CoinAddr(
+			self.proto,
+			self.keccak_256(data.pubkey[1:]).hexdigest()[24:] )

+ 37 - 0
mmgen/proto/xmr/addrgen.py

@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+#
+# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
+# Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
+# Licensed under the GNU General Public License, Version 3:
+#   https://www.gnu.org/licenses
+# Public project repositories:
+#   https://github.com/mmgen/mmgen
+#   https://gitlab.com/mmgen/mmgen
+
+"""
+proto.xmr.addrgen: Monero address generation class for the MMGen suite
+"""
+
+from ...addrgen import addr_generator,check_data
+from ...addr import CoinAddr,MoneroViewKey
+
+class monero(addr_generator.keccak):
+
+	def b58enc(self,addr_bytes):
+		from ...baseconv import baseconv
+		enc = baseconv('b58').frombytes
+		l = len(addr_bytes)
+		a = ''.join([enc( addr_bytes[i*8:i*8+8], pad=11, tostr=True ) for i in range(l//8)])
+		b = enc( addr_bytes[l-l%8:], pad=7, tostr=True )
+		return a + b
+
+	@check_data
+	def to_addr(self,data):
+		step1 = self.proto.addr_fmt_to_ver_bytes['monero'] + data.pubkey
+		return CoinAddr(
+			proto = self.proto,
+			addr = self.b58enc( step1 + self.keccak_256(step1).digest()[:4]) )
+
+	@check_data
+	def to_viewkey(self,data):
+		return MoneroViewKey( data.viewkey_bytes.hex() )

+ 33 - 0
mmgen/proto/zec/addrgen.py

@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+#
+# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
+# Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
+# Licensed under the GNU General Public License, Version 3:
+#   https://www.gnu.org/licenses
+# Public project repositories:
+#   https://github.com/mmgen/mmgen
+#   https://gitlab.com/mmgen/mmgen
+
+"""
+proto.zec.addrgen: Zcash-Z address generation class for the MMGen suite
+"""
+
+from ...addrgen import addr_generator,check_data
+from ...addr import CoinAddr,ZcashViewKey
+from ..common import b58chk_encode
+
+class zcash_z(addr_generator.base):
+
+	@check_data
+	def to_addr(self,data):
+		ret = b58chk_encode(
+			self.proto.addr_fmt_to_ver_bytes['zcash_z']
+			+ data.pubkey )
+		return CoinAddr( self.proto, ret )
+
+	@check_data
+	def to_viewkey(self,data):
+		ret = b58chk_encode(
+			self.proto.addr_fmt_to_ver_bytes['viewkey']
+			+ data.viewkey_bytes )
+		return ZcashViewKey( self.proto, ret )