Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 78b4b27

Browse files
authored
Merge pull request #1182 from ethereum/feature/vmhook-extracting
VM hook redesign (optimized)
2 parents f45ef97 + d307c03 commit 78b4b27

File tree

7 files changed

+63
-94
lines changed

7 files changed

+63
-94
lines changed

ethereumj-core/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ ext {
114114
slf4jVersion = '1.7.7'
115115
leveldbVersion = '0.7'
116116
scastleVersion = '1.58.0.0'
117-
springVersion = '4.2.0.RELEASE'
117+
springVersion = '4.3.19.RELEASE'
118118
hibernateVersion = '4.3.7.Final'
119119
junitVersion = '4.11'
120120
}

ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,11 @@ public BlockchainImpl withParentBlockHeaderValidator(ParentBlockHeaderValidator
229229
return this;
230230
}
231231

232+
public BlockchainImpl withVmHook(VMHook vmHook) {
233+
this.vmHook = vmHook;
234+
return this;
235+
}
236+
232237
private void initConst(SystemProperties config) {
233238
minerCoinbase = config.getMinerCoinbase();
234239
minerExtraData = config.getMineExtraData();

ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.ethereum.validator.DependentBlockHeaderRuleAdapter;
4343
import org.ethereum.vm.DataWord;
4444
import org.ethereum.vm.LogInfo;
45+
import org.ethereum.vm.hook.VMHook;
4546
import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl;
4647
import org.iq80.leveldb.DBException;
4748
import org.spongycastle.util.encoders.Hex;
@@ -82,6 +83,7 @@ public class StandaloneBlockchain implements LocalBlockchain {
8283
PruneManager pruneManager;
8384

8485
private BlockSummary lastSummary;
86+
private VMHook vmHook = VMHook.EMPTY;
8587

8688
class PendingTx {
8789
ECKey sender;
@@ -193,6 +195,11 @@ public StandaloneBlockchain withDbDelay(long dbDelay) {
193195
return this;
194196
}
195197

198+
public StandaloneBlockchain withVmHook(VMHook vmHook) {
199+
this.vmHook = vmHook;
200+
return this;
201+
}
202+
196203
private Map<PendingTx, Transaction> createTransactions(Block parent) {
197204
Map<PendingTx, Transaction> txes = new LinkedHashMap<>();
198205
Map<ByteArrayWrapper, Long> nonces = new HashMap<>();
@@ -484,7 +491,8 @@ private BlockchainImpl createBlockchain(Genesis genesis) {
484491

485492
BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository)
486493
.withEthereumListener(listener)
487-
.withSyncManager(new SyncManager());
494+
.withSyncManager(new SyncManager())
495+
.withVmHook(vmHook);
488496
blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter());
489497
blockchain.setProgramInvokeFactory(programInvokeFactory);
490498
blockchain.setPruneManager(pruneManager);

ethereumj-core/src/main/java/org/ethereum/vm/VM.java

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.ethereum.config.BlockchainConfig;
2121
import org.ethereum.config.SystemProperties;
2222
import org.ethereum.db.ContractDetails;
23-
import org.ethereum.vm.hook.BackwardCompatibilityVmHook;
2423
import org.ethereum.vm.hook.VMHook;
2524
import org.ethereum.vm.program.Program;
2625
import org.ethereum.vm.program.Stack;
@@ -34,7 +33,9 @@
3433
import java.util.HashMap;
3534
import java.util.List;
3635
import java.util.Map;
36+
import java.util.function.Consumer;
3737
import java.util.function.Function;
38+
import java.util.stream.Stream;
3839

3940
import static org.ethereum.crypto.HashUtil.sha3;
4041
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
@@ -89,7 +90,6 @@ public class VM {
8990
// used to reduce expensive BigInt arithmetic
9091
private static BigInteger MAX_MEM_SIZE = BigInteger.valueOf(Integer.MAX_VALUE);
9192

92-
9393
/* Keeps track of the number of steps performed in this VM */
9494
private int vmCounter = 0;
9595

@@ -111,8 +111,11 @@ public class VM {
111111
}};
112112

113113
private final SystemProperties config;
114-
private final VMHook hook;
115114

115+
// deprecated field that holds VM hook. Will be removed in the future releases.
116+
private static VMHook deprecatedHook = VMHook.EMPTY;
117+
private final boolean hasHooks;
118+
private final VMHook[] hooks;
116119

117120
public VM() {
118121
this(SystemProperties.getDefault(), VMHook.EMPTY);
@@ -123,7 +126,16 @@ public VM(SystemProperties config, VMHook hook) {
123126
this.config = config;
124127
this.vmTrace = config.vmTrace();
125128
this.dumpBlock = config.dumpBlock();
126-
this.hook = new BackwardCompatibilityVmHook(hook);
129+
this.hooks = Stream.of(deprecatedHook, hook)
130+
.filter(h -> !h.isEmpty())
131+
.toArray(VMHook[]::new);
132+
this.hasHooks = this.hooks.length > 0;
133+
}
134+
135+
private void onHookEvent(Consumer<VMHook> consumer) {
136+
for (VMHook hook : this.hooks) {
137+
consumer.accept(hook);
138+
}
127139
}
128140

129141
private long calcMemGas(GasCost gasCosts, long oldMemSize, BigInteger newMemSize, long copySize) {
@@ -422,7 +434,9 @@ else if (!currentValue.isZero() && newValue.isZero()) {
422434
this.dumpLine(op, gasBefore, gasCost + callGas, memWords, program);
423435
}
424436

425-
hook.step(program, op);
437+
if (hasHooks) {
438+
onHookEvent(hook -> hook.step(program, op));
439+
}
426440

427441
// Execute operation
428442
switch (op) {
@@ -1413,7 +1427,9 @@ public void play(Program program) {
14131427
if (program.byTestingSuite()) return;
14141428

14151429
try {
1416-
hook.startPlay(program);
1430+
if (hasHooks) {
1431+
onHookEvent(hook -> hook.startPlay(program));
1432+
}
14171433

14181434
while (!program.isStopped()) {
14191435
this.step(program);
@@ -1425,7 +1441,9 @@ public void play(Program program) {
14251441
logger.error("\n !!! StackOverflowError: update your java run command with -Xss2M (-Xss8M for tests) !!!\n", soe);
14261442
System.exit(-1);
14271443
} finally {
1428-
hook.stopPlay(program);
1444+
if (hasHooks) {
1445+
onHookEvent(hook -> hook.stopPlay(program));
1446+
}
14291447
}
14301448
}
14311449

@@ -1436,7 +1454,7 @@ public void play(Program program) {
14361454
@Deprecated
14371455
public static void setVmHook(VMHook vmHook) {
14381456
logger.warn("VM.setVmHook(VMHook vmHook) is deprecated method. Define your hook component as a Spring bean.");
1439-
BackwardCompatibilityVmHook.setDeprecatedHook(vmHook);
1457+
VM.deprecatedHook = vmHook;
14401458
}
14411459

14421460
/**

ethereumj-core/src/main/java/org/ethereum/vm/hook/BackwardCompatibilityVmHook.java

Lines changed: 0 additions & 73 deletions
This file was deleted.

ethereumj-core/src/main/java/org/ethereum/vm/hook/RootVmHook.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
import org.springframework.context.annotation.Primary;
2626
import org.springframework.stereotype.Component;
2727

28-
import java.util.ArrayList;
29-
import java.util.List;
3028
import java.util.Optional;
3129
import java.util.function.Consumer;
3230

@@ -39,35 +37,40 @@ public class RootVmHook implements VMHook {
3937

4038
private static final Logger logger = LoggerFactory.getLogger("VM");
4139

42-
private final List<VMHook> hooks;
40+
private VMHook[] hooks;
4341

4442
@Autowired
45-
public RootVmHook(Optional<List<VMHook>> hooks) {
46-
this.hooks = hooks.orElseGet(ArrayList::new);
43+
public RootVmHook(Optional<VMHook[]> hooks) {
44+
this.hooks = hooks.orElseGet(() -> new VMHook[] {});
4745
}
4846

49-
private void safeProxyToAll(Consumer<VMHook> action) {
50-
this.hooks.forEach(hook -> {
47+
private void proxySafeToAll(Consumer<VMHook> action) {
48+
for (VMHook hook : hooks) {
5149
try {
5250
action.accept(hook);
5351
} catch (Throwable t) {
5452
logger.error("VM hook execution error: ", t);
5553
}
56-
});
54+
}
5755
}
5856

5957
@Override
6058
public void startPlay(Program program) {
61-
safeProxyToAll(hook -> hook.startPlay(program));
59+
proxySafeToAll(hook -> hook.startPlay(program));
6260
}
6361

6462
@Override
6563
public void step(Program program, OpCode opcode) {
66-
safeProxyToAll(hook -> hook.step(program, opcode));
64+
proxySafeToAll(hook -> hook.step(program, opcode));
6765
}
6866

6967
@Override
7068
public void stopPlay(Program program) {
71-
safeProxyToAll(hook -> hook.stopPlay(program));
69+
proxySafeToAll(hook -> hook.stopPlay(program));
70+
}
71+
72+
@Override
73+
public boolean isEmpty() {
74+
return hooks.length == 0;
7275
}
7376
}

ethereumj-core/src/main/java/org/ethereum/vm/hook/VMHook.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ default void step(Program program, OpCode opcode) {
3434
default void stopPlay(Program program) {
3535
}
3636

37+
default boolean isEmpty() {
38+
return false;
39+
}
40+
3741
VMHook EMPTY = new VMHook() {
42+
@Override
43+
public boolean isEmpty() {
44+
return true;
45+
}
3846
};
3947
}

0 commit comments

Comments
 (0)