private async ContractTask OnDeploy(ApplicationEngine engine, ContractState contract, StackItem data, bool update)
 {
     ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2);
     if (md is not null)
         await engine.CallFromNativeContract(Hash, contract.Hash, md.Name, data, update);
     engine.SendNotification(Hash, update ? "Update" : "Deploy", new VM.Types.Array { contract.Hash.ToArray() });
 }
Example #2
0
        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);
        }
Example #3
0
        private void CallContractInternal(ContractState contract, ContractMethodDescriptor method, CallFlags flags, bool hasReturnValue, StackItem[] args)
        {
            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.Length != method.Parameters.Length)
            {
                throw new InvalidOperationException($"Method {method.Name} Expects {method.Parameters.Length} Arguments But Receives {args.Length} Arguments");
            }
            ExecutionContext context_new = LoadContract(contract, method.Name, flags & callingFlags, hasReturnValue, (ushort)args.Length);

            state = context_new.GetState <ExecutionContextState>();
            state.CallingScriptHash = callingScriptHash;

            for (int i = args.Length - 1; i >= 0; i--)
            {
                context_new.EvaluationStack.Push(args[i]);
            }
            if (NativeContract.IsNative(contract.Hash))
            {
                context_new.EvaluationStack.Push(method.Name);
            }
        }
Example #4
0
 public ContractMethodModel(ContractMethodDescriptor method) : base(method)
 {
     if (method != null)
     {
         ReturnType = method.ReturnType;
     }
 }
Example #5
0
        public ExecutionContext LoadContract(ContractState contract, string method, CallFlags callFlags, bool packParameters = false)
        {
            ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method);

            if (md is null)
            {
                return(null);
            }

            ExecutionContext context = LoadScript(contract.Script, callFlags, contract.Hash, md.Offset);

            if (NativeContract.IsNative(contract.Hash))
            {
                if (packParameters)
                {
                    using ScriptBuilder sb = new ScriptBuilder();
                    sb.Emit(OpCode.DEPTH, OpCode.PACK);
                    sb.EmitPush(md.Name);
                    LoadScript(sb.ToArray(), CallFlags.None);
                }
            }
            else
            {
                // Call initialization

                var init = contract.Manifest.Abi.GetMethod("_initialize");

                if (init != null)
                {
                    LoadContext(context.Clone(init.Offset), false);
                }
            }

            return(context);
        }
Example #6
0
        private void 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);

            if (md is null)
            {
                throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}");
            }

            if (md.Safe)
            {
                flags &= ~CallFlags.WriteStates;
            }
            else
            {
                ContractState currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash);
                if (currentContract?.CanCall(contract, method) == false)
                {
                    throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contractHash} From Contract {CurrentScriptHash}");
                }
            }

            CallContractInternal(contract, md, flags, hasReturnValue, args);
        }
Example #7
0
        private void CallContractInternal(UInt160 contractHash, string method, Array args, CallFlags flags, ReturnTypeConvention convention)
        {
            if (method.StartsWith('_'))
            {
                throw new ArgumentException($"Invalid Method Name: {method}");
            }

            ContractState contract = NativeContract.Management.GetContract(Snapshot, contractHash);

            if (contract is null)
            {
                throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}");
            }
            ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method);

            if (md is null)
            {
                throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}");
            }

            if (md.Safe)
            {
                flags &= ~CallFlags.WriteStates;
            }
            else
            {
                ContractState currentContract = NativeContract.Management.GetContract(Snapshot, CurrentScriptHash);
                if (currentContract?.CanCall(contract, method) == false)
                {
                    throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contractHash} From Contract {CurrentScriptHash}");
                }
            }

            CallContractInternal(contract, md, args, flags, convention);
        }
Example #8
0
        public ExecutionContext LoadContract(ContractState contract, string method, CallFlags callFlags, bool hasReturnValue, ushort pcount)
        {
            ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method);

            if (md is null)
            {
                return(null);
            }

            ExecutionContext context = LoadScript(contract.Script,
                                                  pcount: pcount,
                                                  rvcount: hasReturnValue ? 1 : 0,
                                                  initialPosition: md.Offset,
                                                  configureState: p =>
            {
                p.CallFlags  = callFlags;
                p.ScriptHash = contract.Hash;
            });

            // Call initialization
            var init = contract.Manifest.Abi.GetMethod("_initialize");

            if (init != null)
            {
                LoadContext(context.Clone(init.Offset));
            }

            return(context);
        }
