diff --git a/src/Neo/Wallets/Helper.cs b/src/Neo/Wallets/Helper.cs
index 32638f6c6c..15a88890a4 100644
--- a/src/Neo/Wallets/Helper.cs
+++ b/src/Neo/Wallets/Helper.cs
@@ -9,9 +9,10 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.
+#nullable enable
+
using Neo.Cryptography;
using Neo.Extensions;
-using Neo.IO;
using Neo.Network.P2P;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
@@ -63,7 +64,7 @@ public static string ToAddress(this UInt160 scriptHash, byte version)
/// The converted script hash.
public static UInt160 ToScriptHash(this string address, byte version)
{
- byte[] data = address.Base58CheckDecode();
+ var data = address.Base58CheckDecode();
if (data.Length != 21)
throw new FormatException();
if (data[0] != version)
@@ -74,12 +75,28 @@ public static UInt160 ToScriptHash(this string address, byte version)
internal static byte[] XOR(byte[] x, byte[] y)
{
if (x.Length != y.Length) throw new ArgumentException();
- byte[] r = new byte[x.Length];
- for (int i = 0; i < r.Length; i++)
+ var r = new byte[x.Length];
+ for (var i = 0; i < r.Length; i++)
r[i] = (byte)(x[i] ^ y[i]);
return r;
}
+ ///
+ /// Calculates the network fee for the specified transaction.
+ /// In the unit of datoshi, 1 datoshi = 1e-8 GAS
+ ///
+ /// The transaction to calculate.
+ /// The snapshot used to read data.
+ /// Thr protocol settings to use.
+ /// User wallet.
+ /// The maximum cost that can be spent when a contract is executed.
+ /// The network fee of the transaction.
+ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, ProtocolSettings settings, Wallet? wallet = null, long maxExecutionCost = ApplicationEngine.TestModeGas)
+ {
+ Func? accountScript = wallet != null ? (scriptHash) => wallet.GetAccount(scriptHash)?.Contract?.Script : null;
+ return CalculateNetworkFee(tx, snapshot, settings, accountScript, maxExecutionCost);
+ }
+
///
/// Calculates the network fee for the specified transaction.
/// In the unit of datoshi, 1 datoshi = 1e-8 GAS
@@ -90,24 +107,24 @@ internal static byte[] XOR(byte[] x, byte[] y)
/// Function to retrive the script's account from a hash.
/// The maximum cost that can be spent when a contract is executed.
/// The network fee of the transaction.
- public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, ProtocolSettings settings, Func accountScript, long maxExecutionCost = ApplicationEngine.TestModeGas)
+ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot, ProtocolSettings settings, Func? accountScript, long maxExecutionCost = ApplicationEngine.TestModeGas)
{
- UInt160[] hashes = tx.GetScriptHashesForVerifying(snapshot);
+ var hashes = tx.GetScriptHashesForVerifying(snapshot);
// base size for transaction: includes const_header + signers + attributes + script + hashes
int size = Transaction.HeaderSize + tx.Signers.GetVarSize() + tx.Attributes.GetVarSize() + tx.Script.GetVarSize() + UnsafeData.GetVarSize(hashes.Length), index = -1;
- uint exec_fee_factor = NativeContract.Policy.GetExecFeeFactor(snapshot);
+ var exec_fee_factor = NativeContract.Policy.GetExecFeeFactor(snapshot);
long networkFee = 0;
- foreach (UInt160 hash in hashes)
+ foreach (var hash in hashes)
{
index++;
- byte[] witnessScript = accountScript(hash);
- byte[] invocationScript = null;
+ var witnessScript = accountScript != null ? accountScript(hash) : null;
+ byte[]? invocationScript = null;
if (tx.Witnesses != null && witnessScript is null)
{
// Try to find the script in the witnesses
- Witness witness = tx.Witnesses[index];
+ var witness = tx.Witnesses[index];
witnessScript = witness?.VerificationScript.ToArray();
if (witnessScript is null || witnessScript.Length == 0)
@@ -193,14 +210,14 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot,
}
else if (IsMultiSigContract(witnessScript, out int m, out int n))
{
- int size_inv = 66 * m;
+ var size_inv = 66 * m;
size += UnsafeData.GetVarSize(size_inv) + size_inv + witnessScript.GetVarSize();
networkFee += exec_fee_factor * MultiSignatureContractCost(m, n);
}
}
}
networkFee += size * NativeContract.Policy.GetFeePerByte(snapshot);
- foreach (TransactionAttribute attr in tx.Attributes)
+ foreach (var attr in tx.Attributes)
{
networkFee += attr.CalculateNetworkFee(snapshot, tx);
}
diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs
index 40254f1b4e..e73e8a09e9 100644
--- a/src/Neo/Wallets/Wallet.cs
+++ b/src/Neo/Wallets/Wallet.cs
@@ -584,7 +584,7 @@ private Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory scr
tx.SystemFee = engine.FeeConsumed;
}
- tx.NetworkFee = tx.CalculateNetworkFee(snapshot, ProtocolSettings, (a) => GetAccount(a)?.Contract?.Script, maxGas);
+ tx.NetworkFee = tx.CalculateNetworkFee(snapshot, ProtocolSettings, this, maxGas);
if (value >= tx.SystemFee + tx.NetworkFee) return tx;
}
throw new InvalidOperationException("Insufficient GAS");
diff --git a/src/Plugins/RpcServer/RpcServer.Wallet.cs b/src/Plugins/RpcServer/RpcServer.Wallet.cs
index 56232e765c..086bb3c9d5 100644
--- a/src/Plugins/RpcServer/RpcServer.Wallet.cs
+++ b/src/Plugins/RpcServer/RpcServer.Wallet.cs
@@ -177,9 +177,7 @@ protected internal virtual JToken CalculateNetworkFee(JArray _params)
var tx = Result.Ok_Or(() => Convert.FromBase64String(_params[0].AsString()), RpcError.InvalidParams.WithData($"Invalid tx: {_params[0]}")); ;
JObject account = new();
- var networkfee = Wallets.Helper.CalculateNetworkFee(
- tx.AsSerializable(), system.StoreView, system.Settings,
- wallet is not null ? a => wallet.GetAccount(a).Contract.Script : _ => null);
+ var networkfee = Wallets.Helper.CalculateNetworkFee(tx.AsSerializable(), system.StoreView, system.Settings, wallet);
account["networkfee"] = networkfee.ToString();
return account;
}