From 603b79b19667044c1d4a2473e374b09f99f03fff Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Wed, 30 Dec 2020 16:33:48 +0800 Subject: [PATCH] Optimize ApplicationEngine.LoadScript() (#2186) Co-authored-by: Shargon --- src/neo/SmartContract/ApplicationEngine.cs | 13 +++++++------ src/neo/SmartContract/ExecutionContextState.cs | 2 +- src/neo/SmartContract/Helper.cs | 8 ++++++-- .../Extensions/Nep17NativeContractExtensions.cs | 10 +++++----- .../SmartContract/Native/UT_NativeContract.cs | 2 +- .../SmartContract/Native/UT_NeoToken.cs | 14 +++++++------- tests/neo.UnitTests/SmartContract/UT_Contract.cs | 4 ++-- 7 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 3d1ca22659..d04c7e2b9b 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -117,8 +117,11 @@ public ExecutionContext LoadContract(ContractState contract, string method, Call pcount: pcount, rvcount: hasReturnValue ? 1 : 0, initialPosition: md.Offset, - callFlags: callFlags, - scriptHash: contract.Hash); + configureState: p => + { + p.CallFlags = callFlags; + p.ScriptHash = contract.Hash; + }); // Call initialization var init = contract.Manifest.Abi.GetMethod("_initialize"); @@ -130,13 +133,11 @@ public ExecutionContext LoadContract(ContractState contract, string method, Call return context; } - public ExecutionContext LoadScript(Script script, ushort pcount = 0, int rvcount = -1, int initialPosition = 0, CallFlags callFlags = CallFlags.All, UInt160 scriptHash = null) + public ExecutionContext LoadScript(Script script, ushort pcount = 0, int rvcount = -1, int initialPosition = 0, Action configureState = null) { // Create and configure context ExecutionContext context = CreateContext(script, pcount, rvcount, initialPosition); - var state = context.GetState(); - state.CallFlags = callFlags; - state.ScriptHash = scriptHash ?? ((byte[])script).ToScriptHash(); + configureState?.Invoke(context.GetState()); // Load context LoadContext(context); return context; diff --git a/src/neo/SmartContract/ExecutionContextState.cs b/src/neo/SmartContract/ExecutionContextState.cs index 7c5aca4231..0d0250803c 100644 --- a/src/neo/SmartContract/ExecutionContextState.cs +++ b/src/neo/SmartContract/ExecutionContextState.cs @@ -1,6 +1,6 @@ namespace Neo.SmartContract { - internal class ExecutionContextState + public class ExecutionContextState { /// /// Script hash diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index a84c9ec1c7..4c1a6a55a6 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -194,10 +194,14 @@ internal static bool VerifyWitness(this IVerifiable verifiable, StoreView snapsh { if (NativeContract.IsNative(hash)) return false; if (hash != witness.ScriptHash) return false; - engine.LoadScript(verification, callFlags: callFlags, scriptHash: hash, initialPosition: 0); + engine.LoadScript(verification, initialPosition: 0, configureState: p => + { + p.CallFlags = callFlags; + p.ScriptHash = hash; + }); } - engine.LoadScript(witness.InvocationScript, callFlags: CallFlags.None); + engine.LoadScript(witness.InvocationScript, configureState: p => p.CallFlags = CallFlags.None); if (NativeContract.IsNative(hash)) { diff --git a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs index 942993b5e6..909ae98d86 100644 --- a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs @@ -40,7 +40,7 @@ public static bool Transfer(this NativeContract contract, StoreView snapshot, by var engine = ApplicationEngine.Create(TriggerType.Application, new ManualWitness(signFrom ? new UInt160(from) : null), snapshot); - engine.LoadScript(contract.Script, pcount: 4, callFlags: CallFlags.All, scriptHash: contract.Hash); + engine.LoadScript(contract.Script, pcount: 4, configureState: p => p.ScriptHash = contract.Hash); var script = new ScriptBuilder(); script.Emit(OpCode.PUSHNULL); @@ -65,7 +65,7 @@ public static BigInteger TotalSupply(this NativeContract contract, StoreView sna { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(contract.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: contract.Hash); + engine.LoadScript(contract.Script, pcount: 0, configureState: p => p.ScriptHash = contract.Hash); var script = new ScriptBuilder(); script.EmitPush("totalSupply"); @@ -83,7 +83,7 @@ public static BigInteger BalanceOf(this NativeContract contract, StoreView snaps { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(contract.Script, pcount: 1, callFlags: CallFlags.All, scriptHash: contract.Hash); + engine.LoadScript(contract.Script, pcount: 1, configureState: p => p.ScriptHash = contract.Hash); var script = new ScriptBuilder(); script.EmitPush(account); @@ -102,7 +102,7 @@ public static BigInteger Decimals(this NativeContract contract, StoreView snapsh { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(contract.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: contract.Hash); + engine.LoadScript(contract.Script, pcount: 0, configureState: p => p.ScriptHash = contract.Hash); var script = new ScriptBuilder(); script.EmitPush("decimals"); @@ -120,7 +120,7 @@ public static string Symbol(this NativeContract contract, StoreView snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(contract.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: contract.Hash); + engine.LoadScript(contract.Script, pcount: 0, configureState: p => p.ScriptHash = contract.Hash); var script = new ScriptBuilder(); script.EmitPush("symbol"); diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index f7ccdd206d..c473829357 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -99,7 +99,7 @@ public void TestInvoke() { var snapshot = Blockchain.Singleton.GetSnapshot(); ApplicationEngine engine = ApplicationEngine.Create(TriggerType.OnPersist, null, snapshot, 0); - engine.LoadScript(testNativeContract.Script, callFlags: CallFlags.All, scriptHash: testNativeContract.Hash); + engine.LoadScript(testNativeContract.Script, configureState: p => p.ScriptHash = testNativeContract.Hash); ByteString method1 = new ByteString(System.Text.Encoding.Default.GetBytes("wrongMethod")); VMArray args1 = new VMArray(); diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs index 02899a5a71..1bf90d305d 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs @@ -867,7 +867,7 @@ internal static (BigInteger Value, bool State) Check_GetGasPerBlock(StoreView sn { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 0, configureState: p => p.ScriptHash = NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush("getGasPerBlock"); @@ -889,7 +889,7 @@ internal static (VM.Types.Boolean Value, bool State) Check_SetGasPerBlock(StoreV UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot); var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(committeeMultiSigAddr), snapshot); - engine.LoadScript(NativeContract.NEO.Script, pcount: 1, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 1, configureState: p => p.ScriptHash = NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(gasPerBlock); @@ -912,7 +912,7 @@ internal static (bool State, bool Result) Check_Vote(StoreView snapshot, byte[] var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(signAccount ? new UInt160(account) : UInt160.Zero), snapshot); - engine.LoadScript(NativeContract.NEO.Script, pcount: 2, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 2, configureState: p => p.ScriptHash = NativeContract.NEO.Hash); var script = new ScriptBuilder(); @@ -940,7 +940,7 @@ internal static (bool State, bool Result) Check_RegisterValidator(StoreView snap var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot); - engine.LoadScript(NativeContract.NEO.Script, pcount: 1, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 1, configureState: p => p.ScriptHash = NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(pubkey); @@ -962,7 +962,7 @@ internal static ECPoint[] Check_GetCommittee(StoreView snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 0, configureState: p => p.ScriptHash = NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush("getCommittee"); @@ -980,7 +980,7 @@ internal static (BigInteger Value, bool State) Check_UnclaimedGas(StoreView snap { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script, pcount: 2, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 2, configureState: p => p.ScriptHash = NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(snapshot.PersistingBlock.Index); @@ -1040,7 +1040,7 @@ internal static (bool State, bool Result) Check_UnregisterCandidate(StoreView sn var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot); - engine.LoadScript(NativeContract.NEO.Script, pcount: 1, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 1, configureState: p => p.ScriptHash = NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(pubkey); diff --git a/tests/neo.UnitTests/SmartContract/UT_Contract.cs b/tests/neo.UnitTests/SmartContract/UT_Contract.cs index 57cea86681..cc67603991 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Contract.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Contract.cs @@ -180,7 +180,7 @@ public void TestSignatureRedeemScriptFee() using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, new Transaction { Signers = Array.Empty(), Attributes = Array.Empty() }, null)) { - engine.LoadScript(invocation.Concat(verification).ToArray(), callFlags: CallFlags.None); + engine.LoadScript(invocation.Concat(verification).ToArray(), configureState: p => p.CallFlags = CallFlags.None); engine.Execute(); engine.GasConsumed.Should().Be(fee); } @@ -208,7 +208,7 @@ public void TestCreateMultiSigRedeemScriptFee() using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, new Transaction { Signers = Array.Empty(), Attributes = Array.Empty() }, null)) { - engine.LoadScript(invocation.Concat(verification).ToArray(), callFlags: CallFlags.None); + engine.LoadScript(invocation.Concat(verification).ToArray(), configureState: p => p.CallFlags = CallFlags.None); engine.Execute(); engine.GasConsumed.Should().Be(fee); }