Browse Source

proto.eth.tx: make `self.gas` an integer

The MMGen Project 7 months ago
parent
commit
8d33c6d4a9

+ 2 - 1
mmgen/main_txcreate.py

@@ -57,7 +57,8 @@ opts_data = {
 			+                        {fu} (an integer followed by {fl}).
 			+                        See FEE SPECIFICATION below.  If omitted, fee will be
 			+                        calculated using network fee estimation.
-			e- -g, --gas=         g  Specify start gas amount in Wei
+			et -g, --gas=N           Specify gas limit (integer)
+			-s -g, --gas=N           Specify gas limit for Ethereum (integer)
 			-- -i, --info            Display {a_info} and exit
 			-- -I, --inputs=      i  Specify transaction inputs (comma-separated list of
 			+                        MMGen IDs or coin addresses).  Note that ALL unspent

+ 2 - 1
mmgen/main_txdo.py

@@ -57,7 +57,8 @@ opts_data = {
 			+                         {fu} (an integer followed by {fl!r}).
 			+                         See FEE SPECIFICATION below.  If omitted, fee will be
 			+                         calculated using network fee estimation.
-			e- -g, --gas=           g Specify start gas amount in Wei
+			et -g, --gas=N            Specify gas limit (integer)
+			-s -g, --gas=N            Specify gas limit for Ethereum (integer)
 			-- -H, --hidden-incog-input-params=f,o  Read hidden incognito data from file
 			+                        'f' at offset 'o' (comma-separated)
 			-- -i, --in-fmt=        f Input is from wallet format 'f' (see FMT CODES below)

+ 2 - 1
mmgen/proto/eth/contract.py

@@ -67,9 +67,10 @@ class Contract:
 			return ret
 
 	def make_tx_in(self, *, gas, gasPrice, nonce, data):
+		assert isinstance(gas, int), f'{type(gas)}: incorrect type for ‘gas’ (must be an int)'
 		return {
 			'to':       bytes.fromhex(self.addr),
-			'startgas': gas.toWei(),
+			'startgas': gas,
 			'gasprice': gasPrice.toWei(),
 			'value':    0,
 			'nonce':    nonce,

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

@@ -44,12 +44,12 @@ class Base(TxBase):
 
 	# given absolute fee in ETH, return gas price in ETH
 	def fee_abs2gasprice(self, abs_fee):
-		return self.proto.coin_amt(int(abs_fee.toWei() // self.gas.toWei()), from_unit='wei')
+		return self.proto.coin_amt(int(abs_fee.toWei() // self.gas), from_unit='wei')
 
 	# given rel fee (gasPrice) in wei, return absolute fee using self.gas (Ethereum-only method)
 	def fee_gasPrice2abs(self, rel_fee):
 		assert isinstance(rel_fee, int), f'{rel_fee!r}: incorrect type for fee estimate (not an integer)'
-		return self.proto.coin_amt(rel_fee * self.gas.toWei(), from_unit='wei')
+		return self.proto.coin_amt(rel_fee * self.gas, from_unit='wei')
 
 	def is_replaceable(self):
 		return True

+ 2 - 1
mmgen/proto/eth/tx/info.py

@@ -16,6 +16,7 @@ from ....tx.info import TxInfo
 from ....util import fmt, pp_fmt
 from ....color import yellow, blue, cyan, pink
 from ....addr import MMGenID
+from ....obj import Int
 
 class TxInfo(TxInfo):
 	txinfo_hdr_fs = '{hdr}\n  ID={i} ({a} {c}) Sig={s} Locktime={l}\n'
@@ -56,7 +57,7 @@ class TxInfo(TxInfo):
 			m      = pink(tx.swap_memo) if tx.is_swap else None,
 			c      = tx.proto.dcoin if len(tx.outputs) else '',
 			g      = yellow(tx.pretty_fmt_fee(t['gasPrice'].to_unit('Gwei'))),
-			G      = yellow(tx.pretty_fmt_fee(t['startGas'].to_unit('Kwei'))),
+			G      = Int(t['startGas']).hl(),
 			f_mmid = mmid_disp(tx.inputs[0]),
 			t_mmid = mmid_disp(tx.outputs[0]) if tx.outputs and not tx.is_swap else '') + '\n\n'
 

+ 4 - 7
mmgen/proto/eth/tx/new.py

@@ -35,10 +35,7 @@ class New(Base, TxBase.New):
 
 		super().__init__(*args, **kwargs)
 
-		if self.cfg.gas:
-			self.gas = self.proto.coin_amt(int(self.cfg.gas), from_unit='wei')
-		else:
-			self.gas = self.proto.coin_amt(self.dfl_gas, from_unit='wei')
+		self.gas = int(self.cfg.gas or self.dfl_gas)
 
 		if self.cfg.contract_data:
 			m = "'--contract-data' option may not be used with token transaction"
@@ -82,12 +79,12 @@ class New(Base, TxBase.New):
 
 	def set_gas_with_data(self, data):
 		if not self.is_token:
-			self.gas = self.proto.coin_amt(self.dfl_gas + self.byte_cost * len(data), from_unit='wei')
+			self.gas = self.dfl_gas + self.byte_cost * len(data)
 
 	# one-shot method
 	def adj_gas_with_extra_data_len(self, extra_data_len):
 		if not (self.is_token or hasattr(self, '_gas_adjusted')):
-			self.gas += self.proto.coin_amt(self.byte_cost * extra_data_len, from_unit='wei')
+			self.gas += self.byte_cost * extra_data_len
 			self._gas_adjusted = True
 
 	async def process_cmdline_args(self, cmd_args, ad_f, ad_w):
@@ -154,7 +151,7 @@ class New(Base, TxBase.New):
 
 	# given rel fee and units, return absolute fee using self.gas
 	def fee_rel2abs(self, tx_size, amt_in_units, unit):
-		return self.proto.coin_amt(int(amt_in_units * self.gas.toWei()), from_unit=unit)
+		return self.proto.coin_amt(int(amt_in_units * self.gas), from_unit=unit)
 
 	# given fee estimate (gas price) in wei, return absolute fee, adjusting by self.cfg.fee_adjust
 	def fee_est2abs(self, net_fee):

+ 1 - 1
mmgen/proto/eth/tx/signed.py

@@ -35,7 +35,7 @@ class Signed(Completed, TxBase.Signed):
 			'to':       CoinAddr(self.proto, d['to']) if d['to'] else None,
 			'amt':      self.proto.coin_amt(d['value'], from_unit='wei'),
 			'gasPrice': self.proto.coin_amt(d['gasprice'], from_unit='wei'),
-			'startGas': self.proto.coin_amt(d['startgas'], from_unit='wei'),
+			'startGas': d['startgas'],
 			'nonce':    ETHNonce(d['nonce']),
 			'data':     HexStr(d['data']) }
 		if o['data'] and not o['to']: # token- or contract-creating transaction

+ 5 - 3
mmgen/proto/eth/tx/unsigned.py

@@ -32,7 +32,9 @@ class Unsigned(Completed, TxBase.Unsigned):
 			'to':       CoinAddr(self.proto, d['to']) if d['to'] else None,
 			'amt':      self.proto.coin_amt(d['amt']),
 			'gasPrice': self.proto.coin_amt(d['gasPrice']),
-			'startGas': self.proto.coin_amt(d['startGas']),
+			'startGas': (
+				self.proto.coin_amt(d['startGas']).toWei() if '.' in d['startGas'] # for backward compat
+				else int(d['startGas'])),
 			'nonce':    ETHNonce(d['nonce']),
 			'chainId':  None if d['chainId'] == 'None' else Int(d['chainId']),
 			'data':     HexStr(d['data'])}
@@ -43,7 +45,7 @@ class Unsigned(Completed, TxBase.Unsigned):
 	async def do_sign(self, o, wif):
 		o_conv = {
 			'to':       bytes.fromhex(o['to'] or ''),
-			'startgas': o['startGas'].toWei(),
+			'startgas': o['startGas'],
 			'gasprice': o['gasPrice'].toWei(),
 			'value':    o['amt'].toWei() if o['amt'] else 0,
 			'nonce':    o['nonce'],
@@ -129,7 +131,7 @@ class TokenUnsigned(TokenCompleted, Unsigned):
 				self.swap_memo.encode(),
 				o['expiry'])
 			tx_in = c.make_tx_in(
-				gas = self.gas * (7.8 if self.cfg.test_suite else 2),
+				gas = self.gas * (7 if self.cfg.test_suite else 2),
 				gasPrice = o['gasPrice'],
 				nonce = o['nonce'] + 1,
 				data = cdata)

+ 1 - 1
test/cmdtest_d/ethdev.py

@@ -340,7 +340,7 @@ class CmdTestEthdevMethods:
 					to_addr   = usr_addrs[i],
 					amt       = amt,
 					key       = dfl_devkey,
-					gas       = self.proto.coin_amt(120000, from_unit='wei'),
+					gas       = 120000,
 					gasPrice  = self.proto.coin_amt(8, from_unit='Gwei'))
 				rpc = await self.rpc
 				for n in range(50): # long delay for txbump

+ 34 - 12
test/cmdtest_d/ethswap.py

@@ -83,14 +83,15 @@ class CmdTestEthSwapMethods:
 	def token_fund_user(self):
 		return self._token_transfer_ops(
 			op          = 'fund_user',
-			mm_idxs     = [1],
+			mm_idxs     = [1, 2, 12],
+			token_addr  = 'token_addr1',
 			amt         = self.token_fund_amt)
 
 	def token_addrgen(self):
-		return self._token_addrgen(mm_idxs=[1], naddrs=5)
+		return self._token_addrgen(mm_idxs=[1], naddrs=12)
 
 	def token_addrimport(self):
-		return self._token_addrimport('token_addr1', '1-5', expect='5/5')
+		return self._token_addrimport('token_addr1', '1-12', expect='12/12')
 
 	def token_addrimport_inbound(self):
 		token_addr = self.read_from_tmpfile('token_addr1').strip()
@@ -176,9 +177,10 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
 	),
 	'eth_fund': (
 		'funding the ETH tracking wallet',
-		('eth_fund_mmgen_addr1', ''),
-		('eth_fund_mmgen_addr2', ''),
-		('eth_bal1',             ''),
+		('eth_fund_mmgen_addr1',  ''),
+		('eth_fund_mmgen_addr1b', ''),
+		('eth_fund_mmgen_addr2',  ''),
+		('eth_bal1',              ''),
 	),
 	'token_init': (
 		'deploying tokens and initializing the ETH token tracking wallet',
@@ -227,7 +229,8 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
 	'eth_token_swap': (
 		'swap operations (ETH -> ERC20, ERC20 -> BTC, ERC20 -> ETH)',
 		# ETH -> MM1
-		('eth_swaptxcreate3',          ''),
+		('eth_swaptxcreate3a',         ''),
+		('eth_swaptxcreate3b',         ''),
 		('eth_swaptxsign3',            ''),
 		('eth_swaptxsend3',            ''),
 		('eth_swaptxmemo3',            ''),
@@ -240,7 +243,8 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
 		('eth_swaptxreceipt4',         ''),
 		('eth_token_bal2',             ''),
 		# MM1 -> ETH
-		('eth_swaptxcreate5',          ''),
+		('eth_swaptxcreate5a',         ''),
+		('eth_swaptxcreate5b',         ''),
 		('eth_swaptxsign5',            ''),
 		('eth_etherscan_server_start', ''),
 		('eth_swaptxsend5_test',       ''),
@@ -343,6 +347,7 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
 	cmd_group_in = CmdTestEthdev.cmd_group_in + (
 		# eth_fund:
 		('fund_mmgen_addr1',         'funding user address :1)'),
+		('fund_mmgen_addr1b',        'funding user address :3)'),
 		('fund_mmgen_addr2',         'funding user address :11)'),
 		('bal1',                     'the ETH balance'),
 		# eth_swap:
@@ -367,7 +372,8 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
 
 		# eth_token_swap:
 		# ETH -> MM1
-		('swaptxcreate3',          'creating an ETH->MM1 swap transaction'),
+		('swaptxcreate3a',         'creating an ETH->MM1 swap transaction'),
+		('swaptxcreate3b',         'creating an ETH->MM1 swap transaction (specific address)'),
 		('swaptxsign3',            'signing the transaction'),
 		('swaptxsend3',            'sending the transaction'),
 		('swaptxmemo3',            'the memo of the sent transaction'),
@@ -382,7 +388,8 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
 		('token_bal2',             'the token balance'),
 
 		# MM1 -> ETH
-		('swaptxcreate5',          'creating an MM1->ETH swap transaction'),
+		('swaptxcreate5a',         'creating an MM1->ETH swap transaction'),
+		('swaptxcreate5b',         'creating an MM1->ETH swap transaction (specific address)'),
 		('swaptxsign5',            'signing the transaction'),
 		('etherscan_server_start', 'starting the Etherscan server'),
 		('swaptxsend5_test',       'testing the transaction via Etherscan'),
@@ -392,6 +399,9 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
 		('etherscan_server_stop',  'stopping the Etherscan server'),
 	)
 
+	def fund_mmgen_addr1b(self):
+		return self._fund_mmgen_addr(arg=f'{dfl_sid}:E:3,0.001')
+
 	def swaptxcreate1(self):
 		t = self._swaptxcreate(['ETH', '8.765', 'BTC'])
 		t.expect('OK? (Y/n): ', 'y')
@@ -404,7 +414,13 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
 				add_opts = ['--trade-limit=3%']),
 			expect = ':2019e4/1/0')
 
-	def swaptxcreate3(self):
+	def swaptxcreate3a(self):
+		t = self._swaptxcreate(['ETH', '0.7654321', 'ETH.MM1'])
+		t.expect(f'{dfl_sid}:E:4') # check that correct unused address was found
+		t.expect('(Y/n): ', 'y')
+		return self._swaptxcreate_ui_common(t)
+
+	def swaptxcreate3b(self):
 		t = self._swaptxcreate(['ETH', '8.765', 'ETH.MM1', f'{dfl_sid}:E:5'])
 		return self._swaptxcreate_ui_common(t)
 
@@ -424,7 +440,13 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
 		t = self._swaptxcreate(['ETH.MM1', '87.654321', 'BTC', f'{dfl_sid}:C:2'])
 		return self._swaptxcreate_ui_common(t)
 
-	def swaptxcreate5(self):
+	def swaptxcreate5a(self):
+		t = self._swaptxcreate(['ETH.MM1', '98.7654321', 'ETH'])
+		t.expect(f'{dfl_sid}:E:13') # check that correct unused address was found
+		t.expect('(Y/n): ', 'y')
+		return self._swaptxcreate_ui_common(t)
+
+	def swaptxcreate5b(self):
 		t = self._swaptxcreate(['ETH.MM1', '98.7654321', 'ETH', f'{dfl_sid}:E:12'])
 		return self._swaptxcreate_ui_common(t)