From 099f7be04f0e6165391f47a183492ed29318d91b Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 2 Jul 2024 10:40:04 +0200 Subject: [PATCH 01/10] Calculate fee --- src/Neo/Wallets/Helper.cs | 71 ++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index 1273bafc50..c52e9df5f9 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -10,6 +10,7 @@ // modifications are permitted. using Neo.Cryptography; +using Neo.Cryptography.ECC; using Neo.IO; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; @@ -117,6 +118,7 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, if (witnessScript is null || witnessScript.Length == 0) { + // Contract-based verification var contract = NativeContract.ContractManagement.GetContract(snapshot, hash); if (contract is null) throw new ArgumentException($"The smart contract or address {hash} is not found"); @@ -126,7 +128,46 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, if (md.ReturnType != ContractParameterType.Boolean) throw new ArgumentException("The verify method doesn't return boolean value."); if (md.Parameters.Length > 0 && invocationScript is null) - throw new ArgumentException("The verify method requires parameters that need to be passed via the witness' invocation script."); + { + var script = new ScriptBuilder(); + foreach (var par in md.Parameters) + { + switch (par.Type) + { + case ContractParameterType.Any: + case ContractParameterType.Signature: + case ContractParameterType.String: + case ContractParameterType.ByteArray: + script.EmitPush(new byte[64]); + break; + case ContractParameterType.Boolean: + script.EmitPush(true); + break; + case ContractParameterType.Integer: + script.Emit(OpCode.PUSHINT256, new byte[32]); + break; + case ContractParameterType.Hash160: + script.EmitPush(new byte[UInt160.Length]); + break; + case ContractParameterType.Hash256: + script.EmitPush(new byte[UInt256.Length]); + break; + case ContractParameterType.PublicKey: + script.EmitPush(new byte[ECCurve.Secp256r1.ExpectedECPointLength]); + break; + case ContractParameterType.Array: + script.Emit(OpCode.PUSHINT256, new byte[32]); + script.Emit(OpCode.NEWARRAY); + break; + case ContractParameterType.Map: + script.Emit(OpCode.NEWMAP); + break; + default: + throw new ArgumentException("The verify method requires parameters that need to be passed via the witness' invocation script."); + } + } + invocationScript = script.ToArray(); + } // Empty verification and non-empty invocation scripts var invSize = invocationScript?.GetVarSize() ?? Array.Empty().GetVarSize(); @@ -136,25 +177,29 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: settings, gas: maxExecutionCost); engine.LoadContract(contract, md, CallFlags.ReadOnly); if (invocationScript != null) engine.LoadScript(invocationScript, configureState: p => p.CallFlags = CallFlags.None); - if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.Hash} verification fault."); - if (!engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.Hash} returns false."); + _ = engine.Execute(); // https://github.com/neo-project/neo/issues/2805 + //if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.Hash} verification fault."); + //if (!engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.Hash} returns false."); maxExecutionCost -= engine.FeeConsumed; if (maxExecutionCost <= 0) throw new InvalidOperationException("Insufficient GAS."); networkFee += engine.FeeConsumed; } - else if (IsSignatureContract(witnessScript)) - { - size += 67 + witnessScript.GetVarSize(); - networkFee += exec_fee_factor * SignatureContractCost(); - } - else if (IsMultiSigContract(witnessScript, out int m, out int n)) + else { - int size_inv = 66 * m; - size += IO.Helper.GetVarSize(size_inv) + size_inv + witnessScript.GetVarSize(); - networkFee += exec_fee_factor * MultiSignatureContractCost(m, n); + // Regular signature verification. + if (IsSignatureContract(witnessScript)) + { + size += 67 + witnessScript.GetVarSize(); + networkFee += exec_fee_factor * SignatureContractCost(); + } + else if (IsMultiSigContract(witnessScript, out int m, out int n)) + { + int size_inv = 66 * m; + size += IO.Helper.GetVarSize(size_inv) + size_inv + witnessScript.GetVarSize(); + networkFee += exec_fee_factor * MultiSignatureContractCost(m, n); + } } - // We can support more contract types in the future. } networkFee += size * NativeContract.Policy.GetFeePerByte(snapshot); foreach (TransactionAttribute attr in tx.Attributes) From 3a332fadf9857d7a29db0d31d2d25252ff093f1a Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 2 Jul 2024 10:46:53 +0200 Subject: [PATCH 02/10] change values --- src/Neo/Wallets/Helper.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index c52e9df5f9..5570bd0066 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -18,6 +18,7 @@ using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; +using Neo.VM.Types; using System; using static Neo.SmartContract.Helper; @@ -144,7 +145,7 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, script.EmitPush(true); break; case ContractParameterType.Integer: - script.Emit(OpCode.PUSHINT256, new byte[32]); + script.Emit(OpCode.PUSHINT256, new byte[Integer.MaxSize]); break; case ContractParameterType.Hash160: script.EmitPush(new byte[UInt160.Length]); @@ -153,10 +154,10 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, script.EmitPush(new byte[UInt256.Length]); break; case ContractParameterType.PublicKey: - script.EmitPush(new byte[ECCurve.Secp256r1.ExpectedECPointLength]); + script.EmitPush(new byte[33]); break; case ContractParameterType.Array: - script.Emit(OpCode.PUSHINT256, new byte[32]); + script.Emit(OpCode.PUSHINT256, new byte[Integer.MaxSize]); script.Emit(OpCode.NEWARRAY); break; case ContractParameterType.Map: From ad3d477fd3e9ba31bf5dd5daa557ba931409b93f Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 2 Jul 2024 10:47:10 +0200 Subject: [PATCH 03/10] remove using --- src/Neo/Wallets/Helper.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index 5570bd0066..f9a6072b8c 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -10,7 +10,6 @@ // modifications are permitted. using Neo.Cryptography; -using Neo.Cryptography.ECC; using Neo.IO; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; From 7b6ccb9869e62e7e196cc043464ea881973a7404 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 2 Jul 2024 10:50:00 +0200 Subject: [PATCH 04/10] fix using --- src/Neo/Wallets/Helper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index f9a6072b8c..4d56c345b4 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -170,8 +170,8 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, } // Empty verification and non-empty invocation scripts - var invSize = invocationScript?.GetVarSize() ?? Array.Empty().GetVarSize(); - size += Array.Empty().GetVarSize() + invSize; + var invSize = invocationScript?.GetVarSize() ?? System.Array.Empty().GetVarSize(); + size += System.Array.Empty().GetVarSize() + invSize; // Check verify cost using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: settings, gas: maxExecutionCost); From 78ddbb199c159485dbc17bcaf1ae5896d80f09d2 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 2 Jul 2024 10:58:46 +0200 Subject: [PATCH 05/10] Remove comments --- src/Neo/Wallets/Helper.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index 4d56c345b4..202d669384 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -178,8 +178,6 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, engine.LoadContract(contract, md, CallFlags.ReadOnly); if (invocationScript != null) engine.LoadScript(invocationScript, configureState: p => p.CallFlags = CallFlags.None); _ = engine.Execute(); // https://github.com/neo-project/neo/issues/2805 - //if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.Hash} verification fault."); - //if (!engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.Hash} returns false."); maxExecutionCost -= engine.FeeConsumed; if (maxExecutionCost <= 0) throw new InvalidOperationException("Insufficient GAS."); From 8a8af47780f0811266b04e1107b4fa945dcd6049 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 5 Jul 2024 08:56:54 +0200 Subject: [PATCH 06/10] Remove map --- src/Neo/Wallets/Helper.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index 202d669384..45f8487198 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -159,9 +159,6 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, script.Emit(OpCode.PUSHINT256, new byte[Integer.MaxSize]); script.Emit(OpCode.NEWARRAY); break; - case ContractParameterType.Map: - script.Emit(OpCode.NEWMAP); - break; default: throw new ArgumentException("The verify method requires parameters that need to be passed via the witness' invocation script."); } From 58cab0d8223ae3c711b0c0776e5867cea36e89aa Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 11 Jul 2024 10:43:43 +0200 Subject: [PATCH 07/10] Anna's feedback --- src/Neo/Wallets/Helper.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index 45f8487198..72f8d6f54c 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -174,8 +174,11 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: settings, gas: maxExecutionCost); engine.LoadContract(contract, md, CallFlags.ReadOnly); if (invocationScript != null) engine.LoadScript(invocationScript, configureState: p => p.CallFlags = CallFlags.None); - _ = engine.Execute(); // https://github.com/neo-project/neo/issues/2805 - + if (engine.Execute() == VMState.HALT) + { + // https://github.com/neo-project/neo/issues/2805 + _ = engine.ResultStack.Pop().GetBoolean(); // Ensure that the result is boolean + } maxExecutionCost -= engine.FeeConsumed; if (maxExecutionCost <= 0) throw new InvalidOperationException("Insufficient GAS."); networkFee += engine.FeeConsumed; From e2cc49f69158123aeb238da14e2af4fc9416908d Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 11 Jul 2024 10:44:59 +0200 Subject: [PATCH 08/10] ensure only one result --- src/Neo/Wallets/Helper.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index 72f8d6f54c..b12437dc01 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -177,6 +177,7 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, if (engine.Execute() == VMState.HALT) { // https://github.com/neo-project/neo/issues/2805 + if (engine.ResultStack.Count != 1) throw new ArgumentException($"Smart contract {contract.Hash} verification fault."); _ = engine.ResultStack.Pop().GetBoolean(); // Ensure that the result is boolean } maxExecutionCost -= engine.FeeConsumed; From 3812a4518069574677acbbc2dc3c1ebeecf14c22 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 30 Jul 2024 01:23:23 -0700 Subject: [PATCH 09/10] Update src/Neo/Wallets/Helper.cs --- src/Neo/Wallets/Helper.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index a188115d04..9af78e256a 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -156,8 +156,7 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, script.EmitPush(new byte[33]); break; case ContractParameterType.Array: - script.Emit(OpCode.PUSHINT256, new byte[Integer.MaxSize]); - script.Emit(OpCode.NEWARRAY); + script.Emit(OpCode.NEWARRAY0); break; default: throw new ArgumentException("The verify method requires parameters that need to be passed via the witness' invocation script."); From 8ad1acf14af306efeb9fcc493cc2892667a336af Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 31 Jul 2024 01:24:15 -0700 Subject: [PATCH 10/10] Remove error --- src/Neo/Wallets/Helper.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs index 9af78e256a..8d8d5d9361 100644 --- a/src/Neo/Wallets/Helper.cs +++ b/src/Neo/Wallets/Helper.cs @@ -158,8 +158,6 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, case ContractParameterType.Array: script.Emit(OpCode.NEWARRAY0); break; - default: - throw new ArgumentException("The verify method requires parameters that need to be passed via the witness' invocation script."); } } invocationScript = script.ToArray();