Skip to content

Commit

Permalink
Merge pull request #1156 from ethereum/sharding/block-processing
Browse files Browse the repository at this point in the history
Beacon chain block processing
  • Loading branch information
mkalinin committed Aug 28, 2018
2 parents ad9ab1c + 56a3739 commit 3dcd158
Show file tree
Hide file tree
Showing 34 changed files with 2,199 additions and 18 deletions.
16 changes: 16 additions & 0 deletions ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.util.Arrays;
import java.util.Random;

import static java.util.Arrays.copyOfRange;
Expand Down Expand Up @@ -246,6 +247,21 @@ public static byte[] randomHash() {
return randomHash;
}

/**
* As discussed with other sharding implementors:
* there is an agreement on using first 256-bits of BLAKE2B-512 digest
*/
public static byte[] blake2b(byte[] data) {
try {
MessageDigest digest = MessageDigest.getInstance("BLAKE2B-512");
digest.update(data);
return Arrays.copyOf(digest.digest(), 32);
} catch (NoSuchAlgorithmException e) {
LOG.error("Can't find such algorithm", e);
throw new RuntimeException(e);
}
}

public static String shortHash(byte[] hash) {
return Hex.toHexString(hash).substring(0, 6);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ private static class Holder {

INSTANCE.put("MessageDigest.ETH-KECCAK-256", "org.ethereum.crypto.cryptohash.Keccak256");
INSTANCE.put("MessageDigest.ETH-KECCAK-512", "org.ethereum.crypto.cryptohash.Keccak512");

INSTANCE.put("MessageDigest.BLAKE2B-512", "org.spongycastle.jcajce.provider.digest.Blake2b$Blake2b512");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,28 @@

import org.ethereum.config.CommonConfig;
import org.ethereum.config.SystemProperties;
import org.ethereum.crypto.HashUtil;
import org.ethereum.datasource.AbstractCachedSource;
import org.ethereum.datasource.AsyncWriteCache;
import org.ethereum.datasource.BatchSourceWriter;
import org.ethereum.datasource.DbSettings;
import org.ethereum.datasource.DbSource;
import org.ethereum.datasource.MemSizeEstimator;
import org.ethereum.datasource.Source;
import org.ethereum.datasource.WriteCache;
import org.ethereum.datasource.XorDataSource;
import org.ethereum.db.BlockStore;
import org.ethereum.db.DbFlushManager;
import org.ethereum.db.TransactionStore;
import org.ethereum.facade.Ethereum;
import org.ethereum.manager.WorldManager;
import org.ethereum.sharding.manager.ShardingWorldManager;
import org.ethereum.sharding.processing.BeaconChain;
import org.ethereum.sharding.processing.BeaconChainFactory;
import org.ethereum.sharding.processing.db.BeaconStore;
import org.ethereum.sharding.processing.db.IndexedBeaconStore;
import org.ethereum.sharding.processing.state.BeaconStateRepository;
import org.ethereum.sharding.processing.state.StateRepository;
import org.ethereum.sharding.service.ValidatorRepositoryImpl;
import org.ethereum.sharding.service.ValidatorService;
import org.ethereum.sharding.crypto.DepositAuthority;
Expand All @@ -36,13 +50,17 @@
import org.ethereum.sharding.service.ValidatorRepository;
import org.ethereum.sharding.service.ValidatorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Collections;

/**
* In addition to {@link ShardingConfig} bootstraps beacon chain processing.
*
Expand All @@ -68,28 +86,34 @@ public class BeaconConfig {
@Autowired
DepositContractConfig depositContractConfig;

@Autowired
DbFlushManager dbFlushManager;

@Autowired
BlockStore blockStore;

@Autowired
TransactionStore txStore;

@Autowired
ShardingWorldManager shardingWorldManager;

@Autowired
SystemProperties systemProperties;

@Bean
public ValidatorConfig validatorConfig() {
return ValidatorConfig.fromFile();
}

@Bean
public ValidatorService validatorService() {
ValidatorService validatorService;
if (validatorConfig().isEnabled()) {
return new ValidatorServiceImpl(ethereum, dbFlushManager, validatorConfig(),
validatorService = new ValidatorServiceImpl(ethereum, validatorConfig(),
depositContract(), depositAuthority(), randao());
} else {
return new ValidatorService() {};
validatorService = new ValidatorService() {};
}
shardingWorldManager.setValidatorService(validatorService);
return validatorService;
}

@Bean
Expand All @@ -103,6 +127,73 @@ public DepositContract depositContract() {
depositContractConfig.getAbi());
}

@Bean
public BeaconStore beaconStore() {
Source<byte[], byte[]> blockSrc = cachedBeaconChainSource("beacon_block");
Source<byte[], byte[]> indexSrc = cachedBeaconChainSource("beacon_index");
return new IndexedBeaconStore(blockSrc, indexSrc);
}

@Bean
public StateRepository beaconStateRepository() {
Source<byte[], byte[]> src = cachedBeaconChainSource("beacon_state");
return new BeaconStateRepository(src);
}

@Bean
public BeaconChain beaconChain() {
BeaconChain beaconChain = BeaconChainFactory.create(
beaconDbFlusher(), beaconStore(), beaconStateRepository());
shardingWorldManager.setBeaconChain(beaconChain);
return beaconChain;
}

@Bean
@Scope("prototype")
public Source<byte[], byte[]> cachedBeaconChainSource(String name) {
AbstractCachedSource<byte[], byte[]> writeCache = new AsyncWriteCache<byte[], byte[]>(beaconChainSource(name)) {
@Override
protected WriteCache<byte[], byte[]> createCache(Source<byte[], byte[]> source) {
WriteCache.BytesKey<byte[]> ret = new WriteCache.BytesKey<>(source, WriteCache.CacheType.SIMPLE);
ret.withSizeEstimators(MemSizeEstimator.ByteArrayEstimator, MemSizeEstimator.ByteArrayEstimator);
ret.setFlushSource(true);
return ret;
}
}.withName(name);
beaconDbFlusher().addCache(writeCache);
return writeCache;
}

@Bean
@Scope("prototype")
public Source<byte[], byte[]> beaconChainSource(String name) {
return new XorDataSource<>(beaconChainDbCache(), HashUtil.sha3(name.getBytes()));
}

@Bean
public AbstractCachedSource<byte[], byte[]> beaconChainDbCache() {
WriteCache.BytesKey<byte[]> ret = new WriteCache.BytesKey<>(
new BatchSourceWriter<>(beaconChainDB()), WriteCache.CacheType.SIMPLE);
ret.setFlushSource(true);
return ret;
}

@Bean
public DbSource<byte[]> beaconChainDB() {
DbSettings settings = DbSettings.newInstance();
return commonConfig.keyValueDataSource("beaconchain", settings);
}

private DbFlushManager beaconDbFlusher;
public DbFlushManager beaconDbFlusher() {
if (beaconDbFlusher != null)
return beaconDbFlusher;

beaconDbFlusher = new DbFlushManager(systemProperties, Collections.emptySet(), beaconChainDbCache());
shardingWorldManager.setBeaconDbFlusher(beaconDbFlusher);
return beaconDbFlusher;
}

public DepositAuthority depositAuthority() {
return new UnsecuredDepositAuthority(validatorConfig());
}
Expand All @@ -112,7 +203,6 @@ public Randao randao() {
WriteCache.BytesKey<byte[]> cache = new WriteCache.BytesKey<>(
new BatchSourceWriter<>(src), WriteCache.CacheType.SIMPLE);
cache.setFlushSource(true);
dbFlushManager.addCache(cache);

return new Randao(cache);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.ethereum.manager.WorldManager;
import org.ethereum.sharding.manager.ShardingWorldManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
Expand Down Expand Up @@ -67,7 +68,7 @@ public class ShardingConfig {
DbFlushManager dbFlushManager;

@Bean
public WorldManager worldManager() {
public ShardingWorldManager worldManager() {
return new ShardingWorldManager(systemProperties, repository,
ethereumListener, blockchain, blockStore, depositContractConfig(), dbFlushManager);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public class DepositContract {
private static final byte[] DEPOSIT_WEI = convert(32, EtherUtil.Unit.ETHER).toByteArray();
private static final long GAS_LIMIT = 200_000;
private static final long DEFAULT_GAS_PRICE = convert(5, EtherUtil.Unit.GWEI).longValue();
private static final long DEPOSIT_TIMEOUT = 5; // 5 minutes
private static final long DEPOSIT_TIMEOUT = 15; // 15 minutes

private byte[] address;
private byte[] bin;
Expand Down
133 changes: 133 additions & 0 deletions ethereumj-core/src/main/java/org/ethereum/sharding/domain/Beacon.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright (c) [2016] [ <ether.camp> ]
* This file is part of the ethereumJ library.
*
* The ethereumJ library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The ethereumJ library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ethereum.sharding.domain;

import org.ethereum.datasource.Serializer;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.FastByteComparisons;
import org.ethereum.util.RLP;
import org.ethereum.util.RLPList;
import org.spongycastle.util.encoders.Hex;

import java.math.BigInteger;

import static org.ethereum.crypto.HashUtil.blake2b;

/**
* Beacon chain block structure.
*
* @author Mikhail Kalinin
* @since 14.08.2018
*/
public class Beacon {

/* Hash of the parent block */
private byte[] parentHash;
/* Randao commitment reveal */
private byte[] randaoReveal;
/* Reference to main chain block */
private byte[] mainChainRef;
/* Hash of the state */
private byte[] stateHash;
/* Slot number */
private long slotNumber;

public Beacon(byte[] parentHash, byte[] randaoReveal, byte[] mainChainRef, byte[] stateHash, long slotNumber) {
this.parentHash = parentHash;
this.randaoReveal = randaoReveal;
this.mainChainRef = mainChainRef;
this.stateHash = stateHash;
this.slotNumber = slotNumber;
}

public Beacon(byte[] rlp) {
RLPList items = RLP.unwrapList(rlp);
this.parentHash = items.get(0).getRLPData();
this.randaoReveal = items.get(1).getRLPData();
this.mainChainRef = items.get(2).getRLPData();
this.stateHash = items.get(3).getRLPData();
this.slotNumber = ByteUtil.bytesToBigInteger(items.get(4).getRLPData()).longValue();
}

public byte[] getEncoded() {
return RLP.wrapList(parentHash, randaoReveal, mainChainRef, stateHash,
BigInteger.valueOf(slotNumber).toByteArray());
}

public byte[] getHash() {
return blake2b(getEncoded());
}

public byte[] getParentHash() {
return parentHash;
}

public byte[] getRandaoReveal() {
return randaoReveal;
}

public byte[] getMainChainRef() {
return mainChainRef;
}

public byte[] getStateHash() {
return stateHash;
}

public long getSlotNumber() {
return slotNumber;
}

public boolean isParentOf(Beacon other) {
return FastByteComparisons.equal(this.getParentHash(), other.getHash());
}

public void setStateHash(byte[] stateHash) {
this.stateHash = stateHash;
}

@Override
public boolean equals(Object other) {
if (this == other) return true;
if (!(other instanceof Beacon)) return false;

return FastByteComparisons.equal(this.getHash(), ((Beacon) other).getHash());
}

@Override
public String toString() {
return "#" + getSlotNumber() + " (" + Hex.toHexString(getHash()).substring(0,6) + " <~ "
+ Hex.toHexString(getParentHash()).substring(0,6) + ")";
}

public boolean isGenesis() {
return this.slotNumber == 0L;
}

public static final Serializer<Beacon, byte[]> Serializer = new Serializer<Beacon, byte[]>() {
@Override
public byte[] serialize(Beacon block) {
return block == null ? null : block.getEncoded();
}

@Override
public Beacon deserialize(byte[] stream) {
return stream == null ? null : new Beacon(stream);
}
};
}
Loading

0 comments on commit 3dcd158

Please sign in to comment.