Browse Source

MMGenTxInput, MMGenTxOutput: make 'amt' attribute a property

- type checking 'amt' at runtime eliminates the need to reload tx module
  when g.proto changes
MMGen 6 years ago
parent
commit
785582e30d
7 changed files with 27 additions and 18 deletions
  1. 0 5
      mmgen/main_autosign.py
  2. 0 1
      mmgen/main_split.py
  3. 9 5
      mmgen/obj.py
  4. 17 1
      mmgen/tx.py
  5. 1 1
      scripts/test-release.sh
  6. 0 2
      scripts/tx-btc2bch.py
  7. 0 3
      test/unit_tests.py

+ 0 - 5
mmgen/main_autosign.py

@@ -162,7 +162,6 @@ def do_umount():
 		subprocess.call(['umount',mountpoint])
 
 def sign_tx_file(txfile):
-	from importlib import reload
 	try:
 		g.testnet = False
 		g.coin = 'BTC'
@@ -183,10 +182,6 @@ def sign_tx_file(txfile):
 		g.token = tmp_tx.dcoin
 		g.dcoin = tmp_tx.dcoin or g.coin
 
-		reload(sys.modules['mmgen.tx'])
-		if g.proto.base_coin == 'ETH':
-			reload(sys.modules['mmgen.altcoins.eth.tx'])
-
 		tx = mmgen.tx.MMGenTX(txfile)
 
 		if g.proto.sign_mode == 'daemon':

+ 0 - 1
mmgen/main_split.py

@@ -119,7 +119,6 @@ tx1.create_fn()
 gmsg("\nCreating transaction for short chain ({})".format(opt.other_coin))
 
 init_coin(opt.other_coin)
-reload(sys.modules['mmgen.tx'])
 
 tx2 = MMGenSplitTX()
 tx2.inputs = tx1.inputs

+ 9 - 5
mmgen/obj.py

@@ -192,9 +192,10 @@ class Hilite(object):
 # Reassignment and deletion forbidden
 class MMGenImmutableAttr(object): # Descriptor
 
-	def __init__(self,name,dtype,typeconv=True):
+	def __init__(self,name,dtype,typeconv=True,no_type_check=False):
 		self.typeconv = typeconv
-		assert type(dtype) in (str,type)
+		self.no_type_check = no_type_check
+		assert type(dtype) in (str,type) or dtype is None
 		self.name = name
 		self.dtype = dtype
 
@@ -214,10 +215,11 @@ class MMGenImmutableAttr(object): # Descriptor
 			instance.__dict__[self.name] = \
 				globals()[self.dtype](value,on_fail='raise') if type(self.dtype) == str else self.dtype(value)
 		else:               # check type
-			if type(value) != self.dtype:
+			if type(value) == self.dtype or self.no_type_check:
+				instance.__dict__[self.name] = value
+			else:
 				m = "Attribute '{}' of {} instance must of type {}"
 				raise TypeError(m.format(self.name,type(instance),self.dtype))
-			instance.__dict__[self.name] = value
 
 	def __delete__(self,instance):
 		m = "Atribute '{}' of {} instance cannot be deleted"
@@ -250,11 +252,13 @@ class MMGenListItemAttr(MMGenImmutableAttr): # Descriptor
 class MMGenListItem(MMGenObject):
 
 	valid_attrs = None
+	valid_attrs_extra = set()
 
 	def __init__(self,*args,**kwargs):
 		if self.valid_attrs == None:
 			type(self).valid_attrs = (
-				{e for e in dir(self) if e[:2] != '__'} - {'pformat','pmsg','pdie','valid_attrs'} )
+				( {e for e in dir(self) if e[:2] != '__'} | self.valid_attrs_extra ) -
+				{'pformat','pmsg','pdie','valid_attrs','valid_attrs_extra'} )
 		if args:
 			raise ValueError('Non-keyword args not allowed')
 		for k in kwargs:

+ 17 - 1
mmgen/tx.py

@@ -209,7 +209,7 @@ class DeserializedTX(dict,MMGenObject):
 
 class MMGenTxIO(MMGenListItem):
 	vout     = MMGenListItemAttr('vout',int,typeconv=False)
-	amt      = MMGenImmutableAttr('amt',g.proto.coin_amt,typeconv=False) # require amt to be of proper type
+	_amt     = MMGenImmutableAttr('amt',None,no_type_check=True,typeconv=False)
 	label    = MMGenListItemAttr('label','TwComment',reassign_ok=True)
 	mmid     = MMGenListItemAttr('mmid','MMGenID')
 	addr     = MMGenImmutableAttr('addr','CoinAddr')
@@ -217,6 +217,22 @@ class MMGenTxIO(MMGenListItem):
 	txid     = MMGenListItemAttr('txid','CoinTxID')
 	have_wif = MMGenListItemAttr('have_wif',bool,typeconv=False,delete_ok=True)
 
+	valid_attrs_extra = {'amt'}
+
+	# Setting self.amt is runtime-dependent, so make it a property
+	# Make underlying self._amt an MMGenImmutableAttr so that reassignment is prevented
+	@property
+	def amt(self):
+		if type(self._amt) != g.proto.coin_amt:
+			raise ValueError('{}: invalid coin_amt type (must be {})'.format(type(self._amt),g.proto.coin_amt))
+		return self._amt
+
+	@amt.setter
+	def amt(self,val):
+		if type(val) != g.proto.coin_amt:
+			raise ValueError('{}: invalid coin_amt type (must be {})'.format(type(val),g.proto.coin_amt))
+		self._amt = val
+
 class MMGenTxInput(MMGenTxIO):
 	scriptPubKey = MMGenListItemAttr('scriptPubKey','HexStr')
 	sequence     = MMGenListItemAttr('sequence',int,typeconv=False)

+ 1 - 1
scripts/test-release.sh

@@ -164,7 +164,7 @@ t_obj=(
 	"$objtest_py --coin=ltc --testnet=1")
 f_obj='Data object test complete'
 
-i_unit='Unit tests'
+i_unit='Unit'
 s_unit='Running unit'
 t_unit=("$unit_tests_py")
 f_unit='Unit tests run complete'

+ 0 - 2
scripts/tx-btc2bch.py

@@ -48,8 +48,6 @@ if opt.verbose:
 from mmgen.protocol import init_coin
 init_coin('BCH')
 
-reload(sys.modules['mmgen.tx'])
-
 if opt.verbose:
 	gmsg('Converting transaction to {} format'.format(g.coin))
 

+ 0 - 3
test/unit_tests.py

@@ -137,16 +137,13 @@ class UnitTests(object):
 					('bch',False,'test/ref/460D4D-BCH[10.19764,tl=1320969600].rawtx') )
 			from mmgen.protocol import init_coin
 			from mmgen.tx import MMGenTX
-			from importlib import reload
 			print_info('test/ref/*rawtx','MMGen reference transactions')
 			for n,(coin,tn,fn) in enumerate(fns):
 				init_coin(coin,tn)
 				rpc_init(reinit=True)
-				reload(sys.modules['mmgen.tx'])
 				test_tx(MMGenTX(fn).hex,fn,n+1)
 			init_coin('btc',False)
 			rpc_init(reinit=True)
-			reload(sys.modules['mmgen.tx'])
 			Msg('OK')
 
 		from mmgen.tx import DeserializedTX