-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix empty body concept after shanghai #5174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
0c39601
d4a6251
4f7c43d
f782406
b9dcdb4
0d305e6
74ba4cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,26 +17,42 @@ | |
| import static java.util.Arrays.asList; | ||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
| import static org.mockito.ArgumentMatchers.eq; | ||
| import static org.mockito.Mockito.spy; | ||
| import static org.mockito.Mockito.when; | ||
|
|
||
| import org.hyperledger.besu.datatypes.Address; | ||
| import org.hyperledger.besu.datatypes.GWei; | ||
| import org.hyperledger.besu.datatypes.Hash; | ||
| import org.hyperledger.besu.ethereum.chain.Blockchain; | ||
| import org.hyperledger.besu.ethereum.core.Block; | ||
| import org.hyperledger.besu.ethereum.core.BlockBody; | ||
| import org.hyperledger.besu.ethereum.core.BlockHeader; | ||
| import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; | ||
| import org.hyperledger.besu.ethereum.core.Withdrawal; | ||
| import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; | ||
| import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; | ||
| import org.hyperledger.besu.ethereum.eth.manager.ethtaskutils.RetryingMessageTaskTest; | ||
| import org.hyperledger.besu.ethereum.eth.manager.exceptions.MaxRetriesReachedException; | ||
| import org.hyperledger.besu.ethereum.eth.manager.task.EthTask; | ||
| import org.hyperledger.besu.ethereum.eth.messages.GetBlockBodiesMessage; | ||
| import org.hyperledger.besu.ethereum.mainnet.BodyValidation; | ||
| import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; | ||
| import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; | ||
| import org.hyperledger.besu.ethereum.mainnet.WithdrawalsProcessor; | ||
| import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; | ||
| import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
| import java.util.concurrent.CompletableFuture; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import org.apache.tuweni.units.bigints.UInt64; | ||
| import org.junit.Test; | ||
| import org.mockito.Mockito; | ||
|
|
||
| public class CompleteBlocksTaskTest extends RetryingMessageTaskTest<List<Block>> { | ||
|
|
||
|
|
@@ -79,6 +95,115 @@ public void shouldCompleteWithoutPeersWhenAllBlocksAreEmpty() { | |
| assertThat(task.run()).isCompletedWithValue(blocks); | ||
| } | ||
|
|
||
| @Test | ||
| public void shouldCreateCorrectEmptyBlockWhenWithdrawalsAreEnabled() { | ||
|
jframe marked this conversation as resolved.
Outdated
|
||
| final ProtocolSchedule mockProtocolSchedule = Mockito.mock(ProtocolSchedule.class); | ||
| final ProtocolSpec mockParisSpec = Mockito.mock(ProtocolSpec.class); | ||
| final ProtocolSpec mockShanghaiSpec = Mockito.mock(ProtocolSpec.class); | ||
| final WithdrawalsProcessor mockWithdrawalsProcessor = Mockito.mock(WithdrawalsProcessor.class); | ||
|
|
||
| final BlockHeader header1 = | ||
| new BlockHeaderTestFixture().number(1).withdrawalsRoot(null).buildHeader(); | ||
| final BlockHeader header2 = | ||
| new BlockHeaderTestFixture().number(2).withdrawalsRoot(Hash.EMPTY_TRIE_HASH).buildHeader(); | ||
|
|
||
| when(mockProtocolSchedule.getByBlockHeader((eq(header1)))).thenReturn(mockParisSpec); | ||
| when(mockParisSpec.getWithdrawalsProcessor()).thenReturn(Optional.empty()); | ||
| when(mockProtocolSchedule.getByBlockHeader((eq(header2)))).thenReturn(mockShanghaiSpec); | ||
| when(mockShanghaiSpec.getWithdrawalsProcessor()) | ||
| .thenReturn(Optional.of(mockWithdrawalsProcessor)); | ||
|
|
||
| final Block block1 = | ||
| new Block(header1, new BlockBody(Collections.emptyList(), Collections.emptyList())); | ||
| final Block block2 = | ||
| new Block( | ||
| header2, | ||
| new BlockBody( | ||
| Collections.emptyList(), | ||
| Collections.emptyList(), | ||
| Optional.of(Collections.emptyList()))); | ||
|
|
||
| final List<Block> expectedBlocks = asList(block1, block2); | ||
| final EthTask<List<Block>> task = | ||
| CompleteBlocksTask.forHeaders( | ||
| mockProtocolSchedule, | ||
| ethContext, | ||
| List.of(header1, header2), | ||
| maxRetries, | ||
| new NoOpMetricsSystem()); | ||
| assertThat(task.run()).isCompletedWithValue(expectedBlocks); | ||
| } | ||
|
|
||
| @Test | ||
| public void shouldCompleteWhenBlocksAreEmptyExceptForWithdrawals() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this testing that when blocks are empty but have withdrawals they are still downloaded? i.e. that they are considered empty blocks. Was a bit confused from the test name
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yes, i.e. that they are not considered empty blocks like they were being before. Any name suggestion? This was an modification of the existing test's name: |
||
| final ProtocolSchedule mockProtocolSchedule = Mockito.mock(ProtocolSchedule.class); | ||
| final ProtocolSpec mockParisSpec = Mockito.mock(ProtocolSpec.class); | ||
| final ProtocolSpec mockShanghaiSpec = Mockito.mock(ProtocolSpec.class); | ||
| final WithdrawalsProcessor mockWithdrawalsProcessor = Mockito.mock(WithdrawalsProcessor.class); | ||
|
|
||
| final Withdrawal withdrawal = | ||
| new Withdrawal(UInt64.ONE, UInt64.ONE, Address.fromHexString("0x1"), GWei.ONE); | ||
| final List<Withdrawal> withdrawals = List.of(withdrawal); | ||
| final Hash withdrawalsRoot = BodyValidation.withdrawalsRoot(withdrawals); | ||
|
|
||
| final BlockHeader preWithdrawalsHeader = new BlockHeaderTestFixture().number(1).buildHeader(); | ||
| final BlockHeader firstWithdrawalsHeader = | ||
| new BlockHeaderTestFixture().number(2).withdrawalsRoot(withdrawalsRoot).buildHeader(); | ||
| final BlockHeader secondWithdrawalsHeader = | ||
| new BlockHeaderTestFixture().number(3).withdrawalsRoot(Hash.EMPTY_TRIE_HASH).buildHeader(); | ||
|
|
||
| final Block block1 = new Block(preWithdrawalsHeader, BlockBody.empty()); | ||
|
gfukushima marked this conversation as resolved.
Outdated
|
||
| final Block block2 = | ||
| new Block( | ||
| firstWithdrawalsHeader, | ||
| new BlockBody( | ||
| Collections.emptyList(), Collections.emptyList(), Optional.of(withdrawals))); | ||
| final Block block3 = | ||
|
gfukushima marked this conversation as resolved.
|
||
| new Block( | ||
| secondWithdrawalsHeader, | ||
| new BlockBody( | ||
| Collections.emptyList(), | ||
| Collections.emptyList(), | ||
| Optional.of(Collections.emptyList()))); | ||
| final List<Block> expected = asList(block1, block2, block3); | ||
|
|
||
| final RespondingEthPeer respondingPeer = | ||
| EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); | ||
| final RespondingEthPeer.Responder responder = responderForFakeBlocks(expected); | ||
|
gfukushima marked this conversation as resolved.
|
||
|
|
||
| when(mockProtocolSchedule.getByBlockHeader((eq(preWithdrawalsHeader)))) | ||
| .thenReturn(mockParisSpec); | ||
| when(mockParisSpec.getWithdrawalsProcessor()).thenReturn(Optional.empty()); | ||
| when(mockProtocolSchedule.getByBlockHeader((eq(secondWithdrawalsHeader)))) | ||
| .thenReturn(mockShanghaiSpec); | ||
| when(mockShanghaiSpec.getWithdrawalsProcessor()) | ||
| .thenReturn(Optional.of(mockWithdrawalsProcessor)); | ||
|
|
||
| final EthTask<List<Block>> task = | ||
| CompleteBlocksTask.forHeaders( | ||
| mockProtocolSchedule, | ||
| ethContext, | ||
| List.of(preWithdrawalsHeader, firstWithdrawalsHeader, secondWithdrawalsHeader), | ||
| maxRetries, | ||
| new NoOpMetricsSystem()); | ||
|
|
||
| final CompletableFuture<List<Block>> runningTask = task.run(); | ||
|
|
||
| assertThat(runningTask).isNotDone(); | ||
| respondingPeer.respond(responder); | ||
| assertThat(runningTask).isCompletedWithValue(expected); | ||
| // assertThat(task.run()).isCompletedWithValue(expected); | ||
|
gfukushima marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| private RespondingEthPeer.Responder responderForFakeBlocks(final List<Block> blocks) { | ||
| final Blockchain mockBlockchain = spy(blockchain); | ||
| for (Block block : blocks) { | ||
| when(mockBlockchain.getBlockBody(block.getHash())).thenReturn(Optional.of(block.getBody())); | ||
| } | ||
|
|
||
| return RespondingEthPeer.blockchainResponder(mockBlockchain); | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| @Test | ||
| public void shouldReduceTheBlockSegmentSizeAfterEachRetry() { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.