From 2d467f1285f470f0f8552952a158026e34df98b8 Mon Sep 17 00:00:00 2001 From: Shuai Date: Tue, 16 Mar 2021 16:38:44 +0800 Subject: [PATCH 1/9] fix verify api --- src/RpcServer/RpcServer.Wallet.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index 7c75e628f..c5880e360 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,20 +347,20 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar { throw new RpcException(-100, "Unknown contract"); } - var methodName = "verify"; + var md = contract.Manifest.Abi.GetMethod("verify", 0); + if (md is null) + throw new RpcException(-101, $"The smart contract {contract.Hash} haven't got verify method without arguments"); + if (md.ReturnType != ContractParameterType.Boolean) + throw new RpcException(-102, "The verify method doesn't return boolean value."); Transaction tx = signers == null ? null : new Transaction { Signers = signers.GetSigners(), - Attributes = Array.Empty() + Attributes = Array.Empty(), + Witnesses = signers.Witnesses, }; - 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); JObject json = new JObject(); json["script"] = Convert.ToBase64String(contract.Script); json["state"] = engine.Execute(); From 331e24a8fbc03a3d996e726736455ca1156e8ef6 Mon Sep 17 00:00:00 2001 From: Shuai Date: Tue, 16 Mar 2021 18:18:29 +0800 Subject: [PATCH 2/9] refac --- src/RpcServer/RpcServer.Wallet.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index c5880e360..93c6f4882 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -347,7 +347,7 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar { throw new RpcException(-100, "Unknown contract"); } - var md = contract.Manifest.Abi.GetMethod("verify", 0); + 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 without arguments"); if (md.ReturnType != ContractParameterType.Boolean) @@ -357,10 +357,13 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar { Signers = signers.GetSigners(), Attributes = Array.Empty(), - Witnesses = signers.Witnesses, }; using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: system.Settings); engine.LoadContract(contract, md, CallFlags.ReadOnly); + if (args.Length > 0 && args[0].Value is byte[] invocation) + { + engine.LoadScript(new Script(invocation), configureState: p => p.CallFlags = CallFlags.None); + } JObject json = new JObject(); json["script"] = Convert.ToBase64String(contract.Script); json["state"] = engine.Execute(); From 647f56b8057cde64224694f3805f33b9cc0f4ffe Mon Sep 17 00:00:00 2001 From: Shuai Date: Wed, 17 Mar 2021 11:48:18 +0800 Subject: [PATCH 3/9] default signer & parameter --- src/RpcServer/RpcServer.Wallet.cs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index a674c0776..7367f424e 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -349,20 +349,30 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar } 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 without arguments"); + 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 + var defaultSigner = new List() { new() { Account = scriptHash } }; + if (signers != null) { - Signers = signers.GetSigners(), + defaultSigner.AddRange(signers.GetSigners()); + } + Transaction tx = new Transaction + { + Signers = defaultSigner.ToArray(), Attributes = Array.Empty(), + Script = new[] { (byte)OpCode.RET } }; using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: system.Settings); engine.LoadContract(contract, md, CallFlags.ReadOnly); - if (args.Length > 0 && args[0].Value is byte[] invocation) + if (args.Length > 0) { - engine.LoadScript(new Script(invocation), configureState: p => p.CallFlags = CallFlags.None); + using ScriptBuilder sb = new ScriptBuilder(); + for (int i = args.Length - 1; i >= 0; i--) + sb.EmitPush(args[i]); + + engine.LoadScript(new Script(sb.ToArray()), configureState: p => p.CallFlags = CallFlags.None); } JObject json = new JObject(); json["script"] = Convert.ToBase64String(contract.Script); From 108b15e2d4cbe141563411d7fbcfa848ff608ea6 Mon Sep 17 00:00:00 2001 From: Shuai Date: Wed, 17 Mar 2021 15:46:45 +0800 Subject: [PATCH 4/9] refac --- src/RpcServer/RpcServer.Wallet.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index 7367f424e..5af9641ea 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -353,14 +353,9 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar if (md.ReturnType != ContractParameterType.Boolean) throw new RpcException(-102, "The verify method doesn't return boolean value."); - var defaultSigner = new List() { new() { Account = scriptHash } }; - if (signers != null) - { - defaultSigner.AddRange(signers.GetSigners()); - } Transaction tx = new Transaction { - Signers = defaultSigner.ToArray(), + Signers = signers == null ? new Signer[] { new() { Account = scriptHash } } : signers.GetSigners(), Attributes = Array.Empty(), Script = new[] { (byte)OpCode.RET } }; From bf5034ca36a552668939cdab7e84208e4202e19c Mon Sep 17 00:00:00 2001 From: Shuai Date: Wed, 17 Mar 2021 16:30:07 +0800 Subject: [PATCH 5/9] add Witness --- src/RpcServer/RpcServer.SmartContract.cs | 15 ++++++++++++++- src/RpcServer/RpcServer.Wallet.cs | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs index f5a2c5481..37804f3af 100644 --- a/src/RpcServer/RpcServer.SmartContract.cs +++ b/src/RpcServer/RpcServer.SmartContract.cs @@ -97,7 +97,20 @@ 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), + VerificationScript = Convert.FromBase64String(x.Verification) + }).ToArray() + }; // Validate format diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index 5af9641ea..6b030641a 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -357,6 +357,7 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar { Signers = signers == null ? new Signer[] { new() { Account = scriptHash } } : signers.GetSigners(), Attributes = Array.Empty(), + Witnesses = signers?.Witnesses, Script = new[] { (byte)OpCode.RET } }; using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: system.Settings); From b79c6de4a31b6596d99cde61f5fd00e546b68953 Mon Sep 17 00:00:00 2001 From: Shuai Date: Wed, 17 Mar 2021 16:32:30 +0800 Subject: [PATCH 6/9] format --- src/RpcServer/RpcServer.SmartContract.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs index 37804f3af..4da2906d4 100644 --- a/src/RpcServer/RpcServer.SmartContract.cs +++ b/src/RpcServer/RpcServer.SmartContract.cs @@ -99,7 +99,8 @@ private static Signers SignersFromJson(JArray _params, ProtocolSettings settings AllowedGroups = ((JArray)u["allowedgroups"])?.Select(p => ECPoint.Parse(p.AsString(), ECCurve.Secp256r1)).ToArray() }).ToArray()) { - Witnesses = _params.Select(u => new + Witnesses = _params + .Select(u => new { Invocation = u["invocation"]?.AsString(), Verification = u["verification"]?.AsString() From 9f899799ed11983e2ee18e1582fd6dcb7efdf548 Mon Sep 17 00:00:00 2001 From: Shuai Date: Wed, 17 Mar 2021 17:08:26 +0800 Subject: [PATCH 7/9] update --- src/RpcServer/RpcServer.SmartContract.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs index 4da2906d4..b373175ec 100644 --- a/src/RpcServer/RpcServer.SmartContract.cs +++ b/src/RpcServer/RpcServer.SmartContract.cs @@ -105,11 +105,11 @@ private static Signers SignersFromJson(JArray _params, ProtocolSettings settings Invocation = u["invocation"]?.AsString(), Verification = u["verification"]?.AsString() }) - .Where(x => x.Invocation != null && x.Verification != null) + .Where(x => x.Invocation != null || x.Verification != null) .Select(x => new Witness() { - InvocationScript = Convert.FromBase64String(x.Invocation), - VerificationScript = Convert.FromBase64String(x.Verification) + InvocationScript = Convert.FromBase64String(x.Invocation ?? string.Empty), + VerificationScript = Convert.FromBase64String(x.Verification ?? string.Empty) }).ToArray() }; From 1d4b121a4295e9ae5b328a70fcafce80d87b9176 Mon Sep 17 00:00:00 2001 From: Shuai Date: Wed, 17 Mar 2021 17:39:20 +0800 Subject: [PATCH 8/9] update --- src/RpcServer/RpcServer.Wallet.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index 6b030641a..bec760c33 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -368,6 +368,7 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar for (int i = args.Length - 1; i >= 0; i--) sb.EmitPush(args[i]); + tx.Witnesses ??= new Witness[] {new() {InvocationScript = sb.ToArray()}}; engine.LoadScript(new Script(sb.ToArray()), configureState: p => p.CallFlags = CallFlags.None); } JObject json = new JObject(); From 1043c8f8c2f1b60aac663555ac0dda6b4ebcadd9 Mon Sep 17 00:00:00 2001 From: Shuai Date: Wed, 17 Mar 2021 18:24:14 +0800 Subject: [PATCH 9/9] update --- src/RpcServer/RpcServer.Wallet.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index bec760c33..48ef8abe2 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -362,17 +362,21 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar }; using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: system.Settings); 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]); - tx.Witnesses ??= new Witness[] {new() {InvocationScript = sb.ToArray()}}; - engine.LoadScript(new Script(sb.ToArray()), configureState: p => p.CallFlags = CallFlags.None); + 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);