From 95a6c5ad78271c9092aba2c049046245ccb0406f Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Thu, 15 Aug 2019 18:02:16 +0600 Subject: [PATCH 1/2] Avoid unnecessary merklisation of initial deposits --- .../consensus/spec/GenesisFunction.java | 20 ++++++++----------- .../InitialStateTransitionTest.java | 2 +- .../beacon/pow/AbstractDepositContract.java | 14 ++++++++----- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/GenesisFunction.java b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/GenesisFunction.java index 540c2720c..88c7af293 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/GenesisFunction.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/GenesisFunction.java @@ -55,18 +55,14 @@ default BeaconState initialize_beacon_state_from_eth1( state.setLatestBlockHeader(get_block_header(get_empty_block())); // Process deposits - for (int index = 0; index < deposits.size(); index++) { - Deposit deposit = deposits.get(index); - ReadList deposit_data_list = - ReadList.wrap( - deposits.stream().map(Deposit::getData).limit(index + 1).collect(Collectors.toList()), - Integer::new, - 1L << getConstants().getDepositContractTreeDepth().getIntValue()); - state.setEth1Data(new Eth1Data( - hash_tree_root(deposit_data_list), UInt64.valueOf(deposits.size()), eth1_block_hash)); - verify_deposit(state, deposit); - process_deposit(state, deposit); - } + ReadList deposit_data_list = + ReadList.wrap( + deposits.stream().map(Deposit::getData).collect(Collectors.toList()), + Integer::new, + 1L << getConstants().getDepositContractTreeDepth().getIntValue()); + state.setEth1Data(new Eth1Data( + hash_tree_root(deposit_data_list), UInt64.valueOf(deposits.size()), eth1_block_hash)); + deposits.forEach(deposit -> process_deposit(state, deposit)); // Process activations for (ValidatorIndex index : state.getValidators().size().iterateFromZero()) { diff --git a/consensus/src/test/java/org/ethereum/beacon/consensus/transition/InitialStateTransitionTest.java b/consensus/src/test/java/org/ethereum/beacon/consensus/transition/InitialStateTransitionTest.java index 4aff42278..dd0f5410d 100644 --- a/consensus/src/test/java/org/ethereum/beacon/consensus/transition/InitialStateTransitionTest.java +++ b/consensus/src/test/java/org/ethereum/beacon/consensus/transition/InitialStateTransitionTest.java @@ -48,6 +48,6 @@ public void handleChainStartCorrectly() { .plus(spec.getConstants().getSecondsPerDay().times(2)); assertThat(initialState.getGenesisTime()).isEqualTo(expectedTime); - assertThat(initialState.getEth1Data()).isEqualTo(Eth1Data.EMPTY); + assertThat(initialState.getEth1Data()).isEqualTo(eth1Data); } } diff --git a/pow/core/src/main/java/org/ethereum/beacon/pow/AbstractDepositContract.java b/pow/core/src/main/java/org/ethereum/beacon/pow/AbstractDepositContract.java index f898b771a..824b4fdad 100644 --- a/pow/core/src/main/java/org/ethereum/beacon/pow/AbstractDepositContract.java +++ b/pow/core/src/main/java/org/ethereum/beacon/pow/AbstractDepositContract.java @@ -100,12 +100,16 @@ protected synchronized void newDeposits(List eventDataList, by } private void tryChainStart(byte[] blockHash, long blockTimestamp) { + // use fake proof for initial deposits to avoid of unnecessary merklizing + List fakeProof = + Collections.nCopies( + spec.getConstants().getDepositContractTreeDepthPlusOne().getIntValue(), Hash32.ZERO); // instantiate initial deposits - List genesisDeposits = new ArrayList<>(); - for (int i = 0; i < initialDeposits.size(); i++) { - genesisDeposits.add( - Deposit.create(tree.getProof(i, initialDeposits.size()), initialDeposits.get(i))); - } + List genesisDeposits = + initialDeposits.stream() + .map(data -> Deposit.create(fakeProof, data)) + .collect(Collectors.toList()); + try { // check if genesis conditions met Eth1Data genesisEth1Data = From 97ca367fa8d29290875b6b83de6d00ec78020165 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Fri, 16 Aug 2019 13:29:21 +0600 Subject: [PATCH 2/2] Put a comment on why initial deposits are not verified --- .../org/ethereum/beacon/consensus/spec/GenesisFunction.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/GenesisFunction.java b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/GenesisFunction.java index 88c7af293..286d7a603 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/GenesisFunction.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/GenesisFunction.java @@ -62,6 +62,11 @@ default BeaconState initialize_beacon_state_from_eth1( 1L << getConstants().getDepositContractTreeDepth().getIntValue()); state.setEth1Data(new Eth1Data( hash_tree_root(deposit_data_list), UInt64.valueOf(deposits.size()), eth1_block_hash)); + + // according to the spec deposits are verified before processing + // but this is redundant for genesis initialisation + // since passed deposits are created by our own code + // hence, we are able to avoid verification which saves us some computational resources deposits.forEach(deposit -> process_deposit(state, deposit)); // Process activations