use of org.hyperledger.besu.ethereum.trie.RemoveVisitor in project besu by hyperledger.
the class WorldStateProofProvider method isValidRangeProof.
public boolean isValidRangeProof(final Bytes32 startKeyHash, final Bytes32 endKeyHash, final Bytes32 rootHash, final List<Bytes> proofs, final TreeMap<Bytes32, Bytes> keys) {
// check if it's monotonic increasing
if (!Ordering.natural().isOrdered(keys.keySet())) {
return false;
}
// when proof is empty we need to have all the keys to reconstruct the trie
if (proofs.isEmpty()) {
final MerklePatriciaTrie<Bytes, Bytes> trie = new SimpleMerklePatriciaTrie<>(Function.identity());
// add the received keys in the trie
for (Map.Entry<Bytes32, Bytes> key : keys.entrySet()) {
trie.put(key.getKey(), key.getValue());
}
return rootHash.equals(trie.getRootHash());
}
// reconstruct a part of the trie with the proof
final Map<Bytes32, Bytes> proofsEntries = new HashMap<>();
for (Bytes proof : proofs) {
proofsEntries.put(Hash.hash(proof), proof);
}
if (keys.isEmpty()) {
final MerklePatriciaTrie<Bytes, Bytes> trie = new StoredMerklePatriciaTrie<>(new InnerNodeDiscoveryManager<>((location, hash) -> Optional.ofNullable(proofsEntries.get(hash)), Function.identity(), Function.identity(), startKeyHash, endKeyHash, false), rootHash);
try {
// check if there is not missing element
// a missing node will throw an exception while it is loading
// @see org.hyperledger.besu.ethereum.trie.StoredNode#load()
trie.entriesFrom(startKeyHash, Integer.MAX_VALUE);
} catch (MerkleTrieException e) {
return false;
}
return true;
}
// search inner nodes in the range created by the proofs and remove
final InnerNodeDiscoveryManager<Bytes> snapStoredNodeFactory = new InnerNodeDiscoveryManager<>((location, hash) -> Optional.ofNullable(proofsEntries.get(hash)), Function.identity(), Function.identity(), startKeyHash, keys.lastKey(), true);
final MerklePatriciaTrie<Bytes, Bytes> trie = new StoredMerklePatriciaTrie<>(snapStoredNodeFactory, rootHash);
// filling out innerNodes of the InnerNodeDiscoveryManager by walking through the trie
trie.visitAll(node -> {
});
final List<InnerNode> innerNodes = snapStoredNodeFactory.getInnerNodes();
for (InnerNode innerNode : innerNodes) {
trie.removePath(Bytes.concatenate(innerNode.location(), innerNode.path()), new RemoveVisitor<>(false));
}
// add the received keys in the trie to reconstruct the trie
for (Map.Entry<Bytes32, Bytes> account : keys.entrySet()) {
trie.put(account.getKey(), account.getValue());
}
// check if the generated root hash is valid
return rootHash.equals(trie.getRootHash());
}
Aggregations