private bool ExecuteTransaction(Transaction transaction, Timestamp time, StorageChangeSetContext changeSet, Action <Hash, Event> onNotify, OracleReader oracle, BigInteger minimumFee, out byte[] result) { result = null; var runtime = new RuntimeVM(transaction.Script, this, time, transaction, changeSet, oracle, false); runtime.MinimumFee = minimumFee; runtime.ThrowOnFault = true; var state = runtime.Execute(); if (state != ExecutionState.Halt) { return(false); } var cost = runtime.UsedGas; foreach (var evt in runtime.Events) { onNotify(transaction.Hash, evt); } if (runtime.Stack.Count > 0) { var obj = runtime.Stack.Pop(); result = Serialization.Serialize(obj); } return(true); }
public object InvokeContract(string contractName, string methodName, params object[] args) { var contract = FindContract <SmartContract>(contractName); Throw.IfNull(contract, nameof(contract)); var script = ScriptUtils.BeginScript().CallContract(contractName, methodName, args).EndScript(); var changeSet = new StorageChangeSetContext(this.Storage); var vm = new RuntimeVM(script, this, this.LastBlock, null, changeSet, true); contract.SetRuntimeData(vm); var state = vm.Execute(); if (state != ExecutionState.Halt) { throw new ChainException($"Invocation of method '{methodName}' of contract '{contractName}' failed with state: " + state); } if (vm.Stack.Count == 0) { throw new ChainException($"No result, vm stack is empty"); } var result = vm.Stack.Pop(); return(result.ToObject()); }
internal bool Execute(Chain chain, Block block, StorageChangeSetContext changeSet, Action <Hash, Event> onNotify, out byte[] result) { result = null; var runtime = new RuntimeVM(this.Script, chain, block, this, changeSet, false); var state = runtime.Execute(); if (state != ExecutionState.Halt) { return(false); } var cost = runtime.UsedGas; // fee distribution TODO // if (chain.NativeTokenAddress != null && cost > 0) { //chain.TransferToken(this.PublicKey, chain.DistributionPubKey, cost); } foreach (var evt in runtime.Events) { onNotify(this.Hash, evt); } if (runtime.Stack.Count > 0) { var obj = runtime.Stack.Pop(); result = Serialization.Serialize(obj); } return(true); }
internal bool Execute(Chain chain, Block block, StorageChangeSetContext changeSet, Action <Hash, Event> onNotify, OracleReaderDelegate oracleReader, out byte[] result) { result = null; var runtime = new RuntimeVM(this.Script, chain, block, this, changeSet, false); runtime.ThrowOnFault = true; runtime.OracleReader = oracleReader; var state = runtime.Execute(); if (state != ExecutionState.Halt) { return(false); } var cost = runtime.UsedGas; foreach (var evt in runtime.Events) { onNotify(this.Hash, evt); } if (runtime.Stack.Count > 0) { var obj = runtime.Stack.Pop(); result = Serialization.Serialize(obj); } return(true); }
private static VMObject ExecuteScript(Chain chain, byte[] script, ContractInterface abi, string methodName, params object[] args) { var method = abi.FindMethod(methodName); if (method == null) { throw new Exception("ABI is missing: " + method.name); } var changeSet = new StorageChangeSetContext(chain.Storage); var oracle = chain.Nexus.GetOracleReader(); var vm = new RuntimeVM(-1, script, (uint)method.offset, chain, Address.Null, Timestamp.Now, null, changeSet, oracle, ChainTask.Null, true); //var vm = new GasMachine(script, (uint)method.offset); // TODO maybe this needs to be in inverted order? foreach (var arg in args) { vm.Stack.Push(VMObject.FromObject(arg)); } var result = vm.Execute(); if (result == ExecutionState.Halt) { return(vm.Stack.Pop()); } throw new Exception("Script execution failed for: " + method.name); }
private bool ExecuteTransaction(int index, Transaction transaction, byte[] script, Address validator, Timestamp time, StorageChangeSetContext changeSet , Action <Hash, Event> onNotify, OracleReader oracle, ITask task, BigInteger minimumFee, out VMObject result, bool allowModify = true) { if (!transaction.HasSignatures) { throw new ChainException("Cannot execute unsigned transaction"); } result = null; uint offset = 0; RuntimeVM runtime; using (var m = new ProfileMarker("new RuntimeVM")) { runtime = new RuntimeVM(index, script, offset, this, validator, time, transaction, changeSet, oracle, task, false); } runtime.MinimumFee = minimumFee; ExecutionState state; using (var m = new ProfileMarker("runtime.Execute")) state = runtime.Execute(); if (state != ExecutionState.Halt) { return(false); } //var cost = runtime.UsedGas; using (var m = new ProfileMarker("runtime.Events")) { foreach (var evt in runtime.Events) { using (var m2 = new ProfileMarker(evt.ToString())) if (allowModify) { onNotify(transaction.Hash, evt); } } } if (runtime.Stack.Count > 0) { result = runtime.Stack.Pop(); } // merge transaction oracle data oracle.MergeTxData(); return(true); }
private RuntimeVM ExecuteScript(string[] scriptString) { var script = BuildScript(scriptString); var keys = KeyPair.Generate(); var nexus = new Nexus("vmnet", keys.Address, new ConsoleLogger()); var tx = new Transaction(nexus.Name, nexus.RootChain.Name, script, 0, 0); var changeSet = new StorageChangeSetContext(new MemoryStorageContext()); var vm = new RuntimeVM(tx.Script, nexus.RootChain, null, tx, changeSet, true); vm.Execute(); return(vm); }
public VMObject InvokeScript(byte[] script) { var changeSet = new StorageChangeSetContext(this.Storage); var vm = new RuntimeVM(script, this, this.LastBlock, null, changeSet, true); var state = vm.Execute(); if (state != ExecutionState.Halt) { return(null); } if (vm.Stack.Count == 0) { throw new ChainException($"No result, vm stack is empty"); } var result = vm.Stack.Pop(); return(result); }
private bool ExecuteTransaction(int index, Transaction transaction, Timestamp time, StorageChangeSetContext changeSet, Action <Hash, Event> onNotify, OracleReader oracle, BigInteger minimumFee, out byte[] result) { result = null; RuntimeVM runtime; using (var m = new ProfileMarker("new RuntimeVM")) runtime = new RuntimeVM(index, transaction.Script, this, time, transaction, changeSet, oracle, false); runtime.MinimumFee = minimumFee; runtime.ThrowOnFault = true; ExecutionState state; using (var m = new ProfileMarker("runtime.Execute")) state = runtime.Execute(); if (state != ExecutionState.Halt) { return(false); } var cost = runtime.UsedGas; using (var m = new ProfileMarker("runtime.Events")) { foreach (var evt in runtime.Events) { using (var m2 = new ProfileMarker(evt.ToString())) onNotify(transaction.Hash, evt); } } if (runtime.Stack.Count > 0) { var obj = runtime.Stack.Pop(); result = Serialization.Serialize(obj); } return(true); }
public VMObject InvokeScript(StorageContext storage, byte[] script, Timestamp time) { var oracle = Nexus.CreateOracleReader(); var changeSet = new StorageChangeSetContext(storage); var vm = new RuntimeVM(script, this, time, null, changeSet, oracle, true); var state = vm.Execute(); if (state != ExecutionState.Halt) { return(null); } if (vm.Stack.Count == 0) { throw new ChainException($"No result, vm stack is empty"); } var result = vm.Stack.Pop(); return(result); }
public IAPIResult InvokeRawScript([APIParameter("Address or name of chain", "root")] string chainInput, [APIParameter("Serialized script bytes, in hexadecimal format", "0000000000")] string scriptData) { var chain = FindChainByInput(chainInput); if (chain == null) { return(new ErrorResult { error = "invalid chain" }); } byte[] script; try { script = Base16.Decode(scriptData); } catch { return(new ErrorResult { error = "Failed to decode script" }); } if (script.Length == 0) { return(new ErrorResult { error = "Invalid transaction script" }); } var changeSet = new StorageChangeSetContext(chain.Storage); var vm = new RuntimeVM(script, chain, null, null, changeSet, true); var state = vm.Execute(); if (state != ExecutionState.Halt) { return(new ErrorResult { error = $"Execution failed, state:{state}" }); } string encodedResult; if (vm.Stack.Count == 0) { encodedResult = ""; } else { var temp = vm.Stack.Pop(); var result = temp.ToObject(); var resultBytes = Serialization.Serialize(result); encodedResult = Base16.Encode(resultBytes); } var evts = vm.Events.Select(evt => new EventResult() { address = evt.Address.Text, kind = evt.Kind.ToString(), data = Base16.Encode(evt.Data) }); return(new ScriptResult { result = encodedResult, events = evts.ToArray() }); }