示例#1
0
        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());
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
        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);
        }
示例#10
0
        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);
        }
示例#11
0
        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()
            });
        }