Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Ibft2: Replace NewRound with extended Proposal #872

Merged
merged 25 commits into from
Feb 20, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8835c56
Remove the NewRound message, and increase proposal
Feb 14, 2019
ed817e4
Merge branch 'master' into proposal_rcc
rain-on Feb 15, 2019
0ab30f0
Introduce FutureUtils to reduce duplicated code around CompletableFut…
ajsutton Feb 15, 2019
cdd7c95
Select new pivot block when world state becomes unavailable (#869)
ajsutton Feb 15, 2019
3791486
[PAN-2196] Implement world state cancel (#867)
mbaxter Feb 15, 2019
8fb9345
Added perm_reloadPermissionsFromFile
MadelineMurray Feb 18, 2019
5c23d61
[PAN-2270] Rename password hash command (#879)
lucassaldanha Feb 18, 2019
157bead
[PAN-2239] Disconnect peer removed from node whitelist (#877)
lucassaldanha Feb 18, 2019
48a0e45
More bootnodes for goerli (#880)
Errorific Feb 18, 2019
e60255f
[MINOR] Fixing file locations under docker (#885)
Errorific Feb 18, 2019
0bd2246
[PAN-2305] Detect stalled world state downloads (#875)
mbaxter Feb 18, 2019
bfbdd94
Ensure exceptions in suppliers passed to EthScheduler are propagated …
ajsutton Feb 18, 2019
c76ef70
Reduce logging noise from invalid peer discovery packets and handshak…
ajsutton Feb 18, 2019
7902ea7
Add metrics for EthScheduler executors (#878)
ajsutton Feb 18, 2019
8dd15c4
[NC-2058] Improve block propagation time (#808)
smatthewenglish Feb 18, 2019
9e0d4de
[NC-2046] websocket method permissions (#870)
macfarla Feb 18, 2019
597b511
Reorganize eth tasks (#890)
mbaxter Feb 18, 2019
706e319
[PAN-2313] Fix authentication header (#891)
lucassaldanha Feb 18, 2019
0087932
post review
Feb 18, 2019
59a39c3
repair tests
Feb 18, 2019
049ef66
Merge remote-tracking branch 'upstream/master' into proposal_rcc
Feb 19, 2019
b4e3dec
clean up merge
Feb 19, 2019
dfe900e
Merge remote-tracking branch 'upstream/master' into proposal_rcc
Feb 20, 2019
e0f08b1
rebased and working
Feb 20, 2019
3fce78f
Merge branch 'master' into proposal_rcc
rain-on Feb 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Select new pivot block when world state becomes unavailable (#869)
  • Loading branch information
ajsutton authored and tmohay committed Feb 18, 2019
commit cdd7c9554293088c7ea57633bc51af61f1cfad55
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ public static <C> Optional<FastSynchronizer<C>> create(
}

public CompletableFuture<FastSyncState> start() {
LOG.info("Fast sync enabled");
return fastSyncDownloader.start(initialSyncState);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
*/
package tech.pegasys.pantheon.ethereum.eth.sync.fastsync;

import static tech.pegasys.pantheon.util.FutureUtils.completedExceptionally;
import static tech.pegasys.pantheon.util.FutureUtils.exceptionallyCompose;

import tech.pegasys.pantheon.ethereum.eth.sync.worldstate.WorldStateDownloader;
import tech.pegasys.pantheon.ethereum.eth.sync.worldstate.WorldStateUnavailableException;
import tech.pegasys.pantheon.util.ExceptionUtils;

import java.util.concurrent.CompletableFuture;

Expand All @@ -35,13 +40,24 @@ public FastSyncDownloader(
}

public CompletableFuture<FastSyncState> start(final FastSyncState fastSyncState) {
LOG.info("Fast sync enabled");
return fastSyncActions
.waitForSuitablePeers(fastSyncState)
.thenCompose(fastSyncActions::selectPivotBlock)
.thenCompose(fastSyncActions::downloadPivotBlockHeader)
.thenApply(this::storeState)
.thenCompose(this::downloadChainAndWorldState);
return exceptionallyCompose(
fastSyncActions
.waitForSuitablePeers(fastSyncState)
.thenCompose(fastSyncActions::selectPivotBlock)
.thenCompose(fastSyncActions::downloadPivotBlockHeader)
.thenApply(this::storeState)
.thenCompose(this::downloadChainAndWorldState),
this::handleWorldStateUnavailable);
}

private CompletableFuture<FastSyncState> handleWorldStateUnavailable(final Throwable error) {
if (ExceptionUtils.rootCause(error) instanceof WorldStateUnavailableException) {
LOG.warn(
"Fast sync was unable to download the world state. Retrying with a new pivot block.");
return start(FastSyncState.EMPTY_SYNC_STATE);
} else {
return completedExceptionally(error);
}
}

private FastSyncState storeState(final FastSyncState state) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright 2019 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.ethereum.eth.sync.worldstate;

public class WorldStateUnavailableException extends RuntimeException {}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static java.util.concurrent.CompletableFuture.completedFuture;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
Expand All @@ -26,6 +27,7 @@
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.eth.sync.worldstate.WorldStateDownloader;
import tech.pegasys.pantheon.ethereum.eth.sync.worldstate.WorldStateUnavailableException;

import java.util.concurrent.CompletableFuture;

Expand Down Expand Up @@ -247,6 +249,66 @@ public void shouldNotConsiderFastSyncCompleteIfOnlyChainDownloadIsComplete() {
assertThat(result).isNotDone();
}

@SuppressWarnings("unchecked")
@Test
public void shouldResetFastSyncStateAndRestartProcessIfWorldStateIsUnavailable() {
final CompletableFuture<Void> firstWorldStateFuture = new CompletableFuture<>();
final CompletableFuture<Void> secondWorldStateFuture = new CompletableFuture<>();
final CompletableFuture<FastSyncState> chainFuture = new CompletableFuture<>();
final FastSyncState selectPivotBlockState = new FastSyncState(50);
final FastSyncState secondSelectPivotBlockState = new FastSyncState(90);
final BlockHeader pivotBlockHeader = new BlockHeaderTestFixture().number(50).buildHeader();
final BlockHeader secondPivotBlockHeader =
new BlockHeaderTestFixture().number(90).buildHeader();
final FastSyncState downloadPivotBlockHeaderState = new FastSyncState(pivotBlockHeader);
final FastSyncState secondDownloadPivotBlockHeaderState =
new FastSyncState(secondPivotBlockHeader);
// First attempt
when(fastSyncActions.waitForSuitablePeers(EMPTY_SYNC_STATE)).thenReturn(COMPLETE);
when(fastSyncActions.selectPivotBlock(EMPTY_SYNC_STATE))
.thenReturn(
completedFuture(selectPivotBlockState), completedFuture(secondSelectPivotBlockState));
when(fastSyncActions.downloadPivotBlockHeader(selectPivotBlockState))
.thenReturn(completedFuture(downloadPivotBlockHeaderState));
when(fastSyncActions.downloadChain(downloadPivotBlockHeaderState)).thenReturn(chainFuture);
when(worldStateDownloader.run(pivotBlockHeader)).thenReturn(firstWorldStateFuture);

// Second attempt with new pivot block
when(fastSyncActions.downloadPivotBlockHeader(secondSelectPivotBlockState))
.thenReturn(completedFuture(secondDownloadPivotBlockHeaderState));
when(fastSyncActions.downloadChain(secondDownloadPivotBlockHeaderState))
.thenReturn(completedFuture(secondDownloadPivotBlockHeaderState));
when(worldStateDownloader.run(secondPivotBlockHeader)).thenReturn(secondWorldStateFuture);

final CompletableFuture<FastSyncState> result = downloader.start(EMPTY_SYNC_STATE);

verify(fastSyncActions).waitForSuitablePeers(EMPTY_SYNC_STATE);
verify(fastSyncActions).selectPivotBlock(EMPTY_SYNC_STATE);
verify(fastSyncActions).downloadPivotBlockHeader(selectPivotBlockState);
verify(storage).storeState(downloadPivotBlockHeaderState);
verify(fastSyncActions).downloadChain(downloadPivotBlockHeaderState);
verify(worldStateDownloader).run(pivotBlockHeader);
verifyNoMoreInteractions(fastSyncActions, worldStateDownloader, storage);

assertThat(result).isNotDone();

firstWorldStateFuture.completeExceptionally(new WorldStateUnavailableException());
assertThat(result).isNotDone();
assertThat(chainFuture).isCancelled();

verify(fastSyncActions, times(2)).waitForSuitablePeers(EMPTY_SYNC_STATE);
verify(fastSyncActions, times(2)).selectPivotBlock(EMPTY_SYNC_STATE);
verify(fastSyncActions).downloadPivotBlockHeader(secondSelectPivotBlockState);
verify(storage).storeState(secondDownloadPivotBlockHeaderState);
verify(fastSyncActions).downloadChain(secondDownloadPivotBlockHeaderState);
verify(worldStateDownloader).run(secondPivotBlockHeader);
verifyNoMoreInteractions(fastSyncActions, worldStateDownloader, storage);

secondWorldStateFuture.complete(null);

assertThat(result).isCompletedWithValue(secondDownloadPivotBlockHeaderState);
}

private <T> CompletableFuture<T> completedExceptionally(final Throwable error) {
final CompletableFuture<T> result = new CompletableFuture<>();
result.completeExceptionally(error);
Expand Down