private ContractState Deploy(ApplicationEngine engine, byte[] nefFile, byte[] manifest, StackItem data) { if (engine.ScriptContainer is not Transaction tx) { throw new InvalidOperationException(); } if (nefFile.Length == 0) { throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); } if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) { throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); } engine.AddGas(Math.Max( engine.StoragePrice * (nefFile.Length + manifest.Length), GetMinimumDeploymentFee(engine.Snapshot) )); NefFile nef = nefFile.AsSerializable <NefFile>(); ContractManifest parsedManifest = ContractManifest.Parse(manifest); UInt160 hash = Helper.GetContractHash(tx.Sender, nef.CheckSum, parsedManifest.Name); StorageKey key = CreateStorageKey(Prefix_Contract).Add(hash); if (engine.Snapshot.Contains(key)) { throw new InvalidOperationException($"Contract Already Exists: {hash}"); } ContractState contract = new ContractState { Id = GetNextAvailableId(engine.Snapshot), UpdateCounter = 0, Nef = nef, Hash = hash, Manifest = parsedManifest }; if (!contract.Manifest.IsValid(hash)) { throw new InvalidOperationException($"Invalid Manifest Hash: {hash}"); } engine.Snapshot.Add(key, new StorageItem(contract)); // Execute _deploy ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2); if (md != null) { engine.CallFromNativeContract(Hash, hash, md.Name, data, false); } engine.SendNotification(Hash, "Deploy", new VM.Types.Array { contract.Hash.ToArray() }); return(contract); }
internal bool Invoke(ApplicationEngine engine) { if (!engine.CurrentScriptHash.Equals(Hash)) { return(false); } string operation = engine.CurrentContext.EvaluationStack.Pop().GetString(); Array args = (Array)engine.CurrentContext.EvaluationStack.Pop(); if (!methods.TryGetValue(operation, out ContractMethodMetadata method)) { return(false); } ExecutionContextState state = engine.CurrentContext.GetState <ExecutionContextState>(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) { return(false); } if (!engine.AddGas(method.Price)) { return(false); } StackItem result = method.Delegate(engine, args); engine.CurrentContext.EvaluationStack.Push(result); return(true); }
private void Update(ApplicationEngine engine, byte[] nefFile, byte[] manifest, StackItem data) { if (nefFile is null && manifest is null) { throw new ArgumentException(); } engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable <ContractState>(); if (contract is null) { throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); } if (nefFile != null) { if (nefFile.Length == 0) { throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); } // Update nef contract.Nef = nefFile.AsSerializable <NefFile>(); } if (manifest != null) { if (manifest.Length == 0) { throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); } ContractManifest manifest_new = ContractManifest.Parse(manifest); if (manifest_new.Name != contract.Manifest.Name) { throw new InvalidOperationException("The name of the contract can't be changed."); } if (!manifest_new.IsValid(contract.Hash)) { throw new InvalidOperationException($"Invalid Manifest Hash: {contract.Hash}"); } contract.Manifest = manifest_new; } Check(contract.Nef.Script, contract.Manifest.Abi); contract.UpdateCounter++; // Increase update counter if (nefFile != null) { ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2); if (md != null) { engine.CallFromNativeContract(Hash, contract.Hash, md.Name, data, true); } } engine.SendNotification(Hash, "Update", new VM.Types.Array { contract.Hash.ToArray() }); }
private async ContractTask <ContractState> Deploy(ApplicationEngine engine, byte[] nefFile, byte[] manifest, StackItem data) { if (engine.ScriptContainer is not Transaction tx) { throw new InvalidOperationException(); } if (nefFile.Length == 0) { throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); } if (manifest.Length == 0) { throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); } engine.AddGas(Math.Max( engine.StoragePrice * (nefFile.Length + manifest.Length), GetMinimumDeploymentFee(engine.Snapshot) )); NefFile nef = nefFile.AsSerializable <NefFile>(); ContractManifest parsedManifest = ContractManifest.Parse(manifest); Helper.Check(nef.Script, parsedManifest.Abi); UInt160 hash = Helper.GetContractHash(tx.Sender, nef.CheckSum, parsedManifest.Name); if (Policy.IsBlocked(engine.Snapshot, hash)) { throw new InvalidOperationException($"The contract {hash} has been blocked."); } StorageKey key = CreateStorageKey(Prefix_Contract).Add(hash); if (engine.Snapshot.Contains(key)) { throw new InvalidOperationException($"Contract Already Exists: {hash}"); } ContractState contract = new() { Id = GetNextAvailableId(engine.Snapshot), UpdateCounter = 0, Nef = nef, Hash = hash, Manifest = parsedManifest }; if (!contract.Manifest.IsValid(hash)) { throw new InvalidOperationException($"Invalid Manifest Hash: {hash}"); } engine.Snapshot.Add(key, new StorageItem(contract)); await OnDeploy(engine, contract, data, false); return(contract); }
private ContractState Deploy(ApplicationEngine engine, byte[] nefFile, byte[] manifest) { if (!(engine.ScriptContainer is Transaction tx)) { throw new InvalidOperationException(); } if (nefFile.Length == 0) { throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); } if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) { throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); } engine.AddGas(engine.StoragePrice * (nefFile.Length + manifest.Length)); NefFile nef = nefFile.AsSerializable <NefFile>(); UInt160 hash = Helper.GetContractHash(tx.Sender, nef.Script); StorageKey key = CreateStorageKey(Prefix_Contract).Add(hash); if (engine.Snapshot.Storages.Contains(key)) { throw new InvalidOperationException($"Contract Already Exists: {hash}"); } ContractState contract = new ContractState { Id = GetNextAvailableId(engine.Snapshot), UpdateCounter = 0, Script = nef.Script, Hash = hash, Manifest = ContractManifest.Parse(manifest) }; if (!contract.Manifest.IsValid(hash)) { throw new InvalidOperationException($"Invalid Manifest Hash: {hash}"); } engine.Snapshot.Storages.Add(key, new StorageItem(contract)); // Execute _deploy ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy"); if (md != null) { engine.CallFromNativeContract(Hash, hash, md.Name, false); } return(contract); }
internal bool Invoke(ApplicationEngine engine) { if (!engine.CurrentScriptHash.Equals(Hash)) { return(false); } if (!engine.TryPop(out string operation)) { return(false); } if (!engine.TryPop(out Array args)) { return(false); } if (!methods.TryGetValue(operation, out ContractMethodMetadata method)) { return(false); } ExecutionContextState state = engine.CurrentContext.GetState <ExecutionContextState>(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) { return(false); } if (!engine.AddGas(method.Price)) { return(false); } List <object> parameters = new List <object>(); if (method.NeedApplicationEngine) { parameters.Add(engine); } if (method.NeedSnapshot) { parameters.Add(engine.Snapshot); } for (int i = 0; i < method.Parameters.Length; i++) { StackItem item = i < args.Count ? args[i] : StackItem.Null; parameters.Add(engine.Convert(item, method.Parameters[i])); } object returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (method.Handler.ReturnType != typeof(void)) { engine.Push(engine.Convert(returnValue)); } return(true); }
private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] manifest, StackItem data) { if (nefFile is null && manifest is null) { throw new ArgumentException(); } engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable <ContractState>(); if (contract is null) { throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); } if (contract.UpdateCounter == ushort.MaxValue) { throw new InvalidOperationException($"The contract reached the maximum number of updates."); } if (nefFile != null) { if (nefFile.Length == 0) { throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); } // Update nef contract.Nef = nefFile.AsSerializable <NefFile>(); } if (manifest != null) { if (manifest.Length == 0) { throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); } ContractManifest manifest_new = ContractManifest.Parse(manifest); if (manifest_new.Name != contract.Manifest.Name) { throw new InvalidOperationException("The name of the contract can't be changed."); } if (!manifest_new.IsValid(contract.Hash)) { throw new InvalidOperationException($"Invalid Manifest Hash: {contract.Hash}"); } contract.Manifest = manifest_new; } Helper.Check(contract.Nef.Script, contract.Manifest.Abi); contract.UpdateCounter++; // Increase update counter return(OnDeploy(engine, contract, data, true)); }
private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) { return(false); } engine.AddGas(GetRegisterPrice(engine.Snapshot)); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); StorageItem item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState state = item.GetInteroperable <CandidateState>(); state.Registered = true; return(true); }
private void Update(ApplicationEngine engine, byte[] nefFile, byte[] manifest) { if (nefFile is null && manifest is null) { throw new ArgumentException(); } engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); var contract = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable <ContractState>(); if (contract is null) { throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); } if (nefFile != null) { if (nefFile.Length == 0) { throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); } NefFile nef = nefFile.AsSerializable <NefFile>(); // Update script contract.Script = nef.Script; } if (manifest != null) { if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) { throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); } contract.Manifest = ContractManifest.Parse(manifest); if (!contract.Manifest.IsValid(contract.Hash)) { throw new InvalidOperationException($"Invalid Manifest Hash: {contract.Hash}"); } } contract.UpdateCounter++; // Increase update counter if (nefFile != null) { ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy"); if (md != null) { engine.CallFromNativeContract(Hash, contract.Hash, md.Name, true); } } }
internal async void Invoke(ApplicationEngine engine, byte version) { try { if (version != 0) { throw new InvalidOperationException($"The native contract of version {version} is not active."); } ExecutionContext context = engine.CurrentContext; ContractMethodMetadata method = methods[context.InstructionPointer]; ExecutionContextState state = context.GetState <ExecutionContextState>(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) { throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}."); } engine.AddGas(method.CpuFee * Policy.GetExecFeeFactor(engine.Snapshot) + method.StorageFee * Policy.GetStoragePrice(engine.Snapshot)); List <object> parameters = new List <object>(); if (method.NeedApplicationEngine) { parameters.Add(engine); } if (method.NeedSnapshot) { parameters.Add(engine.Snapshot); } for (int i = 0; i < method.Parameters.Length; i++) { parameters.Add(engine.Convert(context.EvaluationStack.Pop(), method.Parameters[i])); } object returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (returnValue is ContractTask task) { await task; returnValue = task.GetResult(); } if (method.Handler.ReturnType != typeof(void) && method.Handler.ReturnType != typeof(ContractTask)) { context.EvaluationStack.Push(engine.Convert(returnValue)); } } catch (Exception ex) { engine.Throw(ex); } }
private uint Renew(ApplicationEngine engine, string name) { if (!nameRegex.IsMatch(name)) { throw new ArgumentException(null, nameof(name)); } string[] names = name.Split('.'); if (names.Length != 2) { throw new ArgumentException(null, nameof(name)); } engine.AddGas(GetPrice(engine.Snapshot)); byte[] hash = GetKey(Utility.StrictUTF8.GetBytes(name)); NameState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Token).Add(hash)).GetInteroperable <NameState>(); engine.Snapshot.Delete(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash)); state.Expiration += OneYear; engine.Snapshot.Add(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash), new StorageItem(new byte[] { 0 })); return(state.Expiration); }
internal void Invoke(ApplicationEngine engine, byte version) { if (ActiveBlockIndex > Ledger.CurrentIndex(engine.Snapshot)) { throw new InvalidOperationException($"The native contract {Name} is not active."); } if (version != 0) { throw new InvalidOperationException($"The native contract of version {version} is not active."); } ExecutionContext context = engine.CurrentContext; ContractMethodMetadata method = methods[context.InstructionPointer]; ExecutionContextState state = context.GetState <ExecutionContextState>(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) { throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}."); } engine.AddGas(method.Price); List <object> parameters = new List <object>(); if (method.NeedApplicationEngine) { parameters.Add(engine); } if (method.NeedSnapshot) { parameters.Add(engine.Snapshot); } for (int i = 0; i < method.Parameters.Length; i++) { parameters.Add(engine.Convert(context.EvaluationStack.Pop(), method.Parameters[i])); } object returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (method.Handler.ReturnType != typeof(void)) { context.EvaluationStack.Push(engine.Convert(returnValue)); } }
private bool Register(ApplicationEngine engine, string name, UInt160 owner) { if (!nameRegex.IsMatch(name)) { throw new ArgumentException(null, nameof(name)); } string[] names = name.Split('.'); if (names.Length != 2) { throw new ArgumentException(null, nameof(name)); } if (!engine.CheckWitnessInternal(owner)) { throw new InvalidOperationException(); } byte[] hash = GetKey(Utility.StrictUTF8.GetBytes(name)); if (engine.Snapshot.TryGet(CreateStorageKey(Prefix_Token).Add(hash)) is not null) { return(false); } StringList roots = engine.Snapshot[CreateStorageKey(Prefix_Roots)].GetInteroperable <StringList>(); if (roots.BinarySearch(names[1]) < 0) { throw new InvalidOperationException(); } engine.AddGas(GetPrice(engine.Snapshot)); NameState state = new NameState { Owner = owner, Name = name, Description = "", Expiration = (uint)(engine.PersistingBlock.Timestamp / 1000) + OneYear }; Mint(engine, state); engine.Snapshot.Add(CreateStorageKey(Prefix_Expiration).AddBigEndian(state.Expiration).Add(hash), new StorageItem(new byte[] { 0 })); return(true); }
internal void Invoke(ApplicationEngine engine) { if (!engine.CurrentScriptHash.Equals(Hash)) { throw new InvalidOperationException("It is not allowed to use Neo.Native.Call directly to call native contracts. System.Contract.Call should be used."); } ExecutionContext context = engine.CurrentContext; string operation = context.EvaluationStack.Pop().GetString(); Array args = context.EvaluationStack.Pop <Array>(); ContractMethodMetadata method = methods[operation]; ExecutionContextState state = context.GetState <ExecutionContextState>(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) { throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}."); } engine.AddGas(method.Price); List <object> parameters = new List <object>(); if (method.NeedApplicationEngine) { parameters.Add(engine); } if (method.NeedSnapshot) { parameters.Add(engine.Snapshot); } for (int i = 0; i < method.Parameters.Length; i++) { StackItem item = i < args.Count ? args[i] : StackItem.Null; parameters.Add(engine.Convert(item, method.Parameters[i])); } object returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (method.Handler.ReturnType != typeof(void)) { context.EvaluationStack.Push(engine.Convert(returnValue)); } }