Пример #1
0
        private static ExecutionState Runtime_Log(RuntimeVM vm)
        {
            var text = vm.Stack.Pop().AsString();

            vm.Log(text);
            return(ExecutionState.Running);
        }
Пример #2
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);
        }
Пример #3
0
        private static ExecutionState Nexus_CreateToken(RuntimeVM vm)
        {
            vm.ExpectStackSize(7);

            var owner = vm.PopAddress();

            var symbol    = vm.PopString("symbol");
            var name      = vm.PopString("name");
            var maxSupply = vm.PopNumber("maxSupply");
            var decimals  = (int)vm.PopNumber("decimals");
            var flags     = vm.PopEnum <TokenFlags>("flags");
            var script    = vm.PopBytes("script");

            ContractInterface abi;

            if (vm.ProtocolVersion >= 4)
            {
                var abiBytes = vm.PopBytes("abi bytes");
                abi = ContractInterface.FromBytes(abiBytes);
            }
            else
            {
                abi = new ContractInterface();
            }

            vm.CreateToken(owner, symbol, name, maxSupply, decimals, flags, script, abi);

            return(ExecutionState.Running);
        }
Пример #4
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);
        }
Пример #5
0
        public bool MigrateMember(RuntimeVM Runtime, Address admin, Address from, Address to)
        {
            Runtime.Expect(Runtime.IsRootChain(), "must be root chain");

            if (to.IsSystem)
            {
                Runtime.Expect(to != this.Address, "can't add organization as member of itself");
            }

            var list = GetMemberList();

            if (!list.Contains <Address>(from))
            {
                return(false);
            }

            Runtime.Expect(!list.Contains <Address>(to), "target address is already a member of organization");

            list.Remove <Address>(from);
            list.Add <Address>(to);

            Runtime.Notify(EventKind.OrganizationRemove, admin, new OrganizationEventData(this.ID, from));
            Runtime.Notify(EventKind.OrganizationAdd, admin, new OrganizationEventData(this.ID, to));

            return(true);
        }
Пример #6
0
        private static ExecutionState Data_Get(RuntimeVM vm)
        {
            vm.ExpectStackSize(3);

            var contractName = vm.PopString("contract");

            vm.Expect(vm.ContractDeployed(contractName), $"contract {contractName} is not deployed");

            var field = vm.PopString("field");
            var key   = SmartContract.GetKeyForField(contractName, field, false);

            var type_obj = vm.Stack.Pop();
            var vmType   = type_obj.AsEnum <VMType>();

            if (vmType == VMType.Object)
            {
                vmType = VMType.Bytes;
            }

            var value_bytes = vm.Storage.Get(key);
            var val         = new VMObject();

            val.SetValue(value_bytes, vmType);
            vm.Stack.Push(val);

            return(ExecutionState.Running);
        }
Пример #7
0
        private static ExecutionState Map_Get(RuntimeVM vm)
        {
            vm.ExpectStackSize(4);

            var contractName = vm.PopString("contract");
            var field        = vm.PopString("field");
            var mapKey       = SmartContract.GetKeyForField(contractName, field, false);

            var entryKey = vm.Stack.Pop().AsByteArray();

            vm.Expect(entryKey.Length > 0, "invalid entry key");

            var type_obj = vm.Stack.Pop();
            var vmType   = type_obj.AsEnum <VMType>();

            var map = new StorageMap(mapKey, vm.Storage);

            var value_bytes = map.GetRaw(entryKey);

            var val = new VMObject();

            if (value_bytes == null)
            {
                val.SetDefaultValue(vmType);
            }
            else
            {
                val.SetValue(value_bytes, vmType);
            }
            vm.Stack.Push(val);

            return(ExecutionState.Running);
        }
Пример #8
0
        private static ExecutionState Runtime_SwapTokens(RuntimeVM Runtime)
        {
            ExpectStackSize(Runtime, 5);

            VMObject temp;

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.String, "expected string for target chain");
            var targetChain = temp.AsString();

            var source      = PopAddress(Runtime);
            var destination = PopAddress(Runtime);

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.String, "expected string for symbol");
            var symbol = temp.AsString();

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.Number, "expected number for amount");
            var value = temp.AsNumber();

            var token = Runtime.GetToken(symbol);

            if (token.IsFungible())
            {
                Runtime.SwapTokens(Runtime.Chain.Name, source, targetChain, destination, symbol, value, null, null);
            }
            else
            {
                var nft = Runtime.ReadToken(symbol, value);
                Runtime.SwapTokens(Runtime.Chain.Name, source, targetChain, destination, symbol, value, nft.ROM, nft.ROM);
            }

            return(ExecutionState.Running);
        }
