Skip to content

Commit

Permalink
mark empty account storage range requests with an accompanying proof …
Browse files Browse the repository at this point in the history
…as complete

Signed-off-by: garyschulte <[email protected]>
  • Loading branch information
garyschulte committed Dec 13, 2023
1 parent 0f89356 commit 57312c8
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Function;
Expand All @@ -43,7 +44,7 @@ public class RangeManager {
private RangeManager() {}

public static int getRangeCount(
final Bytes32 min, final Bytes32 max, final TreeMap<Bytes32, Bytes> items) {
final Bytes32 min, final Bytes32 max, final NavigableMap<Bytes32, Bytes> items) {
if (min.equals(MIN_RANGE) && max.equals(MAX_RANGE)) {
return MAX_RANGE
.toUnsignedBigInteger()
Expand Down Expand Up @@ -120,7 +121,7 @@ public static Map<Bytes32, Bytes32> generateRanges(
public static Optional<Bytes32> findNewBeginElementInRange(
final Bytes32 worldstateRootHash,
final List<Bytes> proofs,
final TreeMap<Bytes32, Bytes> receivedKeys,
final NavigableMap<Bytes32, Bytes> receivedKeys,
final Bytes32 endKeyHash) {
if (receivedKeys.isEmpty() || receivedKeys.lastKey().compareTo(endKeyHash) >= 0) {
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.hyperledger.besu.services.tasks.Task;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -129,15 +130,29 @@ public CompletableFuture<List<Task<SnapDataRequest>>> requestStorage(
(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());
if (response.slots().size() > 0) {
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());
}
}

// if we received no slots, but a proof of exclusion, mark as done:
else if (response.proofs().size() > 0 && requestTasks.size() > 0) {
var lastTask = requestTasks.get(requestTasks.size() - 1);
if (lastTask instanceof StorageRangeDataRequest storageRequest) {
storageRequest.addResponse(
downloadState,
worldStateProofProvider,
Collections.emptyNavigableMap(),
response.proofs());
}
}
}
return requestTasks;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -72,7 +73,9 @@ public StackTrie(
}

public void addElement(
final Bytes32 taskIdentifier, final List<Bytes> proofs, final TreeMap<Bytes32, Bytes> keys) {
final Bytes32 taskIdentifier,
final List<Bytes> proofs,
final NavigableMap<Bytes32, Bytes> keys) {
this.elementsCount.addAndGet(keys.size());
this.elements.put(
taskIdentifier, ImmutableTaskElement.builder().proofs(proofs).keys(keys).build());
Expand Down Expand Up @@ -180,7 +183,7 @@ public List<Bytes> proofs() {
}

@Value.Default
public TreeMap<Bytes32, Bytes> keys() {
public NavigableMap<Bytes32, Bytes> keys() {
return new TreeMap<>();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -212,7 +213,7 @@ public Bytes32 getEndKeyHash() {
}

@VisibleForTesting
public TreeMap<Bytes32, Bytes> getAccounts() {
public NavigableMap<Bytes32, Bytes> getAccounts() {
return stackTrie.getElement(startKeyHash).keys();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@

import java.util.ArrayList;
import java.util.List;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

Expand Down Expand Up @@ -119,7 +119,7 @@ protected int doPersist(
public void addResponse(
final SnapWorldDownloadState downloadState,
final WorldStateProofProvider worldStateProofProvider,
final TreeMap<Bytes32, Bytes> slots,
final NavigableMap<Bytes32, Bytes> slots,
final ArrayDeque<Bytes> proofs) {
if (!slots.isEmpty() || !proofs.isEmpty()) {
if (!worldStateProofProvider.isValidRangeProof(
Expand Down Expand Up @@ -193,7 +193,7 @@ public Bytes32 getStorageRoot() {
return storageRoot;
}

public TreeMap<Bytes32, Bytes> getSlots() {
public NavigableMap<Bytes32, Bytes> getSlots() {
return stackTrie.getElement(startKeyHash).keys();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.hyperledger.besu.ethereum.eth.sync.snapsync.request;

import static org.assertj.core.api.Assertions.assertThat;

import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;

import java.util.Collections;

import kotlin.collections.ArrayDeque;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class StorageRangeDataRequestTest {
private static final Hash HASH_LAST = Hash.fromHexString("F".repeat(64));

@Mock WorldStateStorage storage;

@Test
public void assertEmptySlotsWithProofOfExclusionCompletes() {
var worldstateProofProvider = new WorldStateProofProvider(storage);

var storageRangeRequest =
new StorageRangeDataRequest(
Hash.EMPTY_TRIE_HASH, Bytes32.ZERO, Hash.EMPTY_TRIE_HASH, Bytes32.ZERO, HASH_LAST);

var proofs = new ArrayDeque<Bytes>();
proofs.add(0, Hash.EMPTY_TRIE_HASH);

storageRangeRequest.addResponse(
null, worldstateProofProvider, Collections.emptyNavigableMap(), proofs);
assertThat(storageRangeRequest.isResponseReceived()).isTrue();
}
}

0 comments on commit 57312c8

Please sign in to comment.