use of org.hyperledger.besu.ethereum.trie.InnerNodeDiscoveryManager in project besu by hyperledger.
the class StackTrie method commit.
public void commit(final NodeUpdater nodeUpdater) {
if (nbSegments.decrementAndGet() <= 0 && !elements.isEmpty()) {
final List<Bytes> proofs = new ArrayList<>();
final TreeMap<Bytes32, Bytes> keys = new TreeMap<>();
elements.values().forEach(taskElement -> {
proofs.addAll(taskElement.proofs());
keys.putAll(taskElement.keys());
});
final Map<Bytes32, Bytes> proofsEntries = new HashMap<>();
for (Bytes proof : proofs) {
proofsEntries.put(Hash.hash(proof), proof);
}
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, proofs.isEmpty() ? MerklePatriciaTrie.EMPTY_TRIE_NODE_HASH : rootHash);
for (Map.Entry<Bytes32, Bytes> account : keys.entrySet()) {
trie.put(account.getKey(), new SnapPutVisitor<>(snapStoredNodeFactory, account.getValue()));
}
trie.commit(nodeUpdater, (new CommitVisitor<>(nodeUpdater) {
@Override
public void maybeStoreNode(final Bytes location, final Node<Bytes> node) {
if (!node.isHealNeeded()) {
super.maybeStoreNode(location, node);
}
}
}));
}
}
use of org.hyperledger.besu.ethereum.trie.InnerNodeDiscoveryManager in project besu by hyperledger.
the class RangeManager method findNewBeginElementInRange.
/**
* Helps to create a new range according to the last data obtained. This happens when a peer
* doesn't return all of the data in a range.
*
* @param worldstateRootHash the root hash
* @param proofs proof received
* @param endKeyHash the end of the range initially wanted
* @param receivedKeys the last key received
* @return begin of the new range
*/
public static Optional<Bytes32> findNewBeginElementInRange(final Bytes32 worldstateRootHash, final List<Bytes> proofs, final TreeMap<Bytes32, Bytes> receivedKeys, final Bytes32 endKeyHash) {
if (receivedKeys.isEmpty() || receivedKeys.lastKey().compareTo(endKeyHash) >= 0) {
return Optional.empty();
} else {
final Map<Bytes32, Bytes> proofsEntries = new HashMap<>();
for (Bytes proof : proofs) {
proofsEntries.put(Hash.hash(proof), proof);
}
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie = new StoredMerklePatriciaTrie<>(new InnerNodeDiscoveryManager<>((location, key) -> Optional.ofNullable(proofsEntries.get(key)), Function.identity(), Function.identity(), receivedKeys.lastKey(), endKeyHash, false), worldstateRootHash);
try {
storageTrie.visitAll(bytesNode -> {
});
} catch (MerkleTrieException e) {
return Optional.of(InnerNodeDiscoveryManager.decodePath(e.getLocation()));
}
return Optional.empty();
}
}
use of org.hyperledger.besu.ethereum.trie.InnerNodeDiscoveryManager 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