From 2b76924a4559e1348b420dea2142a0cd92b29ba6 Mon Sep 17 00:00:00 2001 From: Asuka Date: Mon, 31 Aug 2026 17:00:30 +0800 Subject: [PATCH] perf: optimize jump table initialization and reuse --- .../org/tron/core/actuator/VMActuator.java | 3 +- .../main/java/org/tron/core/vm/Operation.java | 8 + .../org/tron/core/vm/OperationRegistry.java | 187 +++++++++--------- .../org/tron/core/vm/program/Program.java | 6 +- .../common/runtime/VMActuatorMockTest.java | 55 +++++- .../common/runtime/vm/OperationsTest.java | 2 +- .../runtime/vm/VoteWitnessCost3Test.java | 4 +- .../tron/core/vm/OperationRegistryTest.java | 142 +++++++++++++ 8 files changed, 307 insertions(+), 100 deletions(-) create mode 100644 framework/src/test/java/org/tron/core/vm/OperationRegistryTest.java diff --git a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java index d785951027b..58f29d6113a 100644 --- a/actuator/src/main/java/org/tron/core/actuator/VMActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/VMActuator.java @@ -189,7 +189,8 @@ public void execute(Object object) throws ContractExeException { throw e; } - VM.play(program, OperationRegistry.getTable()); + // Prepare the table once for this execution and all nested calls. + VM.play(program, OperationRegistry.prepareAndGetTable(isConstantCall)); result = program.getResult(); if (VMConfig.allowEnergyAdjustment()) { diff --git a/actuator/src/main/java/org/tron/core/vm/Operation.java b/actuator/src/main/java/org/tron/core/vm/Operation.java index 87ff8fce749..80b25262089 100644 --- a/actuator/src/main/java/org/tron/core/vm/Operation.java +++ b/actuator/src/main/java/org/tron/core/vm/Operation.java @@ -52,4 +52,12 @@ public void execute(Program program) { public boolean isEnabled() { return enabled.getAsBoolean(); } + + public Operation adjustCost(Function newCost) { + return new Operation(opcode, require, ret, newCost, action, enabled); + } + + public Operation adjustAction(Consumer newAction) { + return new Operation(opcode, require, ret, cost, newAction, enabled); + } } diff --git a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java index 8c078e843a2..28ce2147beb 100644 --- a/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java +++ b/actuator/src/main/java/org/tron/core/vm/OperationRegistry.java @@ -7,12 +7,45 @@ public class OperationRegistry { + private static final Operation DEFAULT_MLOAD = new Operation( + Op.MLOAD, 1, 1, EnergyCost::getMloadCost, OperationActions::mLoadAction); + + private static final Operation DEFAULT_MSTORE = new Operation( + Op.MSTORE, 2, 0, EnergyCost::getMStoreCost, OperationActions::mStoreAction); + + private static final Operation DEFAULT_MSTORE8 = new Operation( + Op.MSTORE8, 2, 0, EnergyCost::getMStore8Cost, OperationActions::mStore8Action); + + private static final Operation ADJUSTED_MLOAD = + DEFAULT_MLOAD.adjustCost(EnergyCost::getMloadCost2); + + private static final Operation ADJUSTED_MSTORE = + DEFAULT_MSTORE.adjustCost(EnergyCost::getMStoreCost2); + + private static final Operation ADJUSTED_MSTORE8 = + DEFAULT_MSTORE8.adjustCost(EnergyCost::getMStore8Cost2); + + private static final Operation DEFAULT_VOTEWITNESS = new Operation( + Op.VOTEWITNESS, 4, 1, EnergyCost::getVoteWitnessCost, + OperationActions::voteWitnessAction, VMConfig::allowTvmVote); + + private static final Operation ADJUSTED_VOTEWITNESS = + DEFAULT_VOTEWITNESS.adjustCost(EnergyCost::getVoteWitnessCost2); + + private static final Operation OSAKA_VOTEWITNESS = + DEFAULT_VOTEWITNESS.adjustCost(EnergyCost::getVoteWitnessCost3); + + private static final Operation DEFAULT_SUICIDE = new Operation( + Op.SUICIDE, 1, 0, EnergyCost::getSuicideCost, OperationActions::suicideAction); + + private static final Operation ADJUSTED_SUICIDE = + DEFAULT_SUICIDE.adjustCost(EnergyCost::getSuicideCost2); + + private static final Operation RESTRICTED_SUICIDE = + DEFAULT_SUICIDE.adjustCost(EnergyCost::getSuicideCost3) + .adjustAction(OperationActions::suicideAction2); + public enum Version { - TRON_V1_0, - TRON_V1_1, - TRON_V1_2, - TRON_V1_3, - TRON_V1_4, TRON_V1_5, // add more // TRON_V2, @@ -21,13 +54,21 @@ public enum Version { private static final Map tableMap = new HashMap<>(); + // The newest version in use. Bump this when a newer operation set is added, + // together with newLatestOperationSet() below. + private static final Version LATEST_VERSION = Version.TRON_V1_5; + static { - tableMap.put(Version.TRON_V1_0, newTronV10OperationSet()); - tableMap.put(Version.TRON_V1_1, newTronV11OperationSet()); - tableMap.put(Version.TRON_V1_2, newTronV12OperationSet()); - tableMap.put(Version.TRON_V1_3, newTronV13OperationSet()); - tableMap.put(Version.TRON_V1_4, newTronV14OperationSet()); - tableMap.put(Version.TRON_V1_5, newTronV15OperationSet()); + tableMap.put(LATEST_VERSION, newLatestOperationSet()); + } + + // Constant calls get a dedicated instance of the newest table, isolated from + // the shared consensus table above. + private static final JumpTable CONSTANT_CALL_TABLE = newLatestOperationSet(); + + // The single place that decides which operation set is the newest. + private static JumpTable newLatestOperationSet() { + return newTronV15OperationSet(); } public static JumpTable newTronV10OperationSet() { @@ -74,28 +115,22 @@ public static JumpTable newTronV15OperationSet() { // Just for warming up class to avoid out_of_time public static void init() {} - public static JumpTable getTable() { - // always get the table which has the newest version - JumpTable table = tableMap.get(Version.TRON_V1_5); - - // next make the corresponding changes, exclude activating opcode - if (VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx()) { - adjustMemOperations(table); - } - - if (VMConfig.allowEnergyAdjustment()) { - adjustForFairEnergy(table); - } - - if (VMConfig.allowTvmSelfdestructRestriction()) { - adjustSelfdestruct(table); - } + public static JumpTable prepareAndGetTable(boolean isConstantCall) { + JumpTable table = getTable(isConstantCall); + // Apply configuration-dependent changes once at the top level. + adjustTable(table); + return table; + } - if (VMConfig.allowTvmOsaka()) { - adjustVoteWitnessCost(table); - } + public static JumpTable getTable(boolean isConstantCall) { + return isConstantCall ? CONSTANT_CALL_TABLE : tableMap.get(LATEST_VERSION); + } - return table; + private static void adjustTable(JumpTable table) { + // Make the corresponding changes, excluding opcode activation. + adjustMemOperations(table); + adjustVoteWitness(table); + adjustSelfdestruct(table); } public static JumpTable newBaseOperationSet() { @@ -331,20 +366,11 @@ public static JumpTable newBaseOperationSet() { EnergyCost::getBaseTierCost, OperationActions::popAction)); - table.set(new Operation( - Op.MLOAD, 1, 1, - EnergyCost::getMloadCost, - OperationActions::mLoadAction)); + table.set(DEFAULT_MLOAD); - table.set(new Operation( - Op.MSTORE, 2, 0, - EnergyCost::getMStoreCost, - OperationActions::mStoreAction)); + table.set(DEFAULT_MSTORE); - table.set(new Operation( - Op.MSTORE8, 2, 0, - EnergyCost::getMStore8Cost, - OperationActions::mStore8Action)); + table.set(DEFAULT_MSTORE8); table.set(new Operation( Op.SLOAD, 1, 1, @@ -449,10 +475,7 @@ public static JumpTable newBaseOperationSet() { EnergyCost::getRevertCost, OperationActions::revertAction)); - table.set(new Operation( - Op.SUICIDE, 1, 0, - EnergyCost::getSuicideCost, - OperationActions::suicideAction)); + table.set(DEFAULT_SUICIDE); return table; } @@ -570,11 +593,7 @@ public static void appendFreezeOperations(JumpTable table) { public static void appendVoteOperations(JumpTable table) { BooleanSupplier proposal = VMConfig::allowTvmVote; - table.set(new Operation( - Op.VOTEWITNESS, 4, 1, - EnergyCost::getVoteWitnessCost, - OperationActions::voteWitnessAction, - proposal)); + table.set(DEFAULT_VOTEWITNESS); table.set(new Operation( Op.WITHDRAWREWARD, 0, 1, @@ -593,23 +612,6 @@ public static void appendLondonOperations(JumpTable table) { proposal)); } - public static void adjustMemOperations(JumpTable table) { - table.set(new Operation( - Op.MLOAD, 1, 1, - EnergyCost::getMloadCost2, - OperationActions::mLoadAction)); - - table.set(new Operation( - Op.MSTORE, 2, 0, - EnergyCost::getMStoreCost2, - OperationActions::mStoreAction)); - - table.set(new Operation( - Op.MSTORE8, 2, 0, - EnergyCost::getMStore8Cost2, - OperationActions::mStore8Action)); - } - public static void appendFreezeV2Operations(JumpTable table) { BooleanSupplier proposal = VMConfig::allowTvmFreezeV2; @@ -664,19 +666,6 @@ public static void appendShangHaiOperations(JumpTable table) { proposal)); } - public static void adjustForFairEnergy(JumpTable table) { - table.set(new Operation( - Op.VOTEWITNESS, 4, 1, - EnergyCost::getVoteWitnessCost2, - OperationActions::voteWitnessAction, - VMConfig::allowTvmVote)); - - table.set(new Operation( - Op.SUICIDE, 1, 0, - EnergyCost::getSuicideCost2, - OperationActions::suicideAction)); - } - public static void appendCancunOperations(JumpTable table) { BooleanSupplier proposal = VMConfig::allowTvmCancun; BooleanSupplier tvmBlobProposal = VMConfig::allowTvmBlob; @@ -722,18 +711,30 @@ public static void appendOsakaOperations(JumpTable table) { proposal)); } - public static void adjustSelfdestruct(JumpTable table) { - table.set(new Operation( - Op.SUICIDE, 1, 0, - EnergyCost::getSuicideCost3, - OperationActions::suicideAction2)); + public static void adjustMemOperations(JumpTable table) { + boolean adjusted = VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx(); + table.set(adjusted ? ADJUSTED_MLOAD : DEFAULT_MLOAD); + table.set(adjusted ? ADJUSTED_MSTORE : DEFAULT_MSTORE); + table.set(adjusted ? ADJUSTED_MSTORE8 : DEFAULT_MSTORE8); } - public static void adjustVoteWitnessCost(JumpTable table) { - table.set(new Operation( - Op.VOTEWITNESS, 4, 1, - EnergyCost::getVoteWitnessCost3, - OperationActions::voteWitnessAction, - VMConfig::allowTvmVote)); + public static void adjustVoteWitness(JumpTable table) { + if (VMConfig.allowTvmOsaka()) { + table.set(OSAKA_VOTEWITNESS); + } else if (VMConfig.allowEnergyAdjustment()) { + table.set(ADJUSTED_VOTEWITNESS); + } else { + table.set(DEFAULT_VOTEWITNESS); + } + } + + public static void adjustSelfdestruct(JumpTable table) { + if (VMConfig.allowTvmSelfdestructRestriction()) { + table.set(RESTRICTED_SUICIDE); + } else if (VMConfig.allowEnergyAdjustment()) { + table.set(ADJUSTED_SUICIDE); + } else { + table.set(DEFAULT_SUICIDE); + } } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 590859a9fef..5eddea4f916 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -914,7 +914,8 @@ this, new DataWord(newAddress), getContractAddress(), value, DataWord.ZERO(), if (VMConfig.allowTvmCompatibleEvm()) { program.setContractVersion(getContractVersion()); } - VM.play(program, OperationRegistry.getTable()); + // Reuse the table prepared by the top-level execution. + VM.play(program, OperationRegistry.getTable(isConstantCall())); createResult = program.getResult(); getTrace().merge(program.getTrace()); // always commit nonce @@ -1146,7 +1147,8 @@ this, new DataWord(contextAddress), program.setContractVersion(invoke.getDeposit() .getContract(codeAddress).getContractVersion()); } - VM.play(program, OperationRegistry.getTable()); + // Reuse the table prepared by the top-level execution. + VM.play(program, OperationRegistry.getTable(isConstantCall())); callResult = program.getResult(); getTrace().merge(program.getTrace()); diff --git a/framework/src/test/java/org/tron/common/runtime/VMActuatorMockTest.java b/framework/src/test/java/org/tron/common/runtime/VMActuatorMockTest.java index ab147f57a79..013ba606e9a 100644 --- a/framework/src/test/java/org/tron/common/runtime/VMActuatorMockTest.java +++ b/framework/src/test/java/org/tron/common/runtime/VMActuatorMockTest.java @@ -1,6 +1,8 @@ package org.tron.common.runtime; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.same; import java.lang.reflect.Field; import java.util.Collections; @@ -13,19 +15,70 @@ import org.tron.common.runtime.vm.LogInfo; import org.tron.core.actuator.VMActuator; import org.tron.core.db.TransactionContext; +import org.tron.core.vm.JumpTable; import org.tron.core.vm.OperationRegistry; import org.tron.core.vm.VM; import org.tron.core.vm.config.VMConfig; import org.tron.core.vm.program.Program; +import org.tron.core.vm.repository.Repository; public class VMActuatorMockTest { @BeforeClass public static void init() { - // warm up the registry so VM.play(..., OperationRegistry.getTable()) arg eval is safe + // Warm up the registry before VM execution timing starts. OperationRegistry.init(); } + @Test + public void constantCallUsesDedicatedJumpTable() throws Exception { + try (MockedStatic vmMock = Mockito.mockStatic(VM.class)) { + Program program = Mockito.mock(Program.class); + Mockito.when(program.getResult()).thenReturn(new ProgramResult()); + + VMActuator actuator = new VMActuator(true); + Field f = VMActuator.class.getDeclaredField("program"); + f.setAccessible(true); + f.set(actuator, program); + + TransactionContext context = Mockito.mock(TransactionContext.class); + Mockito.when(context.getProgramResult()).thenReturn(new ProgramResult()); + + actuator.execute(context); + + JumpTable transactionTable = OperationRegistry.getTable(false); + JumpTable constantCallTable = OperationRegistry.getTable(true); + vmMock.verify(() -> VM.play(any(), same(constantCallTable))); + vmMock.verify(() -> VM.play(any(), argThat(table -> table != transactionTable))); + } + } + + @Test + public void nonConstantCallUsesSharedJumpTable() throws Exception { + try (MockedStatic vmMock = Mockito.mockStatic(VM.class)) { + Program program = Mockito.mock(Program.class); + Mockito.when(program.getResult()).thenReturn(new ProgramResult()); + + VMActuator actuator = new VMActuator(false); + Field f = VMActuator.class.getDeclaredField("program"); + f.setAccessible(true); + f.set(actuator, program); + + Field repositoryField = VMActuator.class.getDeclaredField("rootRepository"); + repositoryField.setAccessible(true); + repositoryField.set(actuator, Mockito.mock(Repository.class)); + + TransactionContext context = Mockito.mock(TransactionContext.class); + Mockito.when(context.getProgramResult()).thenReturn(new ProgramResult()); + + actuator.execute(context); + + // The non-constant call must receive the shared consensus table itself. + JumpTable shared = OperationRegistry.getTable(false); + vmMock.verify(() -> VM.play(any(), same(shared))); + } + } + private void runCatchPathTest(Throwable thrownByVm, boolean osakaOn, int expectedSize) throws Exception { boolean prevOsaka = VMConfig.allowTvmOsaka(); diff --git a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java index a1627f4f2e2..16a56222806 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/OperationsTest.java @@ -51,7 +51,7 @@ public class OperationsTest extends BaseTest { private ProgramInvokeMockImpl invoke; private Program program; - private final JumpTable jumpTable = OperationRegistry.getTable(); + private final JumpTable jumpTable = OperationRegistry.prepareAndGetTable(false); @Autowired private Wallet wallet; diff --git a/framework/src/test/java/org/tron/common/runtime/vm/VoteWitnessCost3Test.java b/framework/src/test/java/org/tron/common/runtime/vm/VoteWitnessCost3Test.java index 2c7aa238033..b949cbd8dc8 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/VoteWitnessCost3Test.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/VoteWitnessCost3Test.java @@ -217,7 +217,7 @@ public void testWitnessArrayLargerThanAmountArray() { @Test public void testOperationRegistryWithoutOsaka() { VMConfig.initAllowTvmOsaka(0); - JumpTable table = OperationRegistry.getTable(); + JumpTable table = OperationRegistry.prepareAndGetTable(false); Operation voteOp = table.get(Op.VOTEWITNESS); assertTrue(voteOp.isEnabled()); @@ -233,7 +233,7 @@ public void testOperationRegistryWithoutOsaka() { public void testOperationRegistryWithOsaka() { VMConfig.initAllowTvmOsaka(1); try { - JumpTable table = OperationRegistry.getTable(); + JumpTable table = OperationRegistry.prepareAndGetTable(false); Operation voteOp = table.get(Op.VOTEWITNESS); assertTrue(voteOp.isEnabled()); diff --git a/framework/src/test/java/org/tron/core/vm/OperationRegistryTest.java b/framework/src/test/java/org/tron/core/vm/OperationRegistryTest.java new file mode 100644 index 00000000000..b6568f8a862 --- /dev/null +++ b/framework/src/test/java/org/tron/core/vm/OperationRegistryTest.java @@ -0,0 +1,142 @@ +package org.tron.core.vm; + +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; + +import org.junit.Test; +import org.tron.core.vm.config.VMConfig; + +public class OperationRegistryTest { + + @Test + public void constantAndTransactionExecutionsUseDedicatedTables() { + JumpTable transactionTable = OperationRegistry.prepareAndGetTable(false); + JumpTable constantCallTable = OperationRegistry.prepareAndGetTable(true); + + assertNotSame(transactionTable, constantCallTable); + assertSame(transactionTable, OperationRegistry.getTable(false)); + assertSame(constantCallTable, OperationRegistry.getTable(true)); + } + + @Test + public void transactionExecutionsReuseTable() { + JumpTable first = OperationRegistry.prepareAndGetTable(false); + JumpTable second = OperationRegistry.prepareAndGetTable(false); + + assertSame(first, second); + } + + @Test + public void constantExecutionsReuseTable() { + JumpTable first = OperationRegistry.prepareAndGetTable(true); + JumpTable second = OperationRegistry.prepareAndGetTable(true); + + assertSame(first, second); + } + + @Test + public void constantAdjustmentsDoNotMutateTransactionTable() { + boolean previousHigherLimit = VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx(); + JumpTable transactionTable = OperationRegistry.getTable(false); + JumpTable constantCallTable = OperationRegistry.getTable(true); + try { + VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx(0); + OperationRegistry.adjustMemOperations(transactionTable); + OperationRegistry.adjustMemOperations(constantCallTable); + Operation transactionMload = transactionTable.get(Op.MLOAD); + Operation constantMload = constantCallTable.get(Op.MLOAD); + + VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx(1); + OperationRegistry.adjustMemOperations(constantCallTable); + + assertSame(transactionMload, transactionTable.get(Op.MLOAD)); + assertNotSame(constantMload, constantCallTable.get(Op.MLOAD)); + } finally { + VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx(previousHigherLimit ? 1 : 0); + OperationRegistry.adjustMemOperations(transactionTable); + OperationRegistry.adjustMemOperations(constantCallTable); + } + } + + @Test + public void adjustedOperationsReuseCachedVariants() { + boolean previousHigherLimit = VMConfig.allowHigherLimitForMaxCpuTimeOfOneTx(); + boolean previousEnergyAdjustment = VMConfig.allowEnergyAdjustment(); + boolean previousOsaka = VMConfig.allowTvmOsaka(); + boolean previousSelfdestructRestriction = VMConfig.allowTvmSelfdestructRestriction(); + JumpTable table = OperationRegistry.newTronV15OperationSet(); + + Operation defaultMload = table.get(Op.MLOAD); + Operation defaultMstore = table.get(Op.MSTORE); + Operation defaultMstore8 = table.get(Op.MSTORE8); + Operation defaultVoteWitness = table.get(Op.VOTEWITNESS); + Operation defaultSuicide = table.get(Op.SUICIDE); + + try { + VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx(1); + VMConfig.initAllowEnergyAdjustment(1); + VMConfig.initAllowTvmOsaka(0); + VMConfig.initAllowTvmSelfdestructRestriction(0); + adjustOperations(table); + + Operation adjustedMload = table.get(Op.MLOAD); + Operation adjustedMstore = table.get(Op.MSTORE); + Operation adjustedMstore8 = table.get(Op.MSTORE8); + Operation adjustedVoteWitness = table.get(Op.VOTEWITNESS); + Operation adjustedSuicide = table.get(Op.SUICIDE); + + assertNotSame(defaultMload, adjustedMload); + assertNotSame(defaultMstore, adjustedMstore); + assertNotSame(defaultMstore8, adjustedMstore8); + assertNotSame(defaultVoteWitness, adjustedVoteWitness); + assertNotSame(defaultSuicide, adjustedSuicide); + + adjustOperations(table); + assertSame(adjustedMload, table.get(Op.MLOAD)); + assertSame(adjustedMstore, table.get(Op.MSTORE)); + assertSame(adjustedMstore8, table.get(Op.MSTORE8)); + assertSame(adjustedVoteWitness, table.get(Op.VOTEWITNESS)); + assertSame(adjustedSuicide, table.get(Op.SUICIDE)); + + VMConfig.initAllowTvmOsaka(1); + VMConfig.initAllowTvmSelfdestructRestriction(1); + adjustOperations(table); + + Operation osakaVoteWitness = table.get(Op.VOTEWITNESS); + Operation restrictedSuicide = table.get(Op.SUICIDE); + assertNotSame(adjustedVoteWitness, osakaVoteWitness); + assertNotSame(adjustedSuicide, restrictedSuicide); + + adjustOperations(table); + assertSame(adjustedMload, table.get(Op.MLOAD)); + assertSame(adjustedMstore, table.get(Op.MSTORE)); + assertSame(adjustedMstore8, table.get(Op.MSTORE8)); + assertSame(osakaVoteWitness, table.get(Op.VOTEWITNESS)); + assertSame(restrictedSuicide, table.get(Op.SUICIDE)); + + VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx(0); + VMConfig.initAllowEnergyAdjustment(0); + VMConfig.initAllowTvmOsaka(0); + VMConfig.initAllowTvmSelfdestructRestriction(0); + adjustOperations(table); + + assertSame(defaultMload, table.get(Op.MLOAD)); + assertSame(defaultMstore, table.get(Op.MSTORE)); + assertSame(defaultMstore8, table.get(Op.MSTORE8)); + assertSame(defaultVoteWitness, table.get(Op.VOTEWITNESS)); + assertSame(defaultSuicide, table.get(Op.SUICIDE)); + } finally { + VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx(previousHigherLimit ? 1 : 0); + VMConfig.initAllowEnergyAdjustment(previousEnergyAdjustment ? 1 : 0); + VMConfig.initAllowTvmOsaka(previousOsaka ? 1 : 0); + VMConfig.initAllowTvmSelfdestructRestriction( + previousSelfdestructRestriction ? 1 : 0); + } + } + + private static void adjustOperations(JumpTable table) { + OperationRegistry.adjustMemOperations(table); + OperationRegistry.adjustVoteWitness(table); + OperationRegistry.adjustSelfdestruct(table); + } +}