Skip to content
This repository has been archived by the owner on Nov 15, 2021. It is now read-only.

Commit

Permalink
Merge 6c8cc5c into 1d81ce3
Browse files Browse the repository at this point in the history
  • Loading branch information
jseagrave21 committed Sep 12, 2019
2 parents 1d81ce3 + 6c8cc5c commit 89d7247
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ All notable changes to this project are documented in this file.
- Fix network syncing against neo-cli ``2.10.3`` clients
- Update Python requirements
- Fix Docker configuration pip issue
- Fix param parsing input from command line


[0.9.0] 2019-08-21
Expand Down
7 changes: 4 additions & 3 deletions neo/Prompt/Commands/BuildNRun.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ def DoRun(contract_script, arguments, wallet, path, verbose=True,
except Exception:
raise TypeError

tx, result, total_ops, engine = test_deploy_and_invoke(script, i_args, wallet, from_addr,
min_fee, invocation_test_mode, debug_map=debug_map,
invoke_attrs=invoke_attrs, owners=owners, enable_debugger=enable_debugger)
tx, result, total_ops, engine = test_deploy_and_invoke(script, i_args, wallet, from_addr, min_fee,
invocation_test_mode, debug_map=debug_map,
invoke_attrs=invoke_attrs, owners=owners,
enable_debugger=enable_debugger, user_entry=True)
i_args.reverse()

return_type_results = []
Expand Down
52 changes: 43 additions & 9 deletions neo/Prompt/Commands/Invoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from neo.SmartContract import TriggerType
from neo.SmartContract.StateMachine import StateMachine
from neo.SmartContract.ContractParameterContext import ContractParametersContext
from neo.SmartContract.ContractParameter import ContractParameterType
from neo.SmartContract.Contract import Contract
from neo.Core.Cryptography.Helper import scripthash_to_address
from neo.Core.Cryptography.Crypto import Crypto
Expand Down Expand Up @@ -161,19 +162,17 @@ def InvokeWithTokenVerificationScript(wallet, tx, token, fee=Fixed8.Zero(), invo
return False


def TestInvokeContract(wallet, args, withdrawal_tx=None, from_addr=None,
min_fee=DEFAULT_MIN_FEE, invoke_attrs=None, owners=None):
def TestInvokeContract(wallet, args, withdrawal_tx=None, from_addr=None, min_fee=DEFAULT_MIN_FEE,
invoke_attrs=None, owners=None, user_entry=False):
BC = GetBlockchain()

contract = BC.GetContract(args[0])

if contract:
#
params = args[1:] if len(args) > 1 else []

params, neo_to_attach, gas_to_attach = PromptUtils.get_asset_attachments(params)
params, parse_addresses = PromptUtils.get_parse_addresses(params)
params.reverse()

if '--i' in params:
params = []
Expand All @@ -183,6 +182,25 @@ def TestInvokeContract(wallet, args, withdrawal_tx=None, from_addr=None,
return None, None, None, None, False
params.append(param)
params.reverse()
elif user_entry:
try:
i_args = []
for index, iarg in enumerate(contract.Code.ParameterList):
ptype = ContractParameterType(iarg)
param, abort = PromptUtils.verify_params(ptype, params[index])
if abort:
return None, None, None, None, False
i_args.append(param)
i_args.reverse()
params = i_args
except IndexError:
print(f"Check params. {len(contract.Code.ParameterList)} params specified and only {len(params)} given.")
return None, None, None, None, False
except Exception as e:
print("Could not parse param as %s : %s " % (ptype, e))
return None, None, None, None, False
else:
params.reverse()

sb = ScriptBuilder()

Expand Down Expand Up @@ -363,7 +381,7 @@ def test_invoke(script, wallet, outputs, withdrawal_tx=None,

def test_deploy_and_invoke(deploy_script, invoke_args, wallet,
from_addr=None, min_fee=DEFAULT_MIN_FEE, invocation_test_mode=True,
debug_map=None, invoke_attrs=None, owners=None, enable_debugger=False, snapshot=None):
debug_map=None, invoke_attrs=None, owners=None, enable_debugger=False, snapshot=None, user_entry=False):

if settings.USE_DEBUG_STORAGE:
debug_storage = DebugStorage.instance()
Expand Down Expand Up @@ -444,16 +462,32 @@ def test_deploy_and_invoke(deploy_script, invoke_args, wallet,
invoke_args, neo_to_attach, gas_to_attach = PromptUtils.get_asset_attachments(invoke_args)
invoke_args, no_parse_addresses = PromptUtils.get_parse_addresses(invoke_args)

invoke_args.reverse()

if '--i' in invoke_args:
invoke_args = []
for index, iarg in enumerate(contract_state.Code.ParameterList):
param, abort = PromptUtils.gather_param(index, iarg)
if abort:
return None, [], 0, None
else:
invoke_args.append(param)
invoke_args.append(param)
invoke_args.reverse()
elif user_entry:
try:
i_args = []
for index, iarg in enumerate(contract_state.Code.ParameterList):
ptype = ContractParameterType(iarg)
param, abort = PromptUtils.verify_params(ptype, invoke_args[index])
if abort:
return None, [], 0, None
i_args.append(param)
i_args.reverse()
invoke_args = i_args
except IndexError:
print(f"Check params. {len(contract_state.Code.ParameterList)} params specified and only {len(invoke_args)} given.")
return None, [], 0, None
except Exception as e:
print("Could not parse param as %s : %s " % (ptype, e))
return None, [], 0, None
else:
invoke_args.reverse()

sb = ScriptBuilder()
Expand Down
3 changes: 2 additions & 1 deletion neo/Prompt/Commands/SC.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ def execute(self, arguments):
logger.debug("invalid fee")
return False

tx, fee, results, num_ops, engine_success = TestInvokeContract(wallet, arguments, from_addr=from_addr, invoke_attrs=invoke_attrs, owners=owners)
tx, fee, results, num_ops, engine_success = TestInvokeContract(wallet, arguments, from_addr=from_addr, invoke_attrs=invoke_attrs,
owners=owners, user_entry=True)
if tx is not None and results is not None:

if return_type is not None:
Expand Down
16 changes: 16 additions & 0 deletions neo/Prompt/Commands/tests/test_sc_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,15 @@ def test_sc_buildrun(self):
self.assertFalse(tx)
self.assertIn("run `sc build_run help` to see supported queries", mock_print.getvalue())

# test too few args
PromptData.Wallet = self.GetWallet1(recreate=True)
with patch('sys.stdout', new=StringIO()) as mock_print:
args = ['build_run', 'neo/Prompt/Commands/tests/SampleSC.py', 'True', 'False', 'False', '070502', '02', 'add', 'AG4GfwjnvydAZodm4xEDivguCtjCFzLcJy',
] # missing third param
tx, result, total_ops, engine = CommandSC().execute(args)
self.assertFalse(tx)
self.assertIn("Check params. 3 params specified and only 2 given.", mock_print.getvalue())

# test successful build and run
PromptData.Wallet = self.GetWallet1(recreate=True)
with patch('sys.stdout', new=StringIO()) as mock_print:
Expand Down Expand Up @@ -379,6 +388,13 @@ def test_sc_invoke(self):
self.assertFalse(res)
self.assertIn("Error testing contract invoke", mock_print.getvalue())

# test too few args
with patch('sys.stdout', new=StringIO()) as mock_print:
args = ['invoke', token_hash_str, 'name'] # missing second arg
res = CommandSC().execute(args)
self.assertFalse(res)
self.assertIn("Check params. 2 params specified and only 1 given.", mock_print.getvalue())

# test with keyboard interrupt
with patch('sys.stdout', new=StringIO()) as mock_print:
with patch('neo.Prompt.Commands.SC.prompt', side_effect=[KeyboardInterrupt]):
Expand Down
66 changes: 38 additions & 28 deletions neo/Prompt/Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,48 +307,58 @@ def get_input_prompt(message):
return prompt(message)


def verify_params(ptype, param):
if ptype == ContractParameterType.String:
return str(param), False
elif ptype == ContractParameterType.Integer:
return int(param), False
elif ptype == ContractParameterType.Boolean:
return bool(param), False
elif ptype == ContractParameterType.PublicKey:
try:
return ECDSA.decode_secp256r1(param).G, False
except ValueError:
return None, True
elif ptype == ContractParameterType.ByteArray:
if isinstance(param, str) and len(param) == 34 and param[0] == 'A':
return Helper.AddrStrToScriptHash(param).Data, False
try:
res = eval(param, {"__builtins__": {'bytearray': bytearray, 'bytes': bytes}}, {})
if isinstance(res, bytes):
return bytearray(res), False
return res, False
except Exception:
pass
raise Exception("Please provide a bytearray or bytes object")

elif ptype == ContractParameterType.Array:
try:
res = eval(param)
if isinstance(res, list):
return res, False
except Exception:
pass
raise Exception("Please provide a list")
else:
raise Exception("Unknown param type %s " % ptype.name)


def gather_param(index, param_type, do_continue=True):
ptype = ContractParameterType(param_type)
prompt_message = '[Param %s] %s input: ' % (index, ptype.name)

try:
result = get_input_prompt(prompt_message)
except KeyboardInterrupt:
print("Input cancelled")
print("Input cancelled")
return None, True
except Exception as e:
print(str(e))
# no results, abort True
return None, True

try:

if ptype == ContractParameterType.String:
return str(result), False
elif ptype == ContractParameterType.Integer:
return int(result), False
elif ptype == ContractParameterType.Boolean:
return bool(result), False
elif ptype == ContractParameterType.PublicKey:
try:
return ECDSA.decode_secp256r1(result).G, False
except ValueError:
return None, True
elif ptype == ContractParameterType.ByteArray:
if isinstance(result, str) and len(result) == 34 and result[0] == 'A':
return Helper.AddrStrToScriptHash(result).Data, False
res = eval(result, {"__builtins__": {'bytearray': bytearray, 'bytes': bytes}}, {})
if isinstance(res, bytes):
return bytearray(res), False
return res, False

elif ptype == ContractParameterType.Array:
res = eval(result)
if isinstance(res, list):
return res, False
raise Exception("Please provide a list")
else:
raise Exception("Unknown param type %s " % ptype.name)
return verify_params(ptype, result)

except KeyboardInterrupt: # Control-C pressed: exit

Expand Down
12 changes: 12 additions & 0 deletions neo/Prompt/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,13 @@ def test_parse_no_address(self):
self.assertFalse(result)

def test_gather_param(self):
# test string input
with mock.patch('neo.Prompt.Utils.get_input_prompt', return_value='hello') as fake_prompt:
result, abort = Utils.gather_param(0, ContractParameterType.String)

self.assertEqual(result, 'hello')

# test integer input
with mock.patch('neo.Prompt.Utils.get_input_prompt', return_value=1) as fake_prompt:
result, abort = Utils.gather_param(0, ContractParameterType.Integer)

Expand All @@ -173,6 +175,7 @@ def test_gather_param(self):

self.assertEqual(result, 1)

# test bytearray input
with mock.patch('neo.Prompt.Utils.get_input_prompt', return_value="bytearray(b'abc')") as fake_prompt:
result, abort = Utils.gather_param(0, ContractParameterType.ByteArray)

Expand All @@ -183,6 +186,14 @@ def test_gather_param(self):

self.assertEqual(result, bytearray(b'abc'))

# test string input when expecting bytearray
with mock.patch('neo.Prompt.Utils.get_input_prompt', return_value="abc") as fake_prompt:
result, abort = Utils.gather_param(0, ContractParameterType.ByteArray, do_continue=False)

self.assertEqual(result, None)
self.assertEqual(abort, True)

# test boolean input
with mock.patch('neo.Prompt.Utils.get_input_prompt', return_value="abc") as fake_prompt:
result, abort = Utils.gather_param(0, ContractParameterType.Boolean)

Expand All @@ -199,6 +210,7 @@ def test_gather_param(self):

self.assertEqual(result, bytearray(b'\xf9\x1dkp\x85\xdb|Z\xaf\t\xf1\x9e\xee\xc1\xca<\r\xb2\xc6\xec'))

# test array input
with mock.patch('neo.Prompt.Utils.get_input_prompt', return_value='["a","b","c"]') as fake_prompt:
result, abort = Utils.gather_param(0, ContractParameterType.Array)

Expand Down
8 changes: 4 additions & 4 deletions neo/SmartContract/tests/test_gas_costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def test_build_contract_3(self):
expected_fee = Fixed8.FromDecimal(.0001)
self.assertEqual(expected_cost, engine.GasConsumed())
self.assertEqual(tx.Gas, expected_fee)
self.assertEqual(result[0].GetByteArray(), bytearray(b'\xab\xab\xab\xab\xab\xab'))
self.assertEqual(result[0].GetByteArray(), bytearray(b'abababababab'))

def test_build_contract_4(self):
"""
Expand All @@ -98,7 +98,7 @@ def test_build_contract_4(self):

tx, result, total_ops, engine = BuildAndRun(arguments, wallet, False)

expected_cost = Fixed8.FromDecimal(2.153)
expected_cost = Fixed8.FromDecimal(3.153)
expected_fee = Fixed8.FromDecimal(.0001)
self.assertEqual(expected_cost, engine.GasConsumed())
self.assertEqual(tx.Gas, expected_fee)
Expand Down Expand Up @@ -126,8 +126,8 @@ def test_build_contract_5(self):

tx, result, total_ops, engine = BuildAndRun(arguments, wallet, False)

expected_cost = Fixed8(1046600000)
expected_gas = Fixed8.FromDecimal(1.0)
expected_cost = Fixed8.FromDecimal(15.466)
expected_gas = Fixed8.FromDecimal(6)
self.assertEqual(expected_cost, engine.GasConsumed())
self.assertEqual(tx.Gas, expected_gas)

Expand Down

0 comments on commit 89d7247

Please sign in to comment.