diff --git a/fixtures/.gitignore b/fixtures/.gitignore index 9e3b66226..4f9233c88 100644 --- a/fixtures/.gitignore +++ b/fixtures/.gitignore @@ -1,5 +1,3 @@ * !.gitignore !1050514.txt -!1321456.txt -!bigtx.txt \ No newline at end of file diff --git a/neo/Core/ContractParameterType.py b/neo/Core/ContractParameterType.py deleted file mode 100644 index 7248b6acf..000000000 --- a/neo/Core/ContractParameterType.py +++ /dev/null @@ -1,20 +0,0 @@ - - - -Signature = 0 -Boolean = 1 -Integer = 2 - -Hash160 = 3 - -Hash256 = 4 - -ByteArray = 5 - -PublicKey = 6 - -String = 7 - -Array = 10 - -Void = 255 \ No newline at end of file diff --git a/neo/Implementations/Wallets/peewee/UserWallet.py b/neo/Implementations/Wallets/peewee/UserWallet.py index b30489a96..014bb9db0 100644 --- a/neo/Implementations/Wallets/peewee/UserWallet.py +++ b/neo/Implementations/Wallets/peewee/UserWallet.py @@ -27,7 +27,6 @@ TransactionInfo from autologging import logged -from neo.SmartContract.ContractParameterType import ContractParameterType import json @logged diff --git a/neo/Prompt/Commands/Invoke.py b/neo/Prompt/Commands/Invoke.py new file mode 100644 index 000000000..e99c47abb --- /dev/null +++ b/neo/Prompt/Commands/Invoke.py @@ -0,0 +1,142 @@ +from neo.Blockchain import GetBlockchain +from neo.SmartContract.ContractParameterType import ContractParameterType, ToName +from neo.VM.ScriptBuilder import ScriptBuilder +import binascii +import json + +from neo.Implementations.Blockchains.LevelDB.DBCollection import DBCollection +from neo.Implementations.Blockchains.LevelDB.DBPrefix import DBPrefix +from neo.Implementations.Blockchains.LevelDB.CachedScriptTable import CachedScriptTable +from neo.Core.State.UnspentCoinState import UnspentCoinState +from neo.Core.State.AccountState import AccountState +from neo.Core.State.CoinState import CoinState +from neo.Core.State.SpentCoinState import SpentCoinState,SpentCoinItem +from neo.Core.State.AssetState import AssetState +from neo.Core.State.ValidatorState import ValidatorState +from neo.Core.State.ContractState import ContractState +from neo.Core.State.StorageItem import StorageItem + +from neo.Core.TX.InvocationTransaction import InvocationTransaction +from neo.Core.Witness import Witness + +from neo.SmartContract.ApplicationEngine import ApplicationEngine +from neo.SmartContract import TriggerType +from neo.SmartContract.StateMachine import StateMachine + +from neo.BigInteger import BigInteger + +def InvokeContract(wallet, args, test=True): + +# print("invoking contract! %s %s " % (wallet, args)) + + BC = GetBlockchain() + + contract = BC.GetContract(args[0]) + + if contract: + descripe_contract(contract) + + params = args[1:] if len(args) > 1 else [] + + if params[0] == 'describe': + return + + params.reverse() + + sb = ScriptBuilder() + + for p in params: + print("pushitng param %s " % p) + + item = parse_param(p) + sb.push(item) + + print("Script.. %s " % sb.ToArray(cleanup=False)) + + sb.EmitAppCall(contract.Code.ScriptHash().Data) +# sb.push(binascii.hexlify(contract.Code.Script)) + print("script is %s " % sb.ToArray(cleanup=False)) + out = sb.ToArray() + print("out %s " % out) + test_invoke(out) + else: + + print("Contract %s not found" % args[0]) + + + +def test_invoke(script): + bc = GetBlockchain() + + sn = bc._db.snapshot() + + accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState) + unspentcoins = DBCollection(bc._db, sn, DBPrefix.ST_Coin, UnspentCoinState) + spentcoins = DBCollection(bc._db, sn, DBPrefix.ST_SpentCoin, SpentCoinState) + assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState) + validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator, ValidatorState) + contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState) + storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem) + + tx = InvocationTransaction() + tx.scripts = [ Witness()] + tx.Script = binascii.unhexlify(script) + print("script is %s " % tx.Script) + script_table = CachedScriptTable(contracts) + service = StateMachine(accounts, validators, assets, contracts, storages, None) + + engine = ApplicationEngine( + trigger_type=TriggerType.Application, + container=tx, + table=script_table, + service=service, + gas=tx.Gas, + testMode=True + ) + + engine.LoadScript(tx.Script, False) + + try: + # drum roll? + success = engine.Execute() + print("SUCCESSS!!!!!!") + if success: + + service.TestCommit() + + for item in engine.EvaluationStack.Items: + print("evaluation item %s " % item) + + except Exception as e: + print("COULD NOT EXECUTE %s " % e) + + +def descripe_contract(contract): + print("invoking contract - %s" % contract.Name.decode('utf-8')) + + functionCode = contract.Code + + parameters = functionCode.ParameterList + script = functionCode.Script + + method_signature = [] + for p in parameters: + method_signature.append("{ %s } " % ToName(p)) + rettype = ToName(functionCode.ReturnType) + print("method signature %s --> %s" % (' '.join(method_signature), rettype)) + + + +def parse_param(p): + + try: + val = int(p) + out = BigInteger(val) + return out + except Exception as e: + pass + + if type(p) is str: + return binascii.hexlify( p.encode('utf-8')) + + return p \ No newline at end of file diff --git a/neo/Prompt/Commands/__init__.py b/neo/Prompt/Commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neo/Prompt/__init__.py b/neo/Prompt/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neo/SmartContract/ContractParameterType.py b/neo/SmartContract/ContractParameterType.py index 5c708b8dc..334633322 100644 --- a/neo/SmartContract/ContractParameterType.py +++ b/neo/SmartContract/ContractParameterType.py @@ -15,5 +15,32 @@ class ContractParameterType(object): Hash256 = 0x04 # 256位散列值 ByteArray = 0x05 # 字节数组 PublicKey = 0x06 + String = 0x07 Array = 16 Void = 0xff + + + +import inspect +#import sys +#import importlib +import binascii + +#module = importlib.import_module('neo.SmartContract.ContractParameterType') +#items = dir(sys.modules[__name__]) + + +def ToName(param_type): + + items = inspect.getmembers(ContractParameterType) + + if type(param_type) is bytes: + param_type = int.from_bytes(param_type, 'little') + + for item in items: + name = item[0] + val = item[1] + if val == param_type: + return name + + return None diff --git a/neo/SmartContract/StateMachine.py b/neo/SmartContract/StateMachine.py index 2f95d5122..50c7ef7e8 100644 --- a/neo/SmartContract/StateMachine.py +++ b/neo/SmartContract/StateMachine.py @@ -88,7 +88,8 @@ def Commit(self): self._contracts.Commit(self._wb, False) self._storages.Commit(self._wb, False) - + def TestCommit(self): + print("test commit items....") def Blockchain_GetAccount(self, engine): hash = UInt160(data=engine.EvaluationStack.Pop().GetByteArray()) diff --git a/neo/VM/ScriptBuilder.py b/neo/VM/ScriptBuilder.py index 0e7027e33..edec9d202 100644 --- a/neo/VM/ScriptBuilder.py +++ b/neo/VM/ScriptBuilder.py @@ -11,6 +11,7 @@ from neo.VM.OpCode import * from neo.IO.MemoryStream import MemoryStream from neo.Cryptography.Helper import base256_encode +from neo.BigInteger import BigInteger class ScriptBuilder(object): """docstring for ScriptBuilder""" @@ -28,7 +29,7 @@ def add(self, op): def push(self, data): if data == None: return - if isinstance(data,int): + if type(data) is int or type(data) is BigInteger: if data == -1: return self.add(PUSHM1) elif data == 0: @@ -36,7 +37,7 @@ def push(self, data): elif data > 0 and data <= 16: return self.add(int.from_bytes(PUSH1,'little') -1 + data) else: - return self.push(base256_encode(data)) + return self.push(binascii.hexlify( base256_encode(data))) else: buf = binascii.unhexlify(data) if len(buf) <= int.from_bytes( PUSHBYTES75, 'big'): @@ -80,11 +81,11 @@ def EmitAppCall(self, scriptHash, useTailCall=False): return self.Emit(TAILCALL, scriptHash) return self.Emit(APPCALL, scriptHash) - def ToArray(self): - self.ms.flush() + def ToArray(self, cleanup=True): retval = self.ms.ToArray() - self.ms.Cleanup() - self.ms = None + if cleanup: + self.ms.Cleanup() + self.ms = None return retval diff --git a/prompt.py b/prompt.py index e64eefa3b..18b298586 100644 --- a/prompt.py +++ b/prompt.py @@ -21,6 +21,7 @@ from neo.Wallets.SignatureContext import SignatureContext from neo.Wallets.KeyPair import KeyPair from neo.Network.NodeLeader import NodeLeader +from neo.Prompt.Commands.Invoke import InvokeContract from neo import Settings from neo.Fixed8 import Fixed8 import traceback @@ -605,6 +606,17 @@ def show_contract_state(self, args): else: print("please specify a contract") + def invoke_contract(self, args): +# if not self.Wallet: +# print("please open a wallet") +# return + + if args and len(args) > 0: + return InvokeContract(self.Wallet, args) + + print("please specify a contract to invoke") + + def show_spent_coins(self, args): item = self.get_arg(args) @@ -761,12 +773,14 @@ def run(self): self.show_tx(arguments) elif command == 'header': self.show_header(arguments) - elif command =='account': + elif command == 'account': self.show_account_state(arguments) elif command == 'asset': self.show_asset_state(arguments) - elif command =='contract': + elif command == 'contract': self.show_contract_state(arguments) + elif command == 'invoke': + self.invoke_contract(arguments) elif command == 'sc': self.show_spent_coins(arguments) elif command == 'mem':