Example #9
0
        protected internal void CallContract(UInt160 contractHash, string method, CallFlags callFlags, Array args)
        {
            if (method.StartsWith('_'))
            {
                throw new ArgumentException($"Invalid Method Name: {method}");
            }
            if ((callFlags & ~CallFlags.All) != 0)
            {
                throw new ArgumentOutOfRangeException(nameof(callFlags));
            }

            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.Count);

            if (md is null)
            {
                throw new InvalidOperationException($"Method \"{method}\" with {args.Count} parameter(s) doesn't exist in the contract {contractHash}.");
            }
            bool hasReturnValue = md.ReturnType != ContractParameterType.Void;

            if (!hasReturnValue)
            {
                CurrentContext.EvaluationStack.Push(StackItem.Null);
            }
            CallContractInternal(contract, md, callFlags, hasReturnValue, args);
        }
Example #10
0
        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()
            });
        }
Example #11
0
 public ContractMethodModel(ContractMethodDescriptor method) : base(method)
 {
     if (method != null)
     {
         Offset     = method.Offset;
         Safe       = method.Safe;
         ReturnType = method.ReturnType;
     }
 }
Example #12
0
        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]);
            }
            if (NativeContract.IsNative(contract.Hash))
            {
                context_new.EvaluationStack.Push(method.Name);
            }

            return(context_new);
        }
Example #13
0
        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);
        }
Example #14
0
        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);
                }
            }
        }
        private bool _loadContract(UInt160 hash, string method, int pcount, CallFlags flags)
        {
            this.isEngineInitialized();
            ContractState cs = NativeContract.ContractManagement.GetContract(this.snapshot, hash);

            if (cs is null)
            {
                return(false);
            }
            ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod(method, pcount);

            this.engine.LoadContract(cs, md, flags);

            return(true);
        }
Example #16
0
        public MethodCallback(ApplicationEngine engine, UInt160 hash, string method)
            : base(ApplicationEngine.System_Contract_Call, false)
        {
            if (method.StartsWith('_'))
            {
                throw new ArgumentException();
            }
            this.contract = NativeContract.Management.GetContract(engine.Snapshot, hash);
            ContractState currentContract = NativeContract.Management.GetContract(engine.Snapshot, engine.CurrentScriptHash);

            if (currentContract?.CanCall(this.contract, method) == false)
            {
                throw new InvalidOperationException();
            }
            this.method = this.contract.Manifest.Abi.Methods.First(p => p.Name == method);
        }
Example #17
0
        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));
        }
Example #18
0
        public MethodCallback(ApplicationEngine engine, UInt160 hash, string method)
            : base(ApplicationEngine.System_Contract_Call, false)
        {
            if (method.StartsWith('_'))
            {
                throw new ArgumentException();
            }
            this.contract = engine.Snapshot.Contracts[hash];
            ContractManifest currentManifest = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash)?.Manifest;

            if (currentManifest != null && !currentManifest.CanCall(this.contract.Manifest, method))
            {
                throw new InvalidOperationException();
            }
            this.method = this.contract.Manifest.Abi.Methods.First(p => p.Name == method);
        }
Example #19
0
        /// <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();
        }
Example #20
0
        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);
        }
