Skip to content

Commit aa452ce

Browse files
authored
Merge pull request #182 from harmony-dev/feature/mocked-start
Feature/mocked start
2 parents 19e2a72 + dd7ebad commit aa452ce

File tree

11 files changed

+361
-102
lines changed

11 files changed

+361
-102
lines changed

chain/src/main/java/org/ethereum/beacon/chain/DefaultBeaconChain.java

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import org.ethereum.beacon.consensus.verifier.VerificationResult;
1818
import org.ethereum.beacon.core.BeaconBlock;
1919
import org.ethereum.beacon.core.BeaconState;
20-
import org.ethereum.beacon.core.state.Checkpoint;
2120
import org.ethereum.beacon.core.types.SlotNumber;
2221
import org.ethereum.beacon.schedulers.Schedulers;
2322
import org.ethereum.beacon.stream.SimpleProcessor;
@@ -28,7 +27,6 @@ public class DefaultBeaconChain implements MutableBeaconChain {
2827
private static final Logger logger = LogManager.getLogger(DefaultBeaconChain.class);
2928

3029
private final BeaconChainSpec spec;
31-
private final BlockTransition<BeaconStateEx> initialTransition;
3230
private final EmptySlotTransition preBlockTransition;
3331
private final BlockTransition<BeaconStateEx> blockTransition;
3432
private final BeaconBlockVerifier blockVerifier;
@@ -44,15 +42,13 @@ public class DefaultBeaconChain implements MutableBeaconChain {
4442

4543
public DefaultBeaconChain(
4644
BeaconChainSpec spec,
47-
BlockTransition<BeaconStateEx> initialTransition,
4845
EmptySlotTransition preBlockTransition,
4946
BlockTransition<BeaconStateEx> blockTransition,
5047
BeaconBlockVerifier blockVerifier,
5148
BeaconStateVerifier stateVerifier,
5249
BeaconChainStorage chainStorage,
5350
Schedulers schedulers) {
5451
this.spec = spec;
55-
this.initialTransition = initialTransition;
5652
this.preBlockTransition = preBlockTransition;
5753
this.blockTransition = blockTransition;
5854
this.blockVerifier = blockVerifier;
@@ -67,7 +63,7 @@ public DefaultBeaconChain(
6763
@Override
6864
public void init() {
6965
if (tupleStorage.isEmpty()) {
70-
initializeStorage();
66+
throw new IllegalStateException("Couldn't start from empty storage");
7167
}
7268
this.recentlyProcessed = fetchRecentTuple();
7369
blockStream.onNext(new BeaconTupleDetails(recentlyProcessed));
@@ -83,23 +79,6 @@ private BeaconTuple fetchRecentTuple() {
8379
() -> new RuntimeException("Block with stored maxSlot not found, maxSlot: " + maxSlot));
8480
}
8581

86-
private void initializeStorage() {
87-
BeaconBlock initialGenesis = spec.get_empty_block();
88-
BeaconStateEx initialState =
89-
initialTransition.apply(BeaconStateEx.getEmpty(spec.getConstants()), initialGenesis);
90-
91-
Hash32 initialStateRoot = spec.hash_tree_root(initialState);
92-
BeaconBlock genesis = initialGenesis.withStateRoot(initialStateRoot);
93-
Hash32 genesisRoot = spec.signing_root(genesis);
94-
BeaconTuple tuple = BeaconTuple.of(genesis, initialState);
95-
96-
tupleStorage.put(tuple);
97-
chainStorage.getJustifiedStorage().set(
98-
new Checkpoint(initialState.getCurrentJustifiedCheckpoint().getEpoch(), genesisRoot));
99-
chainStorage.getFinalizedStorage().set(
100-
new Checkpoint(initialState.getFinalizedCheckpoint().getEpoch(), genesisRoot));
101-
}
102-
10382
@Override
10483
public synchronized ImportResult insert(BeaconBlock block) {
10584
if (rejectedByTime(block)) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.ethereum.beacon.chain.storage.util;
2+
3+
import org.ethereum.beacon.chain.BeaconTuple;
4+
import org.ethereum.beacon.chain.storage.BeaconChainStorage;
5+
import org.ethereum.beacon.consensus.BeaconChainSpec;
6+
import org.ethereum.beacon.consensus.BeaconStateEx;
7+
import org.ethereum.beacon.core.BeaconBlock;
8+
import org.ethereum.beacon.core.state.Checkpoint;
9+
import tech.pegasys.artemis.ethereum.core.Hash32;
10+
11+
/**
12+
* Utility functions to initialize storage from an initial state.
13+
*/
14+
public class StorageUtils {
15+
/**
16+
* Creates a BeaconTuple consisting of the initialState and corresponding block.
17+
* Currently, the block is empty, but could be re-constructed from the state's block header,
18+
* in general.
19+
*/
20+
public static BeaconTuple createInitialBeaconTuple(
21+
BeaconChainSpec spec, BeaconStateEx initialState) {
22+
BeaconBlock initialGenesis = spec.get_empty_block();
23+
Hash32 initialStateRoot = spec.hash_tree_root(initialState);
24+
BeaconBlock genesis = initialGenesis.withStateRoot(initialStateRoot);
25+
return BeaconTuple.of(genesis, initialState);
26+
}
27+
28+
/**
29+
* An utility to properly initialize a storage with a specified initial state.
30+
* Supports only initial state currently. Could be extended in theory, to support
31+
* finalized states.
32+
*/
33+
public static void initializeStorage(
34+
BeaconChainStorage storage, BeaconChainSpec spec, BeaconStateEx initialState) {
35+
assert storage.getTupleStorage().isEmpty();
36+
BeaconTuple tuple = createInitialBeaconTuple(spec, initialState);
37+
Hash32 genesisRoot = spec.signing_root(tuple.getBlock());
38+
storage.getTupleStorage().put(tuple);
39+
storage
40+
.getJustifiedStorage()
41+
.set(new Checkpoint(initialState.getCurrentJustifiedCheckpoint().getEpoch(), genesisRoot));
42+
storage
43+
.getFinalizedStorage()
44+
.set(new Checkpoint(initialState.getFinalizedCheckpoint().getEpoch(), genesisRoot));
45+
}
46+
}

chain/src/test/java/org/ethereum/beacon/chain/DefaultBeaconChainTest.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package org.ethereum.beacon.chain;
22

3-
import java.util.Collections;
4-
import java.util.stream.IntStream;
53
import org.ethereum.beacon.chain.MutableBeaconChain.ImportResult;
64
import org.ethereum.beacon.chain.storage.BeaconChainStorage;
75
import org.ethereum.beacon.chain.storage.impl.SSZBeaconChainStorageFactory;
86
import org.ethereum.beacon.chain.storage.impl.SerializerFactory;
7+
import org.ethereum.beacon.chain.storage.util.StorageUtils;
98
import org.ethereum.beacon.consensus.BeaconChainSpec;
109
import org.ethereum.beacon.consensus.BeaconStateEx;
1110
import org.ethereum.beacon.consensus.BlockTransition;
@@ -33,6 +32,9 @@
3332
import tech.pegasys.artemis.ethereum.core.Hash32;
3433
import tech.pegasys.artemis.util.uint.UInt64;
3534

35+
import java.util.Collections;
36+
import java.util.stream.IntStream;
37+
3638
public class DefaultBeaconChainTest {
3739

3840
@Test
@@ -86,7 +88,7 @@ private MutableBeaconChain createBeaconChain(
8688
BeaconChainSpec spec, StateTransition<BeaconStateEx> perSlotTransition, Schedulers schedulers) {
8789
Time start = Time.castFrom(UInt64.valueOf(schedulers.getCurrentTime() / 1000));
8890
ChainStart chainStart = new ChainStart(start, Eth1Data.EMPTY, Collections.emptyList());
89-
BlockTransition<BeaconStateEx> initialTransition =
91+
InitialStateTransition initialTransition =
9092
new InitialStateTransition(chainStart, spec);
9193
BlockTransition<BeaconStateEx> perBlockTransition =
9294
StateTransitionTestUtil.createPerBlockTransition();
@@ -99,10 +101,11 @@ private MutableBeaconChain createBeaconChain(
99101
BeaconChainStorage chainStorage = new SSZBeaconChainStorageFactory(
100102
spec.getObjectHasher(), SerializerFactory.createSSZ(spec.getConstants()))
101103
.create(database);
104+
BeaconStateEx initialState = initialTransition.apply(spec.get_empty_block());
105+
StorageUtils.initializeStorage(chainStorage, spec, initialState);
102106

103107
return new DefaultBeaconChain(
104108
spec,
105-
initialTransition,
106109
new EmptySlotTransition(
107110
new ExtendedSlotTransition(new PerEpochTransition(spec) {
108111
@Override

chain/src/test/java/org/ethereum/beacon/chain/util/SampleObservableState.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import org.ethereum.beacon.chain.storage.BeaconChainStorage;
1212
import org.ethereum.beacon.chain.storage.impl.SSZBeaconChainStorageFactory;
1313
import org.ethereum.beacon.chain.storage.impl.SerializerFactory;
14+
import org.ethereum.beacon.chain.storage.util.StorageUtils;
1415
import org.ethereum.beacon.consensus.BeaconChainSpec;
16+
import org.ethereum.beacon.consensus.BeaconStateEx;
1517
import org.ethereum.beacon.consensus.StateTransitions;
1618
import org.ethereum.beacon.consensus.TestUtils;
1719
import org.ethereum.beacon.consensus.transition.EmptySlotTransition;
@@ -93,13 +95,14 @@ public SlotNumber getGenesisSlot() {
9395
new SSZBeaconChainStorageFactory(
9496
spec.getObjectHasher(), SerializerFactory.createSSZ(specConstants))
9597
.create(db);
98+
BeaconStateEx initialState = initialTransition.apply(spec.get_empty_block());
99+
StorageUtils.initializeStorage(beaconChainStorage, spec, initialState);
96100

97101
BeaconBlockVerifier blockVerifier = (block, state) -> VerificationResult.PASSED;
98102
BeaconStateVerifier stateVerifier = (block, state) -> VerificationResult.PASSED;
99103

100104
beaconChain = new DefaultBeaconChain(
101105
spec,
102-
initialTransition,
103106
preBlockTransition,
104107
blockTransition,
105108
blockVerifier,
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package org.ethereum.beacon.start.common;
2+
3+
import org.ethereum.beacon.core.types.Time;
4+
import org.ethereum.beacon.db.Database;
5+
import org.ethereum.beacon.db.InMemoryDatabase;
6+
import tech.pegasys.artemis.ethereum.core.Hash32;
7+
8+
import java.io.IOException;
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
import java.nio.file.Paths;
12+
13+
/**
14+
* DB Manager which incapsulates logic to create or remove/clean DB. This is probably an
15+
* intermediate solution. A better way may be extending {@link
16+
* org.ethereum.beacon.chain.storage.BeaconChainStorageFactory} with the appropriate functionality.
17+
*/
18+
public interface DatabaseManager {
19+
/** Creates a DB for a given &lt;genesisTime, depositRoot&gt; pair. */
20+
Database getOrCreateDatabase(Time genesisTime, Hash32 depositRoot);
21+
22+
/** Removes/wipes a DB corresponding to a given &lt;genesisTime, depositRoot&gt; pair. */
23+
void removeDatabase(Time genesisTime, Hash32 depositRoot);
24+
25+
static DatabaseManager createInMemoryDBFactory() {
26+
return new DatabaseManager() {
27+
@Override
28+
public Database getOrCreateDatabase(Time genesisTime, Hash32 depositRoot) {
29+
return new InMemoryDatabase();
30+
}
31+
32+
@Override
33+
public void removeDatabase(Time genesisTime, Hash32 depositRoot) {}
34+
};
35+
}
36+
37+
static DatabaseManager createRocksDBFactory(String dbPrefix, long bufferSize) {
38+
return new DatabaseManager() {
39+
@Override
40+
public Database getOrCreateDatabase(Time genesisTime, Hash32 depositRoot) {
41+
return Database.rocksDB(
42+
Paths.get(computeDbName(dbPrefix, genesisTime, depositRoot)).toString(), bufferSize);
43+
}
44+
45+
@Override
46+
public void removeDatabase(Time genesisTime, Hash32 depositRoot) {
47+
Path path = Paths.get(computeDbName(dbPrefix, genesisTime, depositRoot));
48+
try {
49+
if (Files.exists(path)) {
50+
Files.list(path)
51+
.forEach(
52+
f -> {
53+
try {
54+
Files.delete(f);
55+
} catch (IOException e) {
56+
}
57+
});
58+
// Files.delete(path);
59+
}
60+
} catch (IOException e) {
61+
throw new RuntimeException("Cannot remove DB " + path.toString(), e);
62+
}
63+
}
64+
};
65+
}
66+
67+
static String computeDbName(String dbPrefix, Time startTime, Hash32 depositRoot) {
68+
return String.format(
69+
"%s_start_time_%d_dep_root_%s",
70+
dbPrefix, startTime.getValue(), depositRoot.toStringShort());
71+
}
72+
}

start/common/src/main/java/org/ethereum/beacon/start/common/Launcher.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.ethereum.beacon.start.common;
22

3-
import java.util.List;
43
import org.ethereum.beacon.bench.BenchmarkController;
54
import org.ethereum.beacon.bench.BenchmarkController.BenchmarkRoutine;
65
import org.ethereum.beacon.chain.DefaultBeaconChain;
@@ -30,6 +29,7 @@
3029
import org.ethereum.beacon.db.InMemoryDatabase;
3130
import org.ethereum.beacon.pow.DepositContract;
3231
import org.ethereum.beacon.schedulers.Schedulers;
32+
import org.ethereum.beacon.chain.storage.util.StorageUtils;
3333
import org.ethereum.beacon.util.stats.MeasurementsCollector;
3434
import org.ethereum.beacon.validator.BeaconChainProposer;
3535
import org.ethereum.beacon.validator.attester.BeaconChainAttesterImpl;
@@ -41,6 +41,8 @@
4141
import reactor.core.publisher.Flux;
4242
import reactor.core.publisher.Mono;
4343

44+
import java.util.List;
45+
4446
public class Launcher {
4547
private final BeaconChainSpec spec;
4648
private final DepositContract depositContract;
@@ -117,6 +119,8 @@ void chainStarted(ChainStart chainStartEvent) {
117119

118120
db = new InMemoryDatabase();
119121
beaconChainStorage = storageFactory.create(db);
122+
BeaconStateEx initialState = initialTransition.apply(spec.get_empty_block());
123+
StorageUtils.initializeStorage(beaconChainStorage, spec, initialState);
120124

121125
// do not create block verifier for benchmarks, otherwise verification won't be tracked by
122126
// controller
@@ -129,7 +133,6 @@ void chainStarted(ChainStart chainStartEvent) {
129133
beaconChain =
130134
new DefaultBeaconChain(
131135
spec,
132-
initialTransition,
133136
isBenchmarkMode() ? benchmarkingEmptySlotTransition(spec) : emptySlotTransition,
134137
isBenchmarkMode() ? benchmarkingBlockTransition(spec) : new PerBlockTransition(spec),
135138
blockVerifier,

0 commit comments

Comments
 (0)