protected bool Blockchain_GetContract(ExecutionEngine engine) { UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract == null) { engine.CurrentContext.EvaluationStack.Push(new byte[0]); } else { engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(contract)); } return(true); }
private ExecutionContext CallContractInternal(ContractState contract, ContractMethodDescriptor method, CallFlags flags, bool hasReturnValue, IReadOnlyList <StackItem> args) { if (method.Safe) { flags &= ~CallFlags.WriteStates; } else { ContractState currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); if (currentContract?.CanCall(contract, method.Name) == false) { throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contract.Hash} From Contract {CurrentScriptHash}"); } } if (invocationCounter.TryGetValue(contract.Hash, out var counter)) { invocationCounter[contract.Hash] = counter + 1; } else { invocationCounter[contract.Hash] = 1; } ExecutionContextState state = CurrentContext.GetState <ExecutionContextState>(); UInt160 callingScriptHash = state.ScriptHash; CallFlags callingFlags = state.CallFlags; if (args.Count != method.Parameters.Length) { throw new InvalidOperationException($"Method {method} Expects {method.Parameters.Length} Arguments But Receives {args.Count} Arguments"); } if (hasReturnValue ^ (method.ReturnType != ContractParameterType.Void)) { throw new InvalidOperationException("The return value type does not match."); } ExecutionContext context_new = LoadContract(contract, method, flags & callingFlags); state = context_new.GetState <ExecutionContextState>(); state.CallingScriptHash = callingScriptHash; for (int i = args.Count - 1; i >= 0; i--) { context_new.EvaluationStack.Push(args[i]); } return(context_new); }
private ExecutionContext CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) { throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); } ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) { throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); } return(CallContractInternal(contract, md, flags, hasReturnValue, args)); }
internal static bool VerifyWitness(this IVerifiable verifiable, StoreView snapshot, UInt160 hash, Witness witness, long gas, out long fee) { fee = 0; using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.Clone(), gas)) { CallFlags callFlags = !witness.VerificationScript.IsStandardContract() ? CallFlags.ReadStates : CallFlags.None; byte[] verification = witness.VerificationScript; if (verification.Length == 0) { ContractState cs = NativeContract.Management.GetContract(snapshot, hash); if (cs is null) { return(false); } if (engine.LoadContract(cs, "verify", callFlags, true) is null) { return(false); } } else { if (NativeContract.IsNative(hash)) { return(false); } if (hash != witness.ScriptHash) { return(false); } engine.LoadScript(verification, callFlags, hash, 0); } engine.LoadScript(witness.InvocationScript, CallFlags.None); if (engine.Execute() == VMState.FAULT) { return(false); } if (engine.ResultStack.Count != 1 || !engine.ResultStack.Peek().GetBoolean()) { return(false); } fee = engine.GasConsumed; } return(true); }
/// <summary> /// Initializes a new instance of the <see cref="DeployedContract"/> class with the specified <see cref="ContractState"/>. /// </summary> /// <param name="contract">The <see cref="ContractState"/> corresponding to the contract.</param> public DeployedContract(ContractState contract) { if (contract is null) { throw new ArgumentNullException(nameof(contract)); } Script = null; ScriptHash = contract.Hash; ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify", -1); if (descriptor is null) { throw new NotSupportedException("The smart contract haven't got verify method."); } ParameterList = descriptor.Parameters.Select(u => u.Type).ToArray(); }
private bool Contract_GetStorageContext(ExecutionEngine engine) { ContractState contract = engine.EvaluationStack.Pop().GetInterface <ContractState>(); if (!contracts_created.TryGetValue(contract.ScriptHash, out UInt160 created)) { return(false); } if (!created.Equals(new UInt160(engine.CurrentContext.ScriptHash))) { return(false); } engine.EvaluationStack.Push(StackItem.FromInterface(new StorageContext { ScriptHash = contract.ScriptHash })); return(true); }
private bool Contract_Migrate(ExecutionEngine engine) { if (Trigger != TriggerType.Application) { return(false); } byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); if (script.Length > 1024 * 1024) { return(false); } ContractPropertyState contract_properties = (ContractPropertyState)(byte)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); UInt160 hash = script.ToScriptHash(); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract == null) { contract = new ContractState { Script = script, ContractProperties = contract_properties }; Snapshot.Contracts.Add(hash, contract); ContractsCreated.Add(hash, new UInt160(engine.CurrentContext.ScriptHash)); if (contract.HasStorage) { foreach (var pair in Snapshot.Storages.Find(engine.CurrentContext.ScriptHash).ToArray()) { Snapshot.Storages.Add(new StorageKey { ScriptHash = hash, Key = pair.Key.Key }, new StorageItem { Value = pair.Value.Value, IsConstant = false }); } } } engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(contract)); return(Contract_Destroy(engine)); }
private bool CheckDynamicInvoke(OpCode nextInstruction) { if (nextInstruction == OpCode.APPCALL || nextInstruction == OpCode.TAILCALL) { for (int i = CurrentContext.InstructionPointer + 1; i < CurrentContext.InstructionPointer + 21; i++) { if (CurrentContext.Script[i] != 0) { return(true); } } // if we get this far it is a dynamic call // now look at the current executing script // to determine if it can do dynamic calls ContractState contract = script_table.GetContractState(CurrentContext.ScriptHash); return(contract.HasDynamicInvoke); } return(true); }
private bool Contract_Destroy(ExecutionEngine engine) { UInt160 hash = new UInt160(engine.CurrentContext.ScriptHash); ContractState contract = contracts.TryGet(hash); if (contract == null) { return(true); } contracts.Delete(hash); if (contract.HasStorage) { foreach (var pair in storages.Find(hash.ToArray())) { storages.Delete(pair.Key); } } return(true); }
private static bool Contract_Create(ApplicationEngine engine) { if (engine.Trigger != TriggerType.Application) { return(false); } byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); if (script.Length > 1024 * 1024) { return(false); } var manifest = engine.CurrentContext.EvaluationStack.Pop().GetString(); if (manifest.Length > ContractManifest.MaxLength) { return(false); } UInt160 hash = script.ToScriptHash(); ContractState contract = engine.Snapshot.Contracts.TryGet(hash); if (contract != null) { return(false); } contract = new ContractState { Script = script, Manifest = ContractManifest.Parse(manifest) }; if (!contract.Manifest.IsValid(hash)) { return(false); } engine.Snapshot.Contracts.Add(hash, contract); engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(contract)); return(true); }
protected override ExecutionContext LoadToken(ushort tokenId) { ContractState contract = CurrentContext.GetState <ExecutionContextState>().Contract; if (contract is null || tokenId >= contract.Nef.Tokens.Length) { throw new InvalidOperationException(); } MethodToken token = contract.Nef.Tokens[tokenId]; if (token.ParametersCount > CurrentContext.EvaluationStack.Count) { throw new InvalidOperationException(); } StackItem[] args = new StackItem[token.ParametersCount]; for (int i = 0; i < token.ParametersCount; i++) { args[i] = Pop(); } return(CallContractInternal(token.Hash, token.Method, token.CallFlags, token.HasReturnValue, args)); }
public ExecutionContext LoadContract(ContractState contract, ContractMethodDescriptor method, CallFlags callFlags) { ExecutionContext context = LoadScript(contract.Script, rvcount: method.ReturnType == ContractParameterType.Void ? 0 : 1, initialPosition: method.Offset, configureState: p => { p.CallFlags = callFlags; p.ScriptHash = contract.Hash; p.Contract = contract; }); // Call initialization var init = contract.Manifest.Abi.GetMethod("_initialize", 0); if (init != null) { LoadContext(context.Clone(init.Offset)); } return(context); }
protected bool Contract_GetStorageContext(ExecutionEngine engine) { if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) { ContractState contract = _interface.GetInterface <ContractState>(); if (!ContractsCreated.TryGetValue(contract.ScriptHash, out UInt160 created)) { return(false); } if (!created.Equals(new UInt160(engine.CurrentContext.ScriptHash))) { return(false); } engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext { ScriptHash = contract.ScriptHash, IsReadOnly = false })); return(true); } return(false); }
private void CallContractInternal(ContractState contract, ContractMethodDescriptor method, Array args, CallFlags flags, ReturnTypeConvention convention) { if (invocationCounter.TryGetValue(contract.Hash, out var counter)) { invocationCounter[contract.Hash] = counter + 1; } else { invocationCounter[contract.Hash] = 1; } GetInvocationState(CurrentContext).Convention = convention; ExecutionContextState state = CurrentContext.GetState <ExecutionContextState>(); UInt160 callingScriptHash = state.ScriptHash; CallFlags callingFlags = state.CallFlags; if (args.Count != method.Parameters.Length) { throw new InvalidOperationException($"Method {method.Name} Expects {method.Parameters.Length} Arguments But Receives {args.Count} Arguments"); } ExecutionContext context_new = LoadContract(contract, method.Name, flags & callingFlags, false); state = context_new.GetState <ExecutionContextState>(); state.CallingScriptHash = callingScriptHash; if (NativeContract.IsNative(contract.Hash)) { context_new.EvaluationStack.Push(args); context_new.EvaluationStack.Push(method.Name); } else { for (int i = args.Count - 1; i >= 0; i--) { context_new.EvaluationStack.Push(args[i]); } } }
protected virtual bool Storage_Get(ExecutionEngine engine) { StorageContext context = engine.EvaluationStack.Pop().GetInterface <StorageContext>(); ContractState contract = Blockchain.Default.GetContract(context.ScriptHash); if (contract == null) { return(false); } if (!contract.HasStorage) { return(false); } byte[] key = engine.EvaluationStack.Pop().GetByteArray(); StorageItem item = Blockchain.Default.GetStorageItem(new StorageKey { ScriptHash = context.ScriptHash, Key = key }); engine.EvaluationStack.Push(item?.Value ?? new byte[0]); return(true); }
private static bool Contract_Destroy(ApplicationEngine engine) { if (engine.Trigger != TriggerType.Application) { return(false); } UInt160 hash = engine.CurrentScriptHash; ContractState contract = engine.Snapshot.Contracts.TryGet(hash); if (contract == null) { return(true); } engine.Snapshot.Contracts.Delete(hash); if (contract.HasStorage) { foreach (var pair in engine.Snapshot.Storages.Find(hash.ToArray())) { engine.Snapshot.Storages.Delete(pair.Key); } } return(true); }
protected bool Contract_Destroy(ExecutionEngine engine) { if (Trigger != TriggerType.Application) { return(false); } UInt160 hash = new UInt160(engine.CurrentContext.ScriptHash); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract == null) { return(true); } Snapshot.Contracts.Delete(hash); if (contract.HasStorage) { foreach (var pair in Snapshot.Storages.Find(hash.ToArray())) { Snapshot.Storages.Delete(pair.Key); } } return(true); }
private static bool Contract_Update(ApplicationEngine engine) { if (engine.Trigger != TriggerType.Application) { return(false); } byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); if (script.Length > 1024 * 1024) { return(false); } var manifest = engine.CurrentContext.EvaluationStack.Pop().GetString(); if (manifest.Length > ContractManifest.MaxLength) { return(false); } var contract = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash); if (contract is null) { return(false); } if (script.Length > 0) { UInt160 hash_new = script.ToScriptHash(); if (hash_new.Equals(engine.CurrentScriptHash)) { return(false); } if (engine.Snapshot.Contracts.TryGet(hash_new) != null) { return(false); } contract = new ContractState { Script = script, Manifest = contract.Manifest }; contract.Manifest.Abi.Hash = hash_new; engine.Snapshot.Contracts.Add(hash_new, contract); if (contract.HasStorage) { foreach (var pair in engine.Snapshot.Storages.Find(engine.CurrentScriptHash.ToArray()).ToArray()) { engine.Snapshot.Storages.Add(new StorageKey { ScriptHash = hash_new, Key = pair.Key.Key }, new StorageItem { Value = pair.Value.Value, IsConstant = false }); } } Contract_Destroy(engine); } if (manifest.Length > 0) { contract = engine.Snapshot.Contracts.GetAndChange(contract.ScriptHash); contract.Manifest = ContractManifest.Parse(manifest); if (!contract.Manifest.IsValid(contract.ScriptHash)) { return(false); } } return(true); }
internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas, WitnessFlag filter = WitnessFlag.All) { if (gas < 0) { return(false); } if (gas > MaxVerificationGas) { gas = MaxVerificationGas; } UInt160[] hashes; try { hashes = verifiable.GetScriptHashesForVerifying(snapshot); } catch (InvalidOperationException) { return(false); } if (hashes.Length != verifiable.Witnesses.Length) { return(false); } for (int i = 0; i < hashes.Length; i++) { WitnessFlag flag = verifiable.Witnesses[i].StateDependent ? WitnessFlag.StateDependent : WitnessFlag.StateIndependent; if (!filter.HasFlag(flag)) { gas -= verifiable.Witnesses[i].GasConsumed; if (gas < 0) { return(false); } continue; } using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.Clone(), gas)) { CallFlags callFlags = verifiable.Witnesses[i].StateDependent ? CallFlags.AllowStates : CallFlags.None; byte[] verification = verifiable.Witnesses[i].VerificationScript; if (verification.Length == 0) { ContractState cs = snapshot.Contracts.TryGet(hashes[i]); if (cs is null) { return(false); } if (engine.LoadContract(cs, "verify", callFlags, true) is null) { return(false); } } else { if (NativeContract.IsNative(hashes[i])) { return(false); } if (hashes[i] != verifiable.Witnesses[i].ScriptHash) { return(false); } engine.LoadScript(verification, callFlags, hashes[i], 0); } engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None); if (engine.Execute() == VMState.FAULT) { return(false); } if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) { return(false); } gas -= engine.GasConsumed; verifiable.Witnesses[i].GasConsumed = engine.GasConsumed; } } return(true); }
internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings settings, DataCache snapshot, UInt160 hash, Witness witness, long gas, out long fee) { fee = 0; Script invocationScript; try { invocationScript = new Script(witness.InvocationScript, true); } catch (BadScriptException) { return(false); } using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), null, settings, gas)) { if (witness.VerificationScript.Length == 0) { ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) { return(false); } ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1); if (md?.ReturnType != ContractParameterType.Boolean) { return(false); } engine.LoadContract(cs, md, CallFlags.ReadOnly); } else { if (NativeContract.IsNative(hash)) { return(false); } if (hash != witness.ScriptHash) { return(false); } Script verificationScript; try { verificationScript = new Script(witness.VerificationScript, true); } catch (BadScriptException) { return(false); } engine.LoadScript(verificationScript, initialPosition: 0, configureState: p => { p.CallFlags = CallFlags.ReadOnly; p.ScriptHash = hash; }); } engine.LoadScript(invocationScript, configureState: p => p.CallFlags = CallFlags.None); if (engine.Execute() == VMState.FAULT) { return(false); } if (!engine.ResultStack.Peek().GetBoolean()) { return(false); } fee = engine.GasConsumed; } return(true); }
private bool Contract_Migrate(ExecutionEngine engine) { byte[] script = engine.EvaluationStack.Pop().GetByteArray(); if (script.Length > 1024 * 1024) { return(false); } ContractParameterType[] parameter_list = engine.EvaluationStack.Pop().GetByteArray().Select(p => (ContractParameterType)p).ToArray(); if (parameter_list.Length > 252) { return(false); } ContractParameterType return_type = (ContractParameterType)(byte)engine.EvaluationStack.Pop().GetBigInteger(); ContractPropertyState contract_properties = (ContractPropertyState)(byte)engine.EvaluationStack.Pop().GetBigInteger(); if (engine.EvaluationStack.Peek().GetByteArray().Length > 252) { return(false); } string name = Encoding.UTF8.GetString(engine.EvaluationStack.Pop().GetByteArray()); if (engine.EvaluationStack.Peek().GetByteArray().Length > 252) { return(false); } string version = Encoding.UTF8.GetString(engine.EvaluationStack.Pop().GetByteArray()); if (engine.EvaluationStack.Peek().GetByteArray().Length > 252) { return(false); } string author = Encoding.UTF8.GetString(engine.EvaluationStack.Pop().GetByteArray()); if (engine.EvaluationStack.Peek().GetByteArray().Length > 252) { return(false); } string email = Encoding.UTF8.GetString(engine.EvaluationStack.Pop().GetByteArray()); if (engine.EvaluationStack.Peek().GetByteArray().Length > 65536) { return(false); } string description = Encoding.UTF8.GetString(engine.EvaluationStack.Pop().GetByteArray()); UInt160 hash = script.ToScriptHash(); ContractState contract = contracts.TryGet(hash); if (contract == null) { contract = new ContractState { Script = script, ParameterList = parameter_list, ReturnType = return_type, ContractProperties = contract_properties, Name = name, CodeVersion = version, Author = author, Email = email, Description = description }; contracts.Add(hash, contract); contracts_created.Add(hash, new UInt160(engine.CurrentContext.ScriptHash)); if (contract.HasStorage) { foreach (var pair in storages.Find(engine.CurrentContext.ScriptHash).ToArray()) { storages.Add(new StorageKey { ScriptHash = hash, Key = pair.Key.Key }, new StorageItem { Value = pair.Value.Value }); } } } engine.EvaluationStack.Push(StackItem.FromInterface(contract)); return(Contract_Destroy(engine)); }
/// <summary> /// Return true if is allowed /// </summary> /// <param name="targetContract">The contract that we are calling</param> /// <param name="targetMethod">The method that we are calling</param> /// <returns>Return true or false</returns> public bool CanCall(ContractState targetContract, string targetMethod) { return(Manifest.Permissions.Any(u => u.IsAllowed(targetContract, targetMethod))); }
internal static bool VerifyWitness(this IVerifiable verifiable, StoreView snapshot, UInt160 hash, Witness witness, long gas, out long fee) { fee = 0; using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.Clone(), null, gas)) { CallFlags callFlags = !witness.VerificationScript.IsStandardContract() ? CallFlags.ReadStates : CallFlags.None; byte[] verification = witness.VerificationScript; if (verification.Length == 0) { ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) { return(false); } if (engine.LoadContract(cs, "verify", callFlags, true, 0) is null) { return(false); } } else { if (NativeContract.IsNative(hash)) { return(false); } if (hash != witness.ScriptHash) { return(false); } engine.LoadScript(verification, initialPosition: 0, configureState: p => { p.CallFlags = callFlags; p.ScriptHash = hash; }); } engine.LoadScript(witness.InvocationScript, configureState: p => p.CallFlags = CallFlags.None); if (NativeContract.IsNative(hash)) { try { engine.StepOut(); engine.Push("verify"); } catch { } } if (engine.Execute() == VMState.FAULT) { return(false); } if (!engine.ResultStack.Peek().GetBoolean()) { return(false); } fee = engine.GasConsumed; } return(true); }
private bool Contract_Create(ExecutionEngine engine) { if (Trigger != TriggerType.Application) { return(false); } byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); if (script.Length > 1024 * 1024) { return(false); } ContractParameterType[] parameter_list = engine.CurrentContext.EvaluationStack.Pop().GetByteArray().Select(p => (ContractParameterType)p).ToArray(); if (parameter_list.Length > 252) { return(false); } ContractParameterType return_type = (ContractParameterType)(byte)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); ContractPropertyState contract_properties = (ContractPropertyState)(byte)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); if (engine.CurrentContext.EvaluationStack.Peek().GetByteArray().Length > 252) { return(false); } string name = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); if (engine.CurrentContext.EvaluationStack.Peek().GetByteArray().Length > 252) { return(false); } string version = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); if (engine.CurrentContext.EvaluationStack.Peek().GetByteArray().Length > 252) { return(false); } string author = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); if (engine.CurrentContext.EvaluationStack.Peek().GetByteArray().Length > 252) { return(false); } string email = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); if (engine.CurrentContext.EvaluationStack.Peek().GetByteArray().Length > 65536) { return(false); } string description = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); UInt160 hash = script.ToScriptHash(); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract == null) { contract = new ContractState { Script = script, ParameterList = parameter_list, ReturnType = return_type, ContractProperties = contract_properties, Name = name, CodeVersion = version, Author = author, Email = email, Description = description }; Snapshot.Contracts.Add(hash, contract); ContractsCreated.Add(hash, new UInt160(engine.CurrentContext.ScriptHash)); } engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(contract)); return(true); }
internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas) { if (gas < 0) { return(false); } UInt160[] hashes; try { hashes = verifiable.GetScriptHashesForVerifying(snapshot); } catch (InvalidOperationException) { return(false); } if (hashes.Length != verifiable.Witnesses.Length) { return(false); } for (int i = 0; i < hashes.Length; i++) { int offset; byte[] verification = verifiable.Witnesses[i].VerificationScript; if (verification.Length == 0) { ContractState cs = snapshot.Contracts.TryGet(hashes[i]); if (cs is null) { return(false); } ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify"); if (md is null) { return(false); } verification = cs.Script; offset = md.Offset; } else { if (hashes[i] != verifiable.Witnesses[i].ScriptHash) { return(false); } offset = 0; } using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, verifiable, snapshot, gas)) { engine.LoadScript(verification, CallFlags.ReadOnly).InstructionPointer = offset; engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None); if (engine.Execute() == VMState.FAULT) { return(false); } if (!engine.ResultStack.TryPop(out StackItem result) || !result.ToBoolean()) { return(false); } gas -= engine.GasConsumed; } } return(true); }
internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas, WitnessFlag filter = WitnessFlag.All) { if (gas < 0) { return(false); } if (gas > MaxVerificationGas) { gas = MaxVerificationGas; } UInt160[] hashes; try { hashes = verifiable.GetScriptHashesForVerifying(snapshot); } catch (InvalidOperationException) { return(false); } if (hashes.Length != verifiable.Witnesses.Length) { return(false); } for (int i = 0; i < hashes.Length; i++) { WitnessFlag flag = verifiable.Witnesses[i].StateDependent ? WitnessFlag.StateDependent : WitnessFlag.StateIndependent; if (!filter.HasFlag(flag)) { gas -= verifiable.Witnesses[i].GasConsumed; if (gas < 0) { return(false); } continue; } int offset; ContractMethodDescriptor init = null; byte[] verification = verifiable.Witnesses[i].VerificationScript; if (verification.Length == 0) { ContractState cs = snapshot.Contracts.TryGet(hashes[i]); if (cs is null) { return(false); } ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify"); if (md is null) { return(false); } verification = cs.Script; offset = md.Offset; init = cs.Manifest.Abi.GetMethod("_initialize"); } else { if (NativeContract.IsNative(hashes[i])) { return(false); } if (hashes[i] != verifiable.Witnesses[i].ScriptHash) { return(false); } offset = 0; } using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.Clone(), gas)) { CallFlags callFlags = verifiable.Witnesses[i].StateDependent ? CallFlags.AllowStates : CallFlags.None; ExecutionContext context = engine.LoadScript(verification, callFlags, offset); if (NativeContract.IsNative(hashes[i])) { using ScriptBuilder sb = new ScriptBuilder(); sb.Emit(OpCode.DEPTH, OpCode.PACK); sb.EmitPush("verify"); engine.LoadScript(sb.ToArray(), CallFlags.None); } else if (init != null) { engine.LoadContext(context.Clone(init.Offset), false); } engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None); if (engine.Execute() == VMState.FAULT) { return(false); } if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) { return(false); } gas -= engine.GasConsumed; verifiable.Witnesses[i].GasConsumed = engine.GasConsumed; } } return(true); }