Skip to content
This repository was archived by the owner on Jul 1, 2025. It is now read-only.

Commit efa7f27

Browse files
Matilda-Clerkegaryschulte
authored andcommitted
Clean up pivot selector from peers and unit test (#8020)
* 7582: Add waitForPeer method to PeerSelector and EthPeers Signed-off-by: Matilda Clerke <[email protected]> * 7582: Replace all usages of WaitForPeer[s]Task with new EthPeers.waitForPeer method Signed-off-by: Matilda Clerke <[email protected]> * 7582: Fix PivotBlockConfirmerTest Signed-off-by: Matilda Clerke <[email protected]> * 7582: spotless Signed-off-by: Matilda Clerke <[email protected]> * 7582: Fix broken PivotBlockRetrieverTest Signed-off-by: Matilda Clerke <[email protected]> * 7582: Fix broken FastSyncActionsTest Signed-off-by: Matilda Clerke <[email protected]> * 7582: spotless Signed-off-by: Matilda Clerke <[email protected]> * 7582: Simplify PivotSelectorFromPeers.selectNewPivotBlock and add unit tests Signed-off-by: Matilda Clerke <[email protected]> * 7582: Fix issues after merge Signed-off-by: Matilda Clerke <[email protected]> * 7582: Put AbstractSyncTargetManager.waitForPeerAndThenSetSyncTarget code back separate thread to avoid infinite loop waiting for peers during acceptance tests Signed-off-by: Matilda Clerke <[email protected]> * 7582: Remove pivot block checks when waiting for peer in FastSyncActions Signed-off-by: Matilda Clerke <[email protected]> * 7582: Remove estimated chain height check from PivotBlockConfirmer when waiting for peers Signed-off-by: Matilda Clerke <[email protected]> * 7582: Fix broken PivotBlockRetrieverTest Signed-off-by: Matilda Clerke <[email protected]> * Fix compile errors Signed-off-by: Matilda Clerke <[email protected]> * spotless Signed-off-by: Matilda Clerke <[email protected]> * Refactor mockito usage Signed-off-by: Matilda Clerke <[email protected]> --------- Signed-off-by: Matilda Clerke <[email protected]>
1 parent c03c102 commit efa7f27

File tree

2 files changed

+105
-30
lines changed

2 files changed

+105
-30
lines changed

ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.hyperledger.besu.ethereum.eth.sync.TrailingPeerRequirements;
2424
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
2525

26+
import java.util.List;
2627
import java.util.Optional;
2728
import java.util.concurrent.CompletableFuture;
2829

@@ -86,41 +87,24 @@ protected Optional<FastSyncState> fromBestPeer(final EthPeer peer) {
8687
}
8788

8889
protected Optional<EthPeer> selectBestPeer() {
89-
return ethContext
90-
.getEthPeers()
91-
.bestPeerMatchingCriteria(this::canPeerDeterminePivotBlock)
92-
// Only select a pivot block number when we have a minimum number of height estimates
93-
.filter(unused -> enoughFastSyncPeersArePresent());
94-
}
95-
96-
private boolean enoughFastSyncPeersArePresent() {
97-
final long peerCount = countPeersThatCanDeterminePivotBlock();
90+
List<EthPeer> peers =
91+
ethContext
92+
.getEthPeers()
93+
.streamAvailablePeers()
94+
.filter((peer) -> peer.chainState().hasEstimatedHeight() && peer.isFullyValidated())
95+
.toList();
96+
97+
// Only select a pivot block number when we have a minimum number of height estimates
9898
final int minPeerCount = syncConfig.getSyncMinimumPeerCount();
99-
if (peerCount < minPeerCount) {
99+
if (peers.size() < minPeerCount) {
100100
LOG.info(
101101
"Waiting for valid peers with chain height information. {} / {} required peers currently available.",
102-
peerCount,
102+
peers.size(),
103103
minPeerCount);
104-
return false;
104+
return Optional.empty();
105+
} else {
106+
return peers.stream().max(ethContext.getEthPeers().getBestPeerComparator());
105107
}
106-
return true;
107-
}
108-
109-
private long countPeersThatCanDeterminePivotBlock() {
110-
return ethContext
111-
.getEthPeers()
112-
.streamAvailablePeers()
113-
.filter(this::canPeerDeterminePivotBlock)
114-
.count();
115-
}
116-
117-
private boolean canPeerDeterminePivotBlock(final EthPeer peer) {
118-
LOG.debug(
119-
"peer {} hasEstimatedHeight {} isFullyValidated? {}",
120-
peer.getLoggableId(),
121-
peer.chainState().hasEstimatedHeight(),
122-
peer.isFullyValidated());
123-
return peer.chainState().hasEstimatedHeight() && peer.isFullyValidated();
124108
}
125109

126110
private long conservativelyEstimatedPivotBlock() {
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.ethereum.eth.sync.fastsync;
16+
17+
import org.hyperledger.besu.ethereum.eth.manager.ChainState;
18+
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
19+
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
20+
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
21+
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
22+
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
23+
24+
import java.util.Optional;
25+
import java.util.stream.Stream;
26+
27+
import org.junit.jupiter.api.Assertions;
28+
import org.junit.jupiter.api.BeforeEach;
29+
import org.junit.jupiter.api.Test;
30+
import org.junit.jupiter.api.extension.ExtendWith;
31+
import org.mockito.Mock;
32+
import org.mockito.Mockito;
33+
import org.mockito.junit.jupiter.MockitoExtension;
34+
import org.mockito.junit.jupiter.MockitoSettings;
35+
import org.mockito.quality.Strictness;
36+
37+
@ExtendWith(MockitoExtension.class)
38+
@MockitoSettings(strictness = Strictness.LENIENT)
39+
public class PivotSelectorFromPeersTest {
40+
private @Mock EthContext ethContext;
41+
private @Mock EthPeers ethPeers;
42+
private @Mock SyncState syncState;
43+
44+
private PivotSelectorFromPeers selector;
45+
46+
@BeforeEach
47+
public void beforeTest() {
48+
SynchronizerConfiguration syncConfig =
49+
SynchronizerConfiguration.builder().syncMinimumPeerCount(2).syncPivotDistance(1).build();
50+
51+
selector = new PivotSelectorFromPeers(ethContext, syncConfig, syncState);
52+
}
53+
54+
@Test
55+
public void testSelectNewPivotBlock() {
56+
EthPeer peer1 = mockPeer(true, 10, true);
57+
EthPeer peer2 = mockPeer(true, 8, true);
58+
59+
Mockito.when(ethContext.getEthPeers()).thenReturn(ethPeers);
60+
Mockito.when(ethPeers.streamAvailablePeers()).thenReturn(Stream.of(peer1, peer2));
61+
Mockito.when(ethPeers.getBestPeerComparator())
62+
.thenReturn((p1, ignored) -> p1 == peer1 ? 1 : -1);
63+
64+
Optional<FastSyncState> result = selector.selectNewPivotBlock();
65+
66+
Assertions.assertTrue(result.isPresent());
67+
Assertions.assertEquals(9, result.get().getPivotBlockNumber().getAsLong());
68+
}
69+
70+
@Test
71+
public void testSelectNewPivotBlockWithInsufficientPeers() {
72+
Mockito.when(ethContext.getEthPeers()).thenReturn(ethPeers);
73+
Mockito.when(ethPeers.streamAvailablePeers()).thenReturn(Stream.empty());
74+
75+
Optional<FastSyncState> result = selector.selectNewPivotBlock();
76+
77+
Assertions.assertTrue(result.isEmpty());
78+
}
79+
80+
private EthPeer mockPeer(
81+
final boolean hasEstimatedHeight, final long chainHeight, final boolean isFullyValidated) {
82+
EthPeer ethPeer = Mockito.mock(EthPeer.class);
83+
ChainState chainState = Mockito.mock(ChainState.class);
84+
Mockito.when(ethPeer.chainState()).thenReturn(chainState);
85+
Mockito.when(chainState.hasEstimatedHeight()).thenReturn(hasEstimatedHeight);
86+
Mockito.when(chainState.getEstimatedHeight()).thenReturn(chainHeight);
87+
Mockito.when(ethPeer.isFullyValidated()).thenReturn(isFullyValidated);
88+
89+
return ethPeer;
90+
}
91+
}

0 commit comments

Comments
 (0)