diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs index f5a2c5481..b373175ec 100644 --- a/src/RpcServer/RpcServer.SmartContract.cs +++ b/src/RpcServer/RpcServer.SmartContract.cs @@ -97,7 +97,21 @@ private static Signers SignersFromJson(JArray _params, ProtocolSettings settings Scopes = (WitnessScope)Enum.Parse(typeof(WitnessScope), u["scopes"]?.AsString()), AllowedContracts = ((JArray)u["allowedcontracts"])?.Select(p => UInt160.Parse(p.AsString())).ToArray(), AllowedGroups = ((JArray)u["allowedgroups"])?.Select(p => ECPoint.Parse(p.AsString(), ECCurve.Secp256r1)).ToArray() - }).ToArray()); + }).ToArray()) + { + Witnesses = _params + .Select(u => new + { + Invocation = u["invocation"]?.AsString(), + Verification = u["verification"]?.AsString() + }) + .Where(x => x.Invocation != null || x.Verification != null) + .Select(x => new Witness() + { + InvocationScript = Convert.FromBase64String(x.Invocation ?? string.Empty), + VerificationScript = Convert.FromBase64String(x.Verification ?? string.Empty) + }).ToArray() + }; // Validate format diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index e02df46d4..48ef8abe2 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -333,7 +333,6 @@ protected virtual JObject SendToAddress(JArray _params) [RpcMethod] protected virtual JObject InvokeContractVerify(JArray _params) { - CheckWallet(); UInt160 script_hash = UInt160.Parse(_params[0].AsString()); ContractParameter[] args = _params.Count >= 2 ? ((JArray)_params[1]).Select(p => ContractParameter.FromJson(p)).ToArray() : new ContractParameter[0]; Signers signers = _params.Count >= 3 ? SignersFromJson((JArray)_params[2], system.Settings) : null; @@ -348,22 +347,36 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar { throw new RpcException(-100, "Unknown contract"); } - var methodName = "verify"; + var md = contract.Manifest.Abi.GetMethod("verify", -1); + if (md is null) + throw new RpcException(-101, $"The smart contract {contract.Hash} haven't got verify method."); + if (md.ReturnType != ContractParameterType.Boolean) + throw new RpcException(-102, "The verify method doesn't return boolean value."); - Transaction tx = signers == null ? null : new Transaction + Transaction tx = new Transaction { - Signers = signers.GetSigners(), - Attributes = Array.Empty() + Signers = signers == null ? new Signer[] { new() { Account = scriptHash } } : signers.GetSigners(), + Attributes = Array.Empty(), + Witnesses = signers?.Witnesses, + Script = new[] { (byte)OpCode.RET } }; - ContractParametersContext context = new ContractParametersContext(snapshot, tx); - wallet.Sign(context); - tx.Witnesses = context.Completed ? context.GetWitnesses() : null; - using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: system.Settings); - engine.LoadScript(new ScriptBuilder().EmitDynamicCall(scriptHash, methodName, args).ToArray(), rvcount: 1); + engine.LoadContract(contract, md, CallFlags.ReadOnly); + var invocationScript = new byte[] { }; + if (args.Length > 0) + { + using ScriptBuilder sb = new ScriptBuilder(); + for (int i = args.Length - 1; i >= 0; i--) + sb.EmitPush(args[i]); + + invocationScript = sb.ToArray(); + tx.Witnesses ??= new Witness[] { new() { InvocationScript = invocationScript } }; + engine.LoadScript(new Script(invocationScript), configureState: p => p.CallFlags = CallFlags.None); + } JObject json = new JObject(); - json["script"] = Convert.ToBase64String(contract.Script); + + json["script"] = Convert.ToBase64String(invocationScript); json["state"] = engine.Execute(); json["gasconsumed"] = engine.GasConsumed.ToString(); json["exception"] = GetExceptionMessage(engine.FaultException);