Snap client fixes (#6847)

* manage empty range for storage
* round rather than floor on max remote connections so that maxpeers=1 still can accept remote connections
---------

Signed-off-by: garyschulte <garyschulte@gmail.com>
Co-authored-by: Karim Taam <karim.t2am@gmail.com>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
pull/6856/head
garyschulte 8 months ago committed by GitHub
parent d926052eb2
commit deaea9b34d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 2
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  3. 44
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/RequestDataStep.java
  4. 4
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/StackTrie.java

@ -39,6 +39,7 @@
- In JSON-RPC return optional `v` fields for type 1 and type 2 transactions [#6762](https://github.com/hyperledger/besu/pull/6762)
- Fix Shanghai/QBFT block import bug when syncing new nodes [#6765](https://github.com/hyperledger/besu/pull/6765)
- Fix to avoid broadcasting full blob txs, instead of only the tx announcement, to a subset of nodes [#6835](https://github.com/hyperledger/besu/pull/6835)
- Snap client fixes discovered during snap server testing [#6847](https://github.com/hyperledger/besu/pull/6847)
### Download Links

@ -1554,7 +1554,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
checkState(
fraction >= 0.0 && fraction <= 1.0,
"Fraction of remote connections allowed must be between 0.0 and 1.0 (inclusive).");
maxRemoteInitiatedPeers = (int) Math.floor(fraction * maxPeers);
maxRemoteInitiatedPeers = Math.round(fraction * maxPeers);
} else {
maxRemoteInitiatedPeers = maxPeers;
}

@ -41,6 +41,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@ -49,9 +50,11 @@ import com.google.common.collect.Lists;
import kotlin.collections.ArrayDeque;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RequestDataStep {
private static final Logger LOG = LoggerFactory.getLogger(RequestDataStep.class);
private final WorldStateStorageCoordinator worldStateStorageCoordinator;
private final SnapSyncProcessState fastSyncState;
private final SnapWorldDownloadState downloadState;
@ -131,15 +134,36 @@ public class RequestDataStep {
(response, error) -> {
if (response != null) {
downloadState.removeOutstandingTask(getStorageRangeTask);
for (int i = 0; i < response.slots().size(); i++) {
final StorageRangeDataRequest request =
(StorageRangeDataRequest) requestTasks.get(i).getData();
request.setRootHash(blockHeader.getStateRoot());
request.addResponse(
downloadState,
worldStateProofProvider,
response.slots().get(i),
i < response.slots().size() - 1 ? new ArrayDeque<>() : response.proofs());
final ArrayDeque<NavigableMap<Bytes32, Bytes>> slots = new ArrayDeque<>();
// Check if we have an empty range
/*
* Checks if the response represents an "empty range".
*
* An "empty range" is defined as a response where at least one proof exists
* and either no slots are present, or the first slot is empty
*/
try {
final boolean isEmptyRange =
(response.slots().isEmpty() || response.slots().get(0).isEmpty())
&& !response.proofs().isEmpty();
if (isEmptyRange) { // empty range detected
slots.add(new TreeMap<>());
} else {
slots.addAll(response.slots());
}
for (int i = 0; i < slots.size(); i++) {
final StorageRangeDataRequest request =
(StorageRangeDataRequest) requestTasks.get(i).getData();
request.setRootHash(blockHeader.getStateRoot());
request.addResponse(
downloadState,
worldStateProofProvider,
slots.get(i),
i < slots.size() - 1 ? new ArrayDeque<>() : response.proofs());
}
} catch (final Exception e) {
LOG.error("Error while processing storage range response", e);
}
}
return requestTasks;

@ -114,6 +114,10 @@ public class StackTrie {
keys.putAll(taskElement.keys());
});
if (keys.isEmpty()) {
return; // empty range we can ignore it
}
final Map<Bytes32, Bytes> proofsEntries = new HashMap<>();
for (Bytes proof : proofs) {
proofsEntries.put(Hash.hash(proof), proof);

Loading…
Cancel
Save