Example #21
0
        // Copied from OracleService.CreateResponseTx to avoid taking dependency on OracleService package and it's 110mb GRPC runtime
        public static Transaction?CreateResponseTx(DataCache snapshot, OracleRequest request, OracleResponse response, IReadOnlyList <ECPoint> oracleNodes, ProtocolSettings settings)
        {
            if (oracleNodes.Count == 0)
            {
                throw new Exception("No oracle nodes available. Have you enabled oracles via the `oracle enable` command?");
            }

            var requestTx          = NativeContract.Ledger.GetTransactionState(snapshot, request.OriginalTxid);
            var n                  = oracleNodes.Count;
            var m                  = n - (n - 1) / 3;
            var oracleSignContract = Contract.CreateMultiSigContract(m, oracleNodes);

            var tx = new Transaction()
            {
                Version         = 0,
                Nonce           = unchecked ((uint)response.Id),
                ValidUntilBlock = requestTx.BlockIndex + settings.MaxValidUntilBlockIncrement,
                Signers         = new[]
                {
                    new Signer
                    {
                        Account = NativeContract.Oracle.Hash,
                        Scopes  = WitnessScope.None
                    },
                    new Signer
                    {
                        Account = oracleSignContract.ScriptHash,
                        Scopes  = WitnessScope.None
                    }
                },
                Attributes = new[] { response },
                Script     = OracleResponse.FixedScript,
                Witnesses  = new Witness[2]
            };
            Dictionary <UInt160, Witness> witnessDict = new Dictionary <UInt160, Witness>
            {
                [oracleSignContract.ScriptHash] = new Witness
                {
                    InvocationScript   = Array.Empty <byte>(),
                    VerificationScript = oracleSignContract.Script,
                },
                [NativeContract.Oracle.Hash] = new Witness
                {
                    InvocationScript   = Array.Empty <byte>(),
                    VerificationScript = Array.Empty <byte>(),
                }
            };

            UInt160[] hashes = tx.GetScriptHashesForVerifying(snapshot);
            tx.Witnesses[0] = witnessDict[hashes[0]];
            tx.Witnesses[1] = witnessDict[hashes[1]];

            // Calculate network fee

            var oracleContract          = NativeContract.ContractManagement.GetContract(snapshot, NativeContract.Oracle.Hash);
            var engine                  = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: settings);
            ContractMethodDescriptor md = oracleContract.Manifest.Abi.GetMethod("verify", -1);

            engine.LoadContract(oracleContract, md, CallFlags.None);
            if (engine.Execute() != Neo.VM.VMState.HALT)
            {
                return(null);
            }
            tx.NetworkFee += engine.GasConsumed;

            var executionFactor = NativeContract.Policy.GetExecFeeFactor(snapshot);
            var networkFee      = executionFactor * Neo.SmartContract.Helper.MultiSignatureContractCost(m, n);

            tx.NetworkFee += networkFee;

            // Base size for transaction: includes const_header + signers + script + hashes + witnesses, except attributes

            int size_inv = 66 * m;
            int size     = Transaction.HeaderSize + tx.Signers.GetVarSize() + tx.Script.GetVarSize()
                           + Neo.IO.Helper.GetVarSize(hashes.Length) + witnessDict[NativeContract.Oracle.Hash].Size
                           + Neo.IO.Helper.GetVarSize(size_inv) + size_inv + oracleSignContract.Script.GetVarSize();

            var feePerByte = NativeContract.Policy.GetFeePerByte(snapshot);

            if (response.Result.Length > OracleResponse.MaxResultSize)
            {
                response.Code   = OracleResponseCode.ResponseTooLarge;
                response.Result = Array.Empty <byte>();
            }
            else if (tx.NetworkFee + (size + tx.Attributes.GetVarSize()) * feePerByte > request.GasForResponse)
            {
                response.Code   = OracleResponseCode.InsufficientFunds;
                response.Result = Array.Empty <byte>();
            }
            size          += tx.Attributes.GetVarSize();
            tx.NetworkFee += size * feePerByte;

            // Calculate system fee

            tx.SystemFee = request.GasForResponse - tx.NetworkFee;

            return(tx);
        }
Example #22
0
        internal static bool VerifyWitness(this IVerifiable verifiable, DataCache snapshot, UInt160 hash, Witness witness, long gas, out long fee)
        {
            fee = 0;
            using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), 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);
                    }
                    ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1);
                    if (md?.ReturnType != ContractParameterType.Boolean)
                    {
                        return(false);
                    }
                    engine.LoadContract(cs, md, callFlags);
                }
                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);
        }
Example #23
0
        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);
        }
Example #24
0
        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);
        }
Example #25
0
        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);
        }