Skip to content

Commit

Permalink
Merge 6253e26 into 2e07679
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalinin committed Sep 12, 2018
2 parents 2e07679 + 6253e26 commit 3b6f0c0
Show file tree
Hide file tree
Showing 44 changed files with 1,931 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import org.ethereum.db.TransactionStore;
import org.ethereum.facade.Ethereum;
import org.ethereum.manager.WorldManager;
import org.ethereum.sharding.processing.db.TrieValidatorSet;
import org.ethereum.sharding.processing.db.ValidatorSet;
import org.ethereum.sharding.pubsub.Publisher;
import org.ethereum.sharding.manager.ShardingWorldManager;
import org.ethereum.sharding.processing.BeaconChain;
Expand Down Expand Up @@ -156,13 +158,15 @@ public BeaconStore beaconStore() {
@Bean
public StateRepository beaconStateRepository() {
Source<byte[], byte[]> src = cachedBeaconChainSource("beacon_state");
return new BeaconStateRepository(src);
Source<byte[], byte[]> validatorSrc = cachedBeaconChainSource("validator_set");
Source<byte[], byte[]> crystallizedSrc = cachedBeaconChainSource("crystallized_state");
return new BeaconStateRepository(src, crystallizedSrc, validatorSrc);
}

@Bean
public BeaconChain beaconChain() {
BeaconChain beaconChain = BeaconChainFactory.create(
beaconDbFlusher(), beaconStore(), beaconStateRepository());
BeaconChain beaconChain = BeaconChainFactory.create(beaconDbFlusher(), beaconStore(),
beaconStateRepository(), validatorRepository(), blockStore.getBestBlock());
shardingWorldManager.setBeaconChain(beaconChain);
return beaconChain;
}
Expand Down Expand Up @@ -213,7 +217,7 @@ public Publisher publisher() {
@Bean
public BeaconProposer beaconProposer() {
return new BeaconProposerImpl(ethereum, publisher(), randao(), beaconStateRepository(),
BeaconChainFactory.stateTransition());
BeaconChainFactory.stateTransition(validatorRepository()));
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.ethereum.listener.RecommendedGasPriceTracker;
import org.ethereum.sharding.crypto.DepositAuthority;
import org.ethereum.sharding.domain.Validator;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.FastByteComparisons;
import org.ethereum.util.Futures;
import org.ethereum.util.blockchain.EtherUtil;
Expand All @@ -43,7 +44,9 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import static org.ethereum.util.ByteUtil.bigIntegerToBytes;
import static org.ethereum.util.ByteUtil.longToBytes;
import static org.ethereum.util.ByteUtil.longToBytesNoLeadZeroes;
import static org.ethereum.util.blockchain.EtherUtil.convert;

/**
Expand All @@ -67,7 +70,7 @@ public class DepositContract {

private static final Logger logger = LoggerFactory.getLogger("beacon");

private static final byte[] DEPOSIT_WEI = convert(32, EtherUtil.Unit.ETHER).toByteArray();
private static final byte[] DEPOSIT_WEI = bigIntegerToBytes(convert(32, EtherUtil.Unit.ETHER));
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 = 15; // 15 minutes
Expand Down Expand Up @@ -141,8 +144,8 @@ public Transaction depositTx(final byte[] pubKey, long withdrawalShard, byte[] w
BigInteger nonce = ethereum.getRepository().getNonce(authority.address());
long gasPrice = gasPriceTracker.getRecommendedGasPrice();
Integer chainId = ethereum.getChainIdForNextBlock();
Transaction tx = new Transaction(nonce.toByteArray(), longToBytes(gasPrice), longToBytes(GAS_LIMIT),
address, DEPOSIT_WEI, data, chainId);
Transaction tx = new Transaction(bigIntegerToBytes(nonce), longToBytesNoLeadZeroes(gasPrice),
longToBytesNoLeadZeroes(GAS_LIMIT), address, DEPOSIT_WEI, data, chainId);
authority.sign(tx);
return tx;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,21 @@
*/
package org.ethereum.sharding.domain;

import org.ethereum.sharding.processing.state.BeaconState;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.io.ByteStreams;
import org.ethereum.util.Utils;

import java.io.InputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import static org.ethereum.util.Utils.parseHex;

/**
* A special beacon chain block that is the first block of the chain.
Expand All @@ -35,24 +47,25 @@ public class BeaconGenesis extends Beacon {

private static BeaconGenesis instance;

// stub for proposer, 08/28/2018 @ 11:13am (UTC)
private long timestamp = 1535454832000L;
/* Genesis timestamp, a source of slot's time frames */
private long timestamp = 0L;
/* A list of public keys that identifies participants of initial active validator set */
private List<String> initialValidators = new ArrayList<>();

private BeaconGenesis() {
super(EMPTY, EMPTY, EMPTY, EMPTY, SLOT);
setStateHash(getState().getHash());
BeaconGenesis(Json json) {
super(json.parentHash(), json.randaoReveal(), json.mainChainRef(), EMPTY, SLOT);
this.timestamp = json.timestamp();
this.initialValidators = json.validatorSet();
}

public static BeaconGenesis instance() {
if (instance == null)
instance = new BeaconGenesis();
if (instance == null) {
Json json = Json.fromResource("beacon-genesis.json");
instance = new BeaconGenesis(json);
}
return instance;
}

public BeaconState getState() {
return new BeaconState();
}

public BigInteger getScore() {
return BigInteger.ZERO;
}
Expand All @@ -61,8 +74,69 @@ public long getTimestamp() {
return timestamp;
}

public List<String> getInitialValidators() {
return initialValidators;
}

@Override
public String toString() {
return super.toString() + ", timestamp: " + timestamp;
}

@JsonSerialize
static class Json {
String parentHash;
String randaoReveal;
String mainChainRef;
long timestamp;
String[] validatorSet;

byte[] parentHash() {
return parseHex(parentHash);
}

byte[] randaoReveal() {
return parseHex(randaoReveal);
}

byte[] mainChainRef() {
return parseHex(mainChainRef);
}

long timestamp() {
return timestamp * 1000; // seconds to millis
}

List<String> validatorSet() {
List<String> validators = new ArrayList<>(validatorSet.length);
for (String val : validatorSet) {
if ("0x".equals(val.substring(0, 2))) {
validators.add(val.substring(2));
} else {
validators.add(val);
}
}
return validators;
}

static Json fromResource(String resourceName) {
return fromStream(Json.class.getClassLoader().getResourceAsStream(resourceName));
}

static Json fromStream(InputStream in) {
String json = null;
try {
json = new String(ByteStreams.toByteArray(in));
ObjectMapper mapper = new ObjectMapper()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

return mapper.readValue(json, Json.class);
} catch (Exception e) {
Utils.showErrorAndExit("Failed to parse beacon chain genesis: " + e.getMessage(), json);
throw new RuntimeException(e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,15 @@
*/
package org.ethereum.sharding.domain;

import org.ethereum.datasource.Serializer;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.RLP;
import org.ethereum.util.RLPList;

import java.math.BigInteger;

/**
* Represents and item of a list of validators held by validator registration contract.
* Represents an item of a list of validators held by validator registration contract.
*
* @author Mikhail Kalinin
* @since 21.07.2018
Expand All @@ -30,7 +37,13 @@ public class Validator {
private byte[] withdrawalAddress;
private byte[] randao;

private Validator() {
public Validator(byte[] encoded) {
RLPList list = RLP.unwrapList(encoded);

this.pubKey = list.get(0).getRLPData();
this.withdrawalShard = ByteUtil.bytesToBigInteger(list.get(1).getRLPData()).longValue();
this.withdrawalAddress = list.get(2).getRLPData();
this.randao = list.get(3).getRLPData();
}

public Validator(byte[] pubKey, long withdrawalShard, byte[] withdrawalAddress, byte[] randao) {
Expand All @@ -40,6 +53,10 @@ public Validator(byte[] pubKey, long withdrawalShard, byte[] withdrawalAddress,
this.randao = randao;
}

public byte[] getEncoded() {
return RLP.wrapList(pubKey, BigInteger.valueOf(withdrawalShard).toByteArray(), withdrawalAddress, randao);
}

public byte[] getPubKey() {
return pubKey;
}
Expand All @@ -55,4 +72,16 @@ public byte[] getWithdrawalAddress() {
public byte[] getRandao() {
return randao;
}

public static final Serializer<Validator, byte[]> Serializer = new Serializer<Validator, byte[]>() {
@Override
public byte[] serialize(Validator validator) {
return validator.getEncoded();
}

@Override
public Validator deserialize(byte[] stream) {
return stream == null ? null : new Validator(stream);
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@
import org.ethereum.sharding.config.DepositContractConfig;
import org.ethereum.sharding.processing.BeaconChain;
import org.ethereum.sharding.proposer.ProposerService;
import org.ethereum.sharding.pubsub.BeaconChainSynced;
import org.ethereum.sharding.pubsub.Publisher;
import org.ethereum.sharding.pubsub.ValidatorStateUpdated;
import org.ethereum.sharding.service.ValidatorService;
import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigInteger;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -69,8 +69,10 @@ public class ShardingWorldManager extends WorldManager {
DbFlushManager dbFlushManager;
DbFlushManager beaconDbFlusher;
Publisher publisher;
ValidatorService validatorService;

private CompletableFuture<Void> contractInit = new CompletableFuture<>();
private CompletableFuture<ValidatorService.State> validatorServiceInit = new CompletableFuture<>();

public ShardingWorldManager(SystemProperties config, Repository repository, EthereumListener listener,
Blockchain blockchain, BlockStore blockStore, DepositContractConfig contractConfig,
Expand Down Expand Up @@ -128,19 +130,34 @@ public byte[] getContractAddress() {
}

public void setValidatorService(final ValidatorService validatorService) {
contractInit.thenRunAsync(validatorService::init);
this.validatorService = validatorService;
if (validatorService.getState() == ValidatorService.State.Disabled) {
validatorServiceInit.complete(ValidatorService.State.Disabled);
} else {
publisher.subscribe(ValidatorStateUpdated.class, data -> {
if (data.getNewState() == ValidatorService.State.Enlisted ||
data.getNewState() == ValidatorService.State.DepositFailed) {
validatorServiceInit.complete(data.getNewState());
}
});
}
contractInit.thenRunAsync(this.validatorService::init);
}

public void setProposerService(final ProposerService proposerService) {
publisher.subscribe(ValidatorStateUpdated.class, data -> {
if (data.getNewState() == ValidatorService.State.Enlisted) {
// start only if validator is enlisted and after sync is finished
publisher.subscribe(BeaconChainSynced.class, data -> {
if (validatorService.getState() == ValidatorService.State.Enlisted) {
proposerService.init();
}
});
}

public void setBeaconChain(final BeaconChain beaconChain) {
contractInit.thenRunAsync(beaconChain::init);
// PoC mode:
// wait for validator initialization
// it's needed to be sure that the validator is registered before beacon genesis state calculation
validatorServiceInit.runAfterBothAsync(contractInit, beaconChain::init);
}

public void setPublisher(Publisher publisher) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@
*/
package org.ethereum.sharding.processing;

import org.ethereum.core.Block;
import org.ethereum.db.DbFlushManager;
import org.ethereum.sharding.processing.consensus.BeaconStateTransition;
import org.ethereum.sharding.processing.consensus.GenesisTransition;
import org.ethereum.sharding.processing.consensus.NoTransition;
import org.ethereum.sharding.processing.consensus.NumberAsScore;
import org.ethereum.sharding.processing.consensus.ScoreFunction;
import org.ethereum.sharding.processing.consensus.StateTransition;
import org.ethereum.sharding.processing.db.BeaconStore;
import org.ethereum.sharding.processing.db.ValidatorSet;
import org.ethereum.sharding.processing.state.BeaconState;
import org.ethereum.sharding.processing.state.StateRepository;
import org.ethereum.sharding.processing.validation.BeaconValidator;
import org.ethereum.sharding.processing.validation.StateValidator;
import org.ethereum.sharding.service.ValidatorRepository;

/**
* A factory that creates {@link BeaconChain} instance.
Expand All @@ -39,21 +45,32 @@
*/
public class BeaconChainFactory {

private static StateTransition stateTransition;
private static StateTransition<BeaconState> stateTransition;

public static BeaconChain create(DbFlushManager beaconDbFlusher, BeaconStore store, StateRepository repository) {
public static BeaconChain create(DbFlushManager beaconDbFlusher, BeaconStore store,
StateRepository repository, StateTransition<BeaconState> genesisStateTransition,
StateTransition<BeaconState> stateTransitionFunction) {

BeaconValidator beaconValidator = new BeaconValidator(store);
StateValidator stateValidator = new StateValidator();
ScoreFunction scoreFunction = new NumberAsScore();

return new BeaconChainImpl(beaconDbFlusher, store, stateTransition(),
repository, beaconValidator, stateValidator, scoreFunction);
return new BeaconChainImpl(beaconDbFlusher, store, stateTransitionFunction,
repository, beaconValidator, stateValidator, scoreFunction, genesisStateTransition);
}

public static StateTransition stateTransition() {
public static BeaconChain create(DbFlushManager beaconDbFlusher, BeaconStore store, StateRepository repository,
ValidatorRepository validatorRepository, Block bestBlock) {

StateTransition<BeaconState> genesisStateTransition = new GenesisTransition(validatorRepository)
.withMainChainRef(bestBlock.getHash());

return create(beaconDbFlusher, store, repository, genesisStateTransition, stateTransition(validatorRepository));
}

public static StateTransition<BeaconState> stateTransition(ValidatorRepository validatorRepository) {
if (stateTransition == null)
stateTransition = new NoTransition();
stateTransition = new BeaconStateTransition(validatorRepository);
return stateTransition;
}
}

0 comments on commit 3b6f0c0

Please sign in to comment.