Skip to content
/ besu Public
forked from hyperledger/besu

Commit

Permalink
Support pruned chain history in peer validators (hyperledger#6698)
Browse files Browse the repository at this point in the history
* dao fork block presence is optional in peer validator to support peers with pruned chain history

Signed-off-by: garyschulte <garyschulte@gmail.com>

* Update ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidator.java

Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: garyschulte <garyschulte@gmail.com>

---------

Signed-off-by: garyschulte <garyschulte@gmail.com>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: amsmota <antonio.mota@citi.com>
  • Loading branch information
2 people authored and amsmota committed Apr 16, 2024
1 parent 1512b8b commit edf58a5
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,20 @@ public CompletableFuture<Boolean> validatePeer(
}
final List<BlockHeader> headers = res.getResult();
if (headers.size() == 0) {
// If no headers are returned, fail
LOG.debug(
"Peer {} is invalid because required block ({}) is unavailable.",
ethPeer,
blockNumber);
return false;
if (blockIsRequired()) {
// If no headers are returned, fail
LOG.debug(
"Peer {} is invalid because required block ({}) is unavailable.",
ethPeer,
blockNumber);
return false;
} else {
LOG.debug(
"Peer {} deemed valid because unavailable block ({}) is not required.",
ethPeer,
blockNumber);
return true;
}
}
final BlockHeader header = headers.get(0);
return validateBlockHeader(ethPeer, header);
Expand All @@ -105,6 +113,10 @@ public boolean canBeValidated(final EthPeer ethPeer) {
return ethPeer.chainState().getEstimatedHeight() >= (blockNumber + chainHeightEstimationBuffer);
}

protected boolean blockIsRequired() {
return true;
}

@Override
public Duration nextValidationCheckTimeout(final EthPeer ethPeer) {
if (!ethPeer.chainState().hasEstimatedHeight()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,13 @@ boolean validateBlockHeader(final EthPeer ethPeer, final BlockHeader header) {
}
return validDaoBlock;
}

/**
* In order to support chain history pruning, clients do not need to have the dao fork block to be
* deemed valid.
*/
@Override
protected boolean blockIsRequired() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,28 @@ public void validatePeer_responsivePeerOnWrongSideOfFork() {
assertThat(result).isDone();
assertThat(result).isCompletedWithValue(false);
}

@Test
public void validatePeer_responsivePeerDoesNotHaveBlockWhenPastForkHeight() {
final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create();
final long daoBlockNumber = 500;

final PeerValidator validator =
new DaoForkPeerValidator(
ProtocolScheduleFixture.MAINNET, new NoOpMetricsSystem(), daoBlockNumber, 0);

final RespondingEthPeer peer =
EthProtocolManagerTestUtil.createPeer(ethProtocolManager, daoBlockNumber);

final CompletableFuture<Boolean> result =
validator.validatePeer(ethProtocolManager.ethContext(), peer.getEthPeer());

assertThat(result).isNotDone();

// Respond to block header request with empty
peer.respond(RespondingEthPeer.emptyResponder());

assertThat(result).isDone();
assertThat(result).isCompletedWithValue(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,26 @@ public void validatePeer_responsivePeerWithBadRequiredBlock() {
assertThat(result).isDone();
assertThat(result).isCompletedWithValue(false);
}

@Test
public void validatePeer_responsivePeerDoesNotHaveBlockWhenPastForkHeight() {
final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create();

final PeerValidator validator =
new RequiredBlocksPeerValidator(
ProtocolScheduleFixture.MAINNET, new NoOpMetricsSystem(), 1, Hash.ZERO);

final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1);

final CompletableFuture<Boolean> result =
validator.validatePeer(ethProtocolManager.ethContext(), peer.getEthPeer());

assertThat(result).isNotDone();

// Respond to block header request with empty
peer.respond(RespondingEthPeer.emptyResponder());

assertThat(result).isDone();
assertThat(result).isCompletedWithValue(false);
}
}

0 comments on commit edf58a5

Please sign in to comment.