New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Light History Store for full nodes #2370
base: albatross
Are you sure you want to change the base?
Conversation
98709f7
to
05143af
Compare
Does this fix #1704? |
Correct, this is the proper fix for 1704. |
👍 I updated the PR description with that issue number. |
b27ad62
to
62ad289
Compare
if let Some(txns) = txns_per_block.get_mut(&bn) { | ||
txns.push(txn.clone()); | ||
} else { | ||
let new_txns = vec![txn.clone()]; | ||
txns_per_block.insert(bn, new_txns); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let Some(txns) = txns_per_block.get_mut(&bn) { | |
txns.push(txn.clone()); | |
} else { | |
let new_txns = vec![txn.clone()]; | |
txns_per_block.insert(bn, new_txns); | |
} | |
txns_per_block.entry(bn).or_default().push(txn.clone()); |
for bn in txns_per_block.keys().sorted() { | ||
let hist_txs = txns_per_block.get(bn).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a BTreeMap
, the keys would already be sorted.
Then, this could be simplified to for (bn, hist_txs) in txns_per_block
.
Not sure whether it's worth it though.
Also, there's an inconsistency in naming: txs
vs txns
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I considered using a BTreeMap, but I wasn't sure if it was worth to add the dependency and use it vs just sorting the keys
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if it was worth to add the dependency
It's in the standard library, so would be no additional dependency: std::collections::BTreeMap
.
|
||
for hist_tx in ext_hash_vec { | ||
// If the transaction is inside the validity window, return true. | ||
if hist_tx.block_number >= validity_window_start { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, we only check whether the transaction occurred after the validity window started.
However, it could potentially still fall outside the window if it occurred after it finished.
The second boundary check seems missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I'm not doing anything different than what we were doing before, i.e: I just moved this code: https://github.com/nimiq/core-rs-albatross/blob/albatross/blockchain/src/blockchain/wrappers.rs#L196
to the history store file.
Do you suggest that we used to have a bug?
What do you mean by "if it occurred after it finished." ?
blockchain/src/history/mmr_store.rs
Outdated
// If size is 0 we need to copy the entries from the previous block number to the new one | ||
if size == 0 { | ||
init_mmr_from_block_number(hist_tree_table, tx, block_number); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what this is about
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the light history store, what we are using are "peaks-only MMRs"
However, this means that if we have to revert blocks, we don't have enough information to just remove txns and go back to a previous state, as we do with the regular MMR.
So what we are doing is to store "peaks only mmrs" per block, i.e. essentially we have "snapshots" of how the peaks only MMR looked at each block.
However, since history nodes construct a big MMR with all the transactions of the given epoch, and this is the root that we need to verify against, then it means the starting point for block N is the peaks only mmr of block N-1, which is what this line is doing:
when we start pushing transactions for a block that we didn't have before, we first need to start with the peaks only mmr of the previous block and continue from there.
Let me know if this clarifies just question
}; | ||
|
||
// Deconstruct the key into a block number and a node index. | ||
let (new_block_number, _) = key_to_index(next_key).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
key_to_index
returns an epoch_number
instead of a block_number
(according to the variable names in the function; so this needs updating)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update the comment, because we are using the same functions that the regular history store uses (which constructs keys based on {epoch_number, index} , but for the peaks only mmr, we construct keys based on {block_number, index}
@@ -232,6 +241,72 @@ pub fn remove_block_from_store( | |||
} | |||
} | |||
|
|||
/// Copies the mmr entries of the previous block number | |||
/// This is used to initialize the tree for the given block number, using the previous tree as a baseline | |||
pub fn init_mmr_from_block_number( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the advantage of copying the contents over accessing the previous ones when needed?
Less complexity when accessing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment above.
8eda34a
to
240da36
Compare
3f82095
to
59f9c4b
Compare
780e3c4
to
6eadd57
Compare
Use the light history store for full node clients Necessary changes to use the history interface Several changes to usage of the history store
Mantain the txns in the validity store in database tables.
The history store range function now uses a database transaction Added unittest for total_len_at_epoch in the light history store
Add an unittest to exercise the transaction_in_validity_window functionality in the light history store Fixed typo in range inclusion when pruning the validity store
1ffc549
to
f7eec07
Compare
Use the light history store for full node clients
Necessary changes to use the history interface
Several changes to the usage of the history store
...
This fixes #1704.
Pull request checklist
clippy
andrustfmt
warnings.