internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas) { 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++) { 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 (hashes[i] != verifiable.Witnesses[i].ScriptHash) { return(false); } offset = 0; } using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot.Clone(), gas)) { engine.LoadScript(verification, CallFlags.None).InstructionPointer = offset; if (init != null) { engine.LoadClonedContext(init.Offset); } 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; } } return(true); }