Skip to content

Commit

Permalink
Optimize opcode price charging (#3131)
Browse files Browse the repository at this point in the history
* Optimize price

* Jimmy's review

* CS0618

* Update tests/Neo.UnitTests/SmartContract/UT_OpCodePrices.cs

* Avoid Obsolete

---------

Co-authored-by: Jimmy <[email protected]>
  • Loading branch information
shargon and Jim8y authored Feb 14, 2024
1 parent 25ed6d6 commit 4940501
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 10 deletions.
17 changes: 17 additions & 0 deletions src/Neo/SmartContract/ApplicationEngine.OpCodePrices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// modifications are permitted.

using Neo.VM;
using System;
using System.Collections.Generic;

namespace Neo.SmartContract
Expand All @@ -19,6 +20,7 @@ partial class ApplicationEngine
/// <summary>
/// The prices of all the opcodes.
/// </summary>
[Obsolete("You should use OpCodePriceTable")]
public static readonly IReadOnlyDictionary<OpCode, long> OpCodePrices = new Dictionary<OpCode, long>
{
[OpCode.PUSHINT8] = 1 << 0,
Expand Down Expand Up @@ -218,5 +220,20 @@ partial class ApplicationEngine
[OpCode.ISTYPE] = 1 << 1,
[OpCode.CONVERT] = 1 << 13,
};

public static readonly long[] OpCodePriceTable = new long[byte.MaxValue];

/// <summary>
/// Init OpCodePrices
/// </summary>
static ApplicationEngine()
{
#pragma warning disable CS0618 // Type or member is obsolete
foreach (var entry in OpCodePrices)
#pragma warning restore CS0618 // Type or member is obsolete
{
OpCodePriceTable[(byte)entry.Key] = entry.Value;
}
}
}
}
2 changes: 1 addition & 1 deletion src/Neo/SmartContract/ApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ protected virtual void OnSysCall(InteropDescriptor descriptor)
protected override void PreExecuteInstruction(Instruction instruction)
{
Diagnostic?.PreExecuteInstruction(instruction);
AddGas(ExecFeeFactor * OpCodePrices[instruction.OpCode]);
AddGas(ExecFeeFactor * OpCodePriceTable[(byte)instruction.OpCode]);
}

protected override void PostExecuteInstruction(Instruction instruction)
Expand Down
12 changes: 6 additions & 6 deletions src/Neo/SmartContract/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public static class Helper
/// </summary>
/// <returns>The calculated cost.</returns>
public static long SignatureContractCost() =>
ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * 2 +
ApplicationEngine.OpCodePrices[OpCode.SYSCALL] +
ApplicationEngine.OpCodePriceTable[(byte)OpCode.PUSHDATA1] * 2 +
ApplicationEngine.OpCodePriceTable[(byte)OpCode.SYSCALL] +
ApplicationEngine.CheckSigPrice;

/// <summary>
Expand All @@ -51,12 +51,12 @@ public static long SignatureContractCost() =>
/// <returns>The calculated cost.</returns>
public static long MultiSignatureContractCost(int m, int n)
{
long fee = ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * (m + n);
long fee = ApplicationEngine.OpCodePriceTable[(byte)OpCode.PUSHDATA1] * (m + n);
using (ScriptBuilder sb = new())
fee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(m).ToArray()[0]];
fee += ApplicationEngine.OpCodePriceTable[(byte)(OpCode)sb.EmitPush(m).ToArray()[0]];
using (ScriptBuilder sb = new())
fee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(n).ToArray()[0]];
fee += ApplicationEngine.OpCodePrices[OpCode.SYSCALL];
fee += ApplicationEngine.OpCodePriceTable[(byte)(OpCode)sb.EmitPush(n).ToArray()[0]];
fee += ApplicationEngine.OpCodePriceTable[(byte)OpCode.SYSCALL];
fee += ApplicationEngine.CheckSigPrice * n;
return fee;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/Neo.UnitTests/SmartContract/UT_Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public void TestSignatureRedeemScriptFee()
byte[] verification = Contract.CreateSignatureRedeemScript(key.PublicKey);
byte[] invocation = new ScriptBuilder().EmitPush(UInt160.Zero).ToArray();

var fee = PolicyContract.DefaultExecFeeFactor * (ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * 2 + ApplicationEngine.OpCodePrices[OpCode.SYSCALL] + ApplicationEngine.CheckSigPrice);
var fee = PolicyContract.DefaultExecFeeFactor * (ApplicationEngine.OpCodePriceTable[(byte)OpCode.PUSHDATA1] * 2 + ApplicationEngine.OpCodePriceTable[(byte)OpCode.SYSCALL] + ApplicationEngine.CheckSigPrice);

using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, new Transaction { Signers = Array.Empty<Signer>(), Attributes = Array.Empty<TransactionAttribute>() }, null, settings: TestBlockchain.TheNeoSystem.Settings))
{
Expand Down Expand Up @@ -192,7 +192,7 @@ public void TestCreateMultiSigRedeemScriptFee()
byte[] verification = Contract.CreateMultiSigRedeemScript(2, publicKeys);
byte[] invocation = new ScriptBuilder().EmitPush(UInt160.Zero).EmitPush(UInt160.Zero).ToArray();

long fee = PolicyContract.DefaultExecFeeFactor * (ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * (2 + 2) + ApplicationEngine.OpCodePrices[OpCode.PUSHINT8] * 2 + ApplicationEngine.OpCodePrices[OpCode.SYSCALL] + ApplicationEngine.CheckSigPrice * 2);
long fee = PolicyContract.DefaultExecFeeFactor * (ApplicationEngine.OpCodePriceTable[(byte)OpCode.PUSHDATA1] * (2 + 2) + ApplicationEngine.OpCodePriceTable[(byte)OpCode.PUSHINT8] * 2 + ApplicationEngine.OpCodePriceTable[(byte)OpCode.SYSCALL] + ApplicationEngine.CheckSigPrice * 2);

using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, new Transaction { Signers = Array.Empty<Signer>(), Attributes = Array.Empty<TransactionAttribute>() }, null, settings: TestBlockchain.TheNeoSystem.Settings))
{
Expand Down
15 changes: 14 additions & 1 deletion tests/Neo.UnitTests/SmartContract/UT_OpCodePrices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,20 @@ public class UT_OpCodePrices
public void AllOpcodePriceAreSet()
{
foreach (OpCode opcode in Enum.GetValues(typeof(OpCode)))
Assert.IsTrue(ApplicationEngine.OpCodePrices.ContainsKey(opcode), opcode.ToString());
{
#pragma warning disable CS0618 // Type or member is obsolete
Assert.IsTrue(ApplicationEngine.OpCodePrices.ContainsKey(opcode), opcode.ToString(), $"{opcode} without price");
Assert.AreEqual(ApplicationEngine.OpCodePrices[opcode], ApplicationEngine.OpCodePriceTable[(byte)opcode], $"{opcode} price mismatch");
#pragma warning restore CS0618 // Type or member is obsolete

if (opcode == OpCode.RET ||
opcode == OpCode.SYSCALL ||
opcode == OpCode.ABORT ||
opcode == OpCode.ABORTMSG)
continue;

Assert.AreNotEqual(0, ApplicationEngine.OpCodePriceTable[(byte)opcode], $"{opcode} without price");
}
}
}
}

0 comments on commit 4940501

Please sign in to comment.