private static ExecutionState Runtime_Log(RuntimeVM vm) { var text = vm.Stack.Pop().AsString(); vm.Log(text); return(ExecutionState.Running); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
// 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); }
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 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); }
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); }
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); }
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); }
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); }
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); }
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); }
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()); }
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); }
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); } }