Пример #9
0
        private static ExecutionState Runtime_BurnTokens(RuntimeVM Runtime)
        {
            ExpectStackSize(Runtime, 3);

            VMObject temp;

            var source = PopAddress(Runtime);

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.String, "expected string for symbol");
            var symbol = temp.AsString();

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.Number, "expected number for amount");
            var amount = temp.AsNumber();

            if (Runtime.Nexus.HasGenesis)
            {
                Runtime.Expect(symbol != DomainSettings.FuelTokenSymbol && symbol != DomainSettings.StakingTokenSymbol, "cannot mint system tokens after genesis");
            }

            Runtime.BurnTokens(symbol, source, amount);

            return(ExecutionState.Running);
        }
Пример #10
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);
        }
Пример #11
0
        // TODO proper exceptions
        private static ExecutionState Oracle_Read(RuntimeVM Runtime)
        {
            ExpectStackSize(Runtime, 1);

            var temp = Runtime.Stack.Pop();

            if (temp.Type != VMType.String)
            {
                return(ExecutionState.Fault);
            }

            var url = temp.AsString();

            if (Runtime.Oracle == null)
            {
                return(ExecutionState.Fault);
            }

            url = url.Trim().ToLowerInvariant();
            if (string.IsNullOrEmpty(url))
            {
                return(ExecutionState.Fault);
            }

            var result = Runtime.Oracle.Read(Runtime.Time, /*vm.Transaction.Hash, */ url);

            return(ExecutionState.Running);
        }
Пример #12
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);
        }
Пример #13
0
        private static ExecutionState Runtime_TransferToken(RuntimeVM Runtime)
        {
            Runtime.Expect(Runtime.Stack.Count >= 4, "not enough arguments in stack");

            VMObject temp;

            var source      = PopAddress(Runtime);
            var destination = PopAddress(Runtime);

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.String, "expected string for symbol");
            var symbol = temp.AsString();

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.Number, "expected number for amount");
            var tokenID = temp.AsNumber();

            var success = Runtime.TransferToken(symbol, source, destination, tokenID);

            var result = new VMObject();

            result.SetValue(success);
            Runtime.Stack.Push(result);

            return(ExecutionState.Running);
        }
Пример #14
0
        public bool AddMember(RuntimeVM Runtime, Address from, Address target)
        {
            if (from.IsSystem)
            {
                Runtime.Expect(from != this.Address, "can't add organization as member of itself");
            }

            Runtime.Expect(Runtime.IsRootChain(), "must be root chain");

            var set = GetMemberSet();

            if (set.Contains <Address>(target))
            {
                return(false);
            }

            set.Add <Address>(target);

            var list = GetMemberList();

            list.Add <Address>(target);

            Runtime.Notify(EventKind.OrganizationAdd, from, new OrganizationEventData(this.ID, target));
            return(true);
        }
Пример #15
0
        private static ExecutionState Runtime_IsMinter(RuntimeVM vm)
        {
            try
            {
                var tx = vm.Transaction;
                Throw.IfNull(tx, nameof(tx));

                vm.ExpectStackSize(1);

                var address = vm.PopAddress();
                var symbol  = vm.PopString("symbol");

                bool success = vm.IsMintingAddress(address, symbol);

                var result = new VMObject();
                result.SetValue(success);
                vm.Stack.Push(result);
            }
            catch (Exception e)
            {
                throw new VMException(vm, e.Message);
            }

            return(ExecutionState.Running);
        }
Пример #16
0
        private static ExecutionState Runtime_MintToken(RuntimeVM Runtime)
        {
            ExpectStackSize(Runtime, 4);

            VMObject temp;

            var source      = PopAddress(Runtime);
            var destination = PopAddress(Runtime);

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.String, "expected string for symbol");
            var symbol = temp.AsString();

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.Bytes, "expected bytes for rom");
            var rom = temp.AsByteArray();

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.Bytes, "expected bytes for ram");
            var ram = temp.AsByteArray();

            var tokenID = Runtime.MintToken(symbol, source, destination, rom, ram);

            var result = new VMObject();

            result.SetValue(tokenID);
            Runtime.Stack.Push(result);

            return(ExecutionState.Running);
        }
Пример #17
0
        private static ExecutionState Runtime_IsWitness(RuntimeVM vm)
        {
            try
            {
                var tx = vm.Transaction;
                Throw.IfNull(tx, nameof(tx));

                vm.ExpectStackSize(1);

                var address = vm.PopAddress();
                //var success = tx.IsSignedBy(address);
                // TODO check if this was just a bug or there was a real reason
                var success = vm.IsWitness(address);

                var result = new VMObject();
                result.SetValue(success);
                vm.Stack.Push(result);
            }
            catch (Exception e)
            {
                throw new VMException(vm, e.Message);
            }

            return(ExecutionState.Running);
        }
Пример #18
0
        private static ExecutionState Runtime_CreatePlatform(RuntimeVM Runtime)
        {
            ExpectStackSize(Runtime, 3);

            VMObject temp;

            var source = PopAddress(Runtime);

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.String, "expected string for name");
            var name = temp.AsString();

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.String, "expected string for pubaddress");
            var externalAddress = temp.AsString();

            var interopAddress = PopAddress(Runtime);

            temp = Runtime.Stack.Pop();
            Runtime.Expect(temp.Type == VMType.String, "expected string for symbol");
            var symbol = temp.AsString();

            var target = Runtime.CreatePlatform(source, name, externalAddress, interopAddress, symbol);

            var result = new VMObject();

            result.SetValue(target);
            Runtime.Stack.Push(result);

            return(ExecutionState.Running);
        }
Пример #19
0
        private static ExecutionState Map_Has(RuntimeVM vm)
        {
            vm.ExpectStackSize(3);

            var contractName = vm.PopString("contract");
            var field        = vm.PopString("field");
            var mapKey       = SmartContract.GetKeyForField(contractName, field, false);

            var entryKey = vm.Stack.Pop().AsByteArray();

            vm.Expect(entryKey.Length > 0, "invalid entry key");

            var type_obj = vm.Stack.Pop();
            var vmType   = type_obj.AsEnum <VMType>();

            var map = new StorageMap(mapKey, vm.Storage);

            var keyExists = map.ContainsKey(entryKey);

            var val = new VMObject();

            val.SetValue(keyExists);
            vm.Stack.Push(val);

            return(ExecutionState.Running);
        }
Пример #20
0
        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());
        }
Пример #21
0
        private static ExecutionState Map_Set(RuntimeVM vm)
        {
            vm.ExpectStackSize(3);

            // for security reasons we don't accept the caller to specify a contract name
            var contractName = vm.CurrentContext.Name;

            vm.Expect(vm.ContractDeployed(contractName), $"contract {contractName} is not deployed");

            var field  = vm.PopString("field");
            var mapKey = SmartContract.GetKeyForField(contractName, field, false);

            var entry_obj = vm.Stack.Pop();
            var entryKey  = entry_obj.AsByteArray();

            vm.Expect(entryKey.Length > 0, "invalid entry key");

            var value = vm.Stack.Pop();

            var map = new StorageMap(mapKey, vm.Storage);

            var value_bytes = value.AsByteArray();

            map.SetRaw(entryKey, value_bytes);

            return(ExecutionState.Running);
        }
Пример #22
0
        private static Address PopAddress(RuntimeVM vm)
        {
            var temp = vm.Stack.Pop();

            if (temp.Type == VMType.String)
            {
                var text = temp.AsString();
                if (Address.IsValidAddress(text))
                {
                    return(Address.FromText(text));
                }
                return(vm.Nexus.LookUpName(vm.Storage, text));
            }
            else
            if (temp.Type == VMType.Bytes)
            {
                var bytes = temp.AsByteArray();
                var addr  = Serialization.Unserialize <Address>(bytes);
                return(addr);
            }
            else
            {
                var addr = temp.AsInterop <Address>();
                return(addr);
            }
        }