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

Commit

Permalink
Use header validation mode for ommers (#1313)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajsutton authored Apr 23, 2019
1 parent 9aa9c7c commit 80d9af3
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ boolean fastBlockValidation(
final ProtocolContext<C> context,
final Block block,
final List<TransactionReceipt> receipts,
final HeaderValidationMode headerValidationMode);
final HeaderValidationMode headerValidationMode,
final HeaderValidationMode ommerValidationMode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ public boolean fastBlockValidation(
final ProtocolContext<C> context,
final Block block,
final List<TransactionReceipt> receipts,
final HeaderValidationMode headerValidationMode) {
final HeaderValidationMode headerValidationMode,
final HeaderValidationMode ommerValidationMode) {
final BlockHeader header = block.getHeader();
if (!blockHeaderValidator.validateHeader(header, context, headerValidationMode)) {
return false;
}

if (!blockBodyValidator.validateBodyLight(
context, block, receipts, HeaderValidationMode.FULL)) {
if (!blockBodyValidator.validateBodyLight(context, block, receipts, ommerValidationMode)) {
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@ boolean importBlock(
* @param block The block
* @param receipts The receipts associated with this block.
* @param headerValidationMode Determines the validation to perform on this header.
* @param ommerValidationMode Determines the validation to perform on ommer headers.
* @return {@code true} if the block was added somewhere in the blockchain; otherwise {@code
* false}
*/
boolean fastImportBlock(
ProtocolContext<C> context,
Block block,
List<TransactionReceipt> receipts,
HeaderValidationMode headerValidationMode);
HeaderValidationMode headerValidationMode,
HeaderValidationMode ommerValidationMode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,9 @@ public enum HeaderValidationMode {
SKIP_DETACHED,

/** Fully validate the header */
FULL
FULL;

public boolean isFormOfLightValidation() {
return this == LIGHT || this == LIGHT_DETACHED_ONLY || this == LIGHT_SKIP_DETACHED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,15 @@ private boolean isOmmerValid(
return false;
}

if (!ommerValidationMode.isFormOfLightValidation()) {
return isOmmerSiblingOfAncestor(context, current, ommer);
} else {
return true;
}
}

private boolean isOmmerSiblingOfAncestor(
final ProtocolContext<C> context, final BlockHeader current, final BlockHeader ommer) {
// The current block is guaranteed to have a parent because it's a valid header.
final long lastAncestorBlockNumber = Math.max(current.getNumber() - MAX_GENERATION, 0);

Expand All @@ -236,7 +245,6 @@ private boolean isOmmerValid(
}
previous = ancestor;
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ public boolean fastImportBlock(
final ProtocolContext<C> context,
final Block block,
final List<TransactionReceipt> receipts,
final HeaderValidationMode headerValidationMode) {
final HeaderValidationMode headerValidationMode,
final HeaderValidationMode ommerValidationMode) {

if (blockValidator.fastBlockValidation(context, block, receipts, headerValidationMode)) {
if (blockValidator.fastBlockValidation(
context, block, receipts, headerValidationMode, ommerValidationMode)) {
context.getBlockchain().appendBlock(block, receipts);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,18 @@ public class FastImportBlocksStep<C> implements Consumer<List<BlockWithReceipts>
private static final Logger LOG = LogManager.getLogger();
private final ProtocolSchedule<C> protocolSchedule;
private final ProtocolContext<C> protocolContext;
private final ValidationPolicy validationPolicy;
private final ValidationPolicy headerValidationPolicy;
private final ValidationPolicy ommerValidationPolicy;

public FastImportBlocksStep(
final ProtocolSchedule<C> protocolSchedule,
final ProtocolContext<C> protocolContext,
final ValidationPolicy validationPolicy) {
final ValidationPolicy headerValidationPolicy,
final ValidationPolicy ommerValidationPolicy) {
this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext;
this.validationPolicy = validationPolicy;
this.headerValidationPolicy = headerValidationPolicy;
this.ommerValidationPolicy = ommerValidationPolicy;
}

@Override
Expand All @@ -61,6 +64,7 @@ private boolean importBlock(final BlockWithReceipts blockWithReceipts) {
protocolContext,
blockWithReceipts.getBlock(),
blockWithReceipts.getReceipts(),
validationPolicy.getValidationModeForNextBlock());
headerValidationPolicy.getValidationModeForNextBlock(),
ommerValidationPolicy.getValidationModeForNextBlock());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,22 @@ public class FastSyncBlockHandler<C> implements BlockHandler<BlockWithReceipts>
private final ProtocolContext<C> protocolContext;
private final EthContext ethContext;
private final MetricsSystem metricsSystem;
private final ValidationPolicy validationPolicy;
private final ValidationPolicy headerValidationPolicy;
private final ValidationPolicy ommerValidationPolicy;

public FastSyncBlockHandler(
final ProtocolSchedule<C> protocolSchedule,
final ProtocolContext<C> protocolContext,
final EthContext ethContext,
final MetricsSystem metricsSystem,
final ValidationPolicy validationPolicy) {
final ValidationPolicy headerValidationPolicy,
final ValidationPolicy ommerValidationPolicy) {
this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext;
this.ethContext = ethContext;
this.metricsSystem = metricsSystem;
this.validationPolicy = validationPolicy;
this.headerValidationPolicy = headerValidationPolicy;
this.ommerValidationPolicy = ommerValidationPolicy;
}

@Override
Expand Down Expand Up @@ -105,7 +108,8 @@ public CompletableFuture<List<BlockWithReceipts>> validateAndImportBlocks(
protocolContext,
block,
blockWithReceipt.getReceipts(),
validationPolicy.getValidationModeForNextBlock())) {
headerValidationPolicy.getValidationModeForNextBlock(),
ommerValidationPolicy.getValidationModeForNextBlock())) {
return invalidBlockFailure(block);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ public CompletableFuture<List<Hash>> importBlocksForCheckpoints(
HeaderValidationMode.LIGHT_SKIP_DETACHED,
HeaderValidationMode.SKIP_DETACHED,
fastSyncValidationCounter);
final FastSyncValidationPolicy ommerValidationPolicy =
new FastSyncValidationPolicy(
config.fastSyncFullValidationRate(),
HeaderValidationMode.LIGHT,
HeaderValidationMode.FULL,
fastSyncValidationCounter);
final FastSyncValidationPolicy detatchedValidationPolicy =
new FastSyncValidationPolicy(
config.fastSyncFullValidationRate(),
Expand All @@ -89,7 +95,8 @@ public CompletableFuture<List<Hash>> importBlocksForCheckpoints(
protocolContext,
ethContext,
metricsSystem,
attachedValidationPolicy),
attachedValidationPolicy,
ommerValidationPolicy),
detatchedValidationPolicy,
checkpointHeaders,
metricsSystem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
package tech.pegasys.pantheon.ethereum.eth.sync.fastsync;

import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.DETACHED_ONLY;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.FULL;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.LIGHT;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.LIGHT_DETACHED_ONLY;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.LIGHT_SKIP_DETACHED;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.SKIP_DETACHED;
Expand Down Expand Up @@ -48,6 +50,7 @@ public class FastSyncDownloadPipelineFactory<C> implements DownloadPipelineFacto
private final MetricsSystem metricsSystem;
private final FastSyncValidationPolicy attachedValidationPolicy;
private final FastSyncValidationPolicy detachedValidationPolicy;
private final FastSyncValidationPolicy ommerValidationPolicy;

public FastSyncDownloadPipelineFactory(
final SynchronizerConfiguration syncConfig,
Expand All @@ -74,6 +77,9 @@ public FastSyncDownloadPipelineFactory(
LIGHT_SKIP_DETACHED,
SKIP_DETACHED,
fastSyncValidationCounter);
ommerValidationPolicy =
new FastSyncValidationPolicy(
this.syncConfig.fastSyncFullValidationRate(), LIGHT, FULL, fastSyncValidationCounter);
detachedValidationPolicy =
new FastSyncValidationPolicy(
this.syncConfig.fastSyncFullValidationRate(),
Expand Down Expand Up @@ -116,7 +122,8 @@ public Pipeline<?> createDownloadPipelineForSyncTarget(final SyncTarget target)
final DownloadReceiptsStep downloadReceiptsStep =
new DownloadReceiptsStep(ethContext, metricsSystem);
final FastImportBlocksStep<C> importBlockStep =
new FastImportBlocksStep<>(protocolSchedule, protocolContext, attachedValidationPolicy);
new FastImportBlocksStep<>(
protocolSchedule, protocolContext, attachedValidationPolicy, ommerValidationPolicy);

return PipelineBuilder.createPipelineFrom(
"fetchCheckpoints",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.FULL;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.LIGHT;

import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.core.Block;
Expand All @@ -46,6 +47,7 @@ public class FastImportBlocksStepTest {
@Mock private ProtocolContext<Void> protocolContext;
@Mock private BlockImporter<Void> blockImporter;
@Mock private ValidationPolicy validationPolicy;
@Mock private ValidationPolicy ommerValidationPolicy;
private final BlockDataGenerator gen = new BlockDataGenerator();

private FastImportBlocksStep<Void> importBlocksStep;
Expand All @@ -55,9 +57,11 @@ public void setUp() {
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(protocolSpec);
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
when(validationPolicy.getValidationModeForNextBlock()).thenReturn(FULL);
when(ommerValidationPolicy.getValidationModeForNextBlock()).thenReturn(LIGHT);

importBlocksStep =
new FastImportBlocksStep<>(protocolSchedule, protocolContext, validationPolicy);
new FastImportBlocksStep<>(
protocolSchedule, protocolContext, validationPolicy, ommerValidationPolicy);
}

@Test
Expand All @@ -70,7 +74,11 @@ public void shouldImportBlocks() {

for (final BlockWithReceipts blockWithReceipts : blocksWithReceipts) {
when(blockImporter.fastImportBlock(
protocolContext, blockWithReceipts.getBlock(), blockWithReceipts.getReceipts(), FULL))
protocolContext,
blockWithReceipts.getBlock(),
blockWithReceipts.getReceipts(),
FULL,
LIGHT))
.thenReturn(true);
}
importBlocksStep.accept(blocksWithReceipts);
Expand All @@ -87,7 +95,7 @@ public void shouldThrowExceptionWhenValidationFails() {
final BlockWithReceipts blockWithReceipts = new BlockWithReceipts(block, gen.receipts(block));

when(blockImporter.fastImportBlock(
protocolContext, block, blockWithReceipts.getReceipts(), FULL))
protocolContext, block, blockWithReceipts.getReceipts(), FULL, LIGHT))
.thenReturn(false);
assertThatThrownBy(() -> importBlocksStep.accept(singletonList(blockWithReceipts)))
.isInstanceOf(InvalidBlockException.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.LIGHT;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.LIGHT_SKIP_DETACHED;

import tech.pegasys.pantheon.ethereum.ProtocolContext;
Expand Down Expand Up @@ -60,6 +61,7 @@ public class FastSyncBlockHandlerTest {
private static final Block BLOCK3 =
new Block(new BlockHeaderTestFixture().number(3).buildHeader(), EMPTY_BODY);
private static final HeaderValidationMode VALIDATION_MODE = LIGHT_SKIP_DETACHED;
private static final HeaderValidationMode OMMER_VALIDATION_MODE = LIGHT;

@SuppressWarnings("unchecked")
private final ProtocolSchedule<Void> protocolSchedule = mock(ProtocolSchedule.class);
Expand All @@ -82,16 +84,23 @@ public class FastSyncBlockHandlerTest {
new DeterministicEthScheduler());
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
private final ValidationPolicy validationPolicy = mock(ValidationPolicy.class);
private final ValidationPolicy ommerValidationPolicy = mock(ValidationPolicy.class);

private final FastSyncBlockHandler<Void> blockHandler =
new FastSyncBlockHandler<>(
protocolSchedule, protocolContext, ethContext, metricsSystem, validationPolicy);
protocolSchedule,
protocolContext,
ethContext,
metricsSystem,
validationPolicy,
ommerValidationPolicy);

@Before
public void setUp() {
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(protocolSpec);
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
when(validationPolicy.getValidationModeForNextBlock()).thenReturn(VALIDATION_MODE);
when(ommerValidationPolicy.getValidationModeForNextBlock()).thenReturn(OMMER_VALIDATION_MODE);
}

@After
Expand All @@ -101,7 +110,8 @@ public void checkWorldStateIsUnused() {

@Test
public void shouldFastImportBlocks() {
when(blockImporter.fastImportBlock(protocolContext, BLOCK, emptyList(), VALIDATION_MODE))
when(blockImporter.fastImportBlock(
protocolContext, BLOCK, emptyList(), VALIDATION_MODE, OMMER_VALIDATION_MODE))
.thenReturn(true);
final List<BlockWithReceipts> blocksWithReceipts =
singletonList(new BlockWithReceipts(BLOCK, emptyList()));
Expand All @@ -110,12 +120,15 @@ public void shouldFastImportBlocks() {
blockHandler.validateAndImportBlocks(blocksWithReceipts);

assertThat(result).isCompleted();
verify(blockImporter).fastImportBlock(protocolContext, BLOCK, emptyList(), VALIDATION_MODE);
verify(blockImporter)
.fastImportBlock(
protocolContext, BLOCK, emptyList(), VALIDATION_MODE, OMMER_VALIDATION_MODE);
}

@Test
public void shouldReturnExceptionallyCompletedFutureWhenBlockImportFails() {
when(blockImporter.fastImportBlock(protocolContext, BLOCK, emptyList(), VALIDATION_MODE))
when(blockImporter.fastImportBlock(
protocolContext, BLOCK, emptyList(), VALIDATION_MODE, OMMER_VALIDATION_MODE))
.thenReturn(false);

final CompletableFuture<List<BlockWithReceipts>> result =
Expand All @@ -127,9 +140,11 @@ public void shouldReturnExceptionallyCompletedFutureWhenBlockImportFails() {

@Test
public void shouldNotContinueImportingBlocksAfterValidationFailure() {
when(blockImporter.fastImportBlock(protocolContext, BLOCK, emptyList(), VALIDATION_MODE))
when(blockImporter.fastImportBlock(
protocolContext, BLOCK, emptyList(), VALIDATION_MODE, OMMER_VALIDATION_MODE))
.thenReturn(true);
when(blockImporter.fastImportBlock(protocolContext, BLOCK2, emptyList(), VALIDATION_MODE))
when(blockImporter.fastImportBlock(
protocolContext, BLOCK2, emptyList(), VALIDATION_MODE, OMMER_VALIDATION_MODE))
.thenReturn(false);

final CompletableFuture<List<BlockWithReceipts>> result =
Expand All @@ -141,9 +156,14 @@ public void shouldNotContinueImportingBlocksAfterValidationFailure() {

assertThat(result).isCompletedExceptionally();

verify(blockImporter).fastImportBlock(protocolContext, BLOCK, emptyList(), VALIDATION_MODE);
verify(blockImporter).fastImportBlock(protocolContext, BLOCK2, emptyList(), VALIDATION_MODE);
verify(blockImporter)
.fastImportBlock(
protocolContext, BLOCK, emptyList(), VALIDATION_MODE, OMMER_VALIDATION_MODE);
verify(blockImporter)
.fastImportBlock(
protocolContext, BLOCK2, emptyList(), VALIDATION_MODE, OMMER_VALIDATION_MODE);
verify(blockImporter, never())
.fastImportBlock(protocolContext, BLOCK3, emptyList(), VALIDATION_MODE);
.fastImportBlock(
protocolContext, BLOCK3, emptyList(), VALIDATION_MODE, OMMER_VALIDATION_MODE);
}
}

0 comments on commit 80d9af3

Please sign in to comment.