Use header validation mode for ommers (#1313)

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Adrian Sutton 6 years ago committed by GitHub
parent 8ed882a517
commit d5da0eb47b
  1. 3
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/BlockValidator.java
  2. 6
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/MainnetBlockValidator.java
  3. 4
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/core/BlockImporter.java
  4. 6
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/HeaderValidationMode.java
  5. 10
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockBodyValidator.java
  6. 6
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockImporter.java
  7. 12
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/fastsync/FastImportBlocksStep.java
  8. 12
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/fastsync/FastSyncBlockHandler.java
  9. 9
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/fastsync/FastSyncBlockImportTaskFactory.java
  10. 9
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java
  11. 14
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/fastsync/FastImportBlocksStepTest.java
  12. 38
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/fastsync/FastSyncBlockHandlerTest.java

@ -43,5 +43,6 @@ public interface BlockValidator<C> {
final ProtocolContext<C> context,
final Block block,
final List<TransactionReceipt> receipts,
final HeaderValidationMode headerValidationMode);
final HeaderValidationMode headerValidationMode,
final HeaderValidationMode ommerValidationMode);
}

@ -102,14 +102,14 @@ public class MainnetBlockValidator<C> implements BlockValidator<C> {
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;

@ -66,6 +66,7 @@ public interface BlockImporter<C> {
* @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}
*/
@ -73,5 +74,6 @@ public interface BlockImporter<C> {
ProtocolContext<C> context,
Block block,
List<TransactionReceipt> receipts,
HeaderValidationMode headerValidationMode);
HeaderValidationMode headerValidationMode,
HeaderValidationMode ommerValidationMode);
}

@ -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;
}
}

@ -224,6 +224,15 @@ public class MainnetBlockBodyValidator<C> implements BlockBodyValidator<C> {
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);
@ -236,7 +245,6 @@ public class MainnetBlockBodyValidator<C> implements BlockBodyValidator<C> {
}
previous = ancestor;
}
return false;
}
}

@ -64,9 +64,11 @@ public class MainnetBlockImporter<C> implements BlockImporter<C> {
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;
}

@ -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
@ -61,6 +64,7 @@ public class FastImportBlocksStep<C> implements Consumer<List<BlockWithReceipts>
protocolContext,
blockWithReceipts.getBlock(),
blockWithReceipts.getReceipts(),
validationPolicy.getValidationModeForNextBlock());
headerValidationPolicy.getValidationModeForNextBlock(),
ommerValidationPolicy.getValidationModeForNextBlock());
}
}

@ -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
@ -105,7 +108,8 @@ public class FastSyncBlockHandler<C> implements BlockHandler<BlockWithReceipts>
protocolContext,
block,
blockWithReceipt.getReceipts(),
validationPolicy.getValidationModeForNextBlock())) {
headerValidationPolicy.getValidationModeForNextBlock(),
ommerValidationPolicy.getValidationModeForNextBlock())) {
return invalidBlockFailure(block);
}
}

@ -71,6 +71,12 @@ class FastSyncBlockImportTaskFactory<C> implements BlockImportTaskFactory {
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(),
@ -89,7 +95,8 @@ class FastSyncBlockImportTaskFactory<C> implements BlockImportTaskFactory {
protocolContext,
ethContext,
metricsSystem,
attachedValidationPolicy),
attachedValidationPolicy,
ommerValidationPolicy),
detatchedValidationPolicy,
checkpointHeaders,
metricsSystem);

@ -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;
@ -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,
@ -74,6 +77,9 @@ public class FastSyncDownloadPipelineFactory<C> implements DownloadPipelineFacto
LIGHT_SKIP_DETACHED,
SKIP_DETACHED,
fastSyncValidationCounter);
ommerValidationPolicy =
new FastSyncValidationPolicy(
this.syncConfig.fastSyncFullValidationRate(), LIGHT, FULL, fastSyncValidationCounter);
detachedValidationPolicy =
new FastSyncValidationPolicy(
this.syncConfig.fastSyncFullValidationRate(),
@ -116,7 +122,8 @@ public class FastSyncDownloadPipelineFactory<C> implements DownloadPipelineFacto
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",

@ -20,6 +20,7 @@ import static org.mockito.Mockito.times;
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;
@ -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;
@ -55,9 +57,11 @@ public class FastImportBlocksStepTest {
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
@ -70,7 +74,11 @@ public class FastImportBlocksStepTest {
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);
@ -87,7 +95,7 @@ public class FastImportBlocksStepTest {
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);

@ -22,6 +22,7 @@ import static org.mockito.Mockito.never;
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;
@ -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);
@ -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
@ -101,7 +110,8 @@ public class FastSyncBlockHandlerTest {
@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()));
@ -110,12 +120,15 @@ public class FastSyncBlockHandlerTest {
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 =
@ -127,9 +140,11 @@ public class FastSyncBlockHandlerTest {
@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 =
@ -141,9 +156,14 @@ public class FastSyncBlockHandlerTest {
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);
}
}

Loading…
Cancel
Save