Skip to content

Commit

Permalink
snapsync server storage range implementation and initial test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
garyschulte committed Sep 24, 2023
1 parent 30dfc08 commit c32a98e
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@
import org.slf4j.LoggerFactory;

@SuppressWarnings("unused")
public class BonsaiWorldStateKeyValueStorage
implements WorldStateStorage, FlatWorldStateStorage, AutoCloseable {
public class BonsaiWorldStateKeyValueStorage implements FlatWorldStateStorage, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateKeyValueStorage.class);

// 0x776f726c64526f6f74
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@

import org.hyperledger.besu.ethereum.bonsai.storage.flat.FlatDbStrategy;

public interface FlatWorldStateStorage {

FlatDbMode getFlatDbMode();
public interface FlatWorldStateStorage extends WorldStateStorage {

FlatDbStrategy getFlatDbStrategy();
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
import org.hyperledger.besu.ethereum.eth.messages.snap.TrieNodesMessage;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.worldstate.FlatWorldStateStorage;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;

Expand Down Expand Up @@ -60,7 +63,7 @@ class SnapServer {
StorageRangeMessage.create(new ArrayDeque<>(), Collections.emptyList());

private final EthMessages snapMessages;
private final Function<Hash, Optional<WorldStateStorage>> worldStateStorageProvider;
private final Function<Hash, Optional<FlatWorldStateStorage>> worldStateStorageProvider;

SnapServer(final EthMessages snapMessages, final WorldStateArchive archive) {

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'archive' is never used.
this.snapMessages = snapMessages;
Expand All @@ -70,7 +73,7 @@ class SnapServer {

SnapServer(
final EthMessages snapMessages,
final Function<Hash, Optional<WorldStateStorage>> worldStateStorageProvider) {
final Function<Hash, Optional<FlatWorldStateStorage>> worldStateStorageProvider) {
this.snapMessages = snapMessages;
this.worldStateStorageProvider = worldStateStorageProvider;
}
Expand Down Expand Up @@ -163,24 +166,23 @@ MessageData constructGetStorageRangeResponse(final MessageData message) {

for (var forAccountHash : range.hashes()) {
// start key proof

// collectedProofs.addAll(
// worldStateProof.getStorageProofRelatedNodes(
// /* TODO: need account root hash here, not worldstate root hash */
// range.worldStateRootHash(), forAccountHash, Hash.wrap(startKeyBytes)));
collectedProofs.addAll(
worldStateProof.getStorageProofRelatedNodes(
getAccountStorageRoot(forAccountHash, storage),
forAccountHash,
Hash.wrap(startKeyBytes)));

var accountStorages =
storage.streamFlatStorages(
Hash.wrap(forAccountHash), startKeyBytes, endKeyBytes, statefulPredicate);
collectedStorages.add(accountStorages);

// last key proof

// collectedProofs.addAll(
// worldStateProof.getStorageProofRelatedNodes(
// /* TODO: need account root hash here, not worldstate root hash */
// range.worldStateRootHash(), forAccountHash,
// Hash.wrap(accountStorages.lastKey())));
collectedProofs.addAll(
worldStateProof.getStorageProofRelatedNodes(
getAccountStorageRoot(forAccountHash, storage),
forAccountHash,
Hash.wrap(accountStorages.lastKey())));

if (statefulPredicate.shouldGetMore()) {
// reset startkeyBytes for subsequent accounts
Expand Down Expand Up @@ -243,4 +245,13 @@ public boolean test(final Pair<Bytes32, Bytes> pair) {
}
}
}

// expedient to just use the streaming interface
Hash getAccountStorageRoot(final Bytes32 accountHash, final WorldStateStorage storage) {
return storage.streamFlatAccounts(accountHash, accountHash, 1L).values().stream()
.map(rlpbytes -> StateTrieAccountValue.readFrom(new BytesValueRLPInput(rlpbytes, true)))
.map(StateTrieAccountValue::getStorageRoot)
.findFirst()
.orElse(Hash.ZERO);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,11 @@ public void assertStorageForSingleAccount() {
var firstAccountStorages = slotsData.slots().first();
assertThat(firstAccountStorages.size()).isEqualTo(10);

// TODO: proving is not working yet
// assertThat(assertIsValidStorageProof(acct3, Hash.ZERO, firstAccountStorages,
// slotsData.proofs())).isTrue();
// TODO: figure out why storage proofs are failing validation:
// assertThat(
// assertIsValidStorageProof(acct3, Hash.ZERO, firstAccountStorages,
// slotsData.proofs()))
// .isTrue();
}

static SnapTestAccount createTestAccount(final String hexAddr) {
Expand Down Expand Up @@ -191,14 +193,16 @@ static SnapTestAccount createTestContractAccount(
.forEach(
i -> {
Bytes32 mockBytes32 = Bytes32.fromHexStringLenient(i.toString());
updater.putAccountStateTrieNode(
Bytes.concatenate(acctHash, mockBytes32), Hash.hash(mockBytes32), mockBytes32);
trie.put(mockBytes32, mockBytes32);
flatdb.putFlatAccountStorageValueByStorageSlotHash(
updater.getWorldStateTransaction(),
acctHash,
Hash.wrap(mockBytes32),
mockBytes32);
});
trie.commit(
(location, key, value) ->
updater.putAccountStorageTrieNode(acctHash, location, key, value));
updater.commit();
return new SnapTestAccount(
acctHash,
Expand Down

0 comments on commit c32a98e

Please sign in to comment.