-
Notifications
You must be signed in to change notification settings - Fork 17
Test real blocks #601
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
Test real blocks #601
Conversation
This seems preferable to me because:
I note that git-lfs is installed by default on ubuntu 24.04, but according to gemini LLM:
and even if installed by default, ti requires user to |
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'd like to switch to downloading the blk0.dat within the unit test if we can, for reasons outlined in a previous comment.
just for reference: I performed a timed git checkout of this branch via my slow connection. It took 8 minutes, 48 seconds.
I'm not sure the GlobalStateLock constructor change is needed and/or I think it can be done more cleanly. see inline comments.
It's likely worth inviting another reviewer for another set of eyes.
src/models/state/mod.rs
Outdated
genesis: Block, | ||
cli_args: cli_args::Args, | ||
rpc_server_to_main_tx: tokio::sync::mpsc::Sender<RPCServerToMain>, | ||
) -> Result<Self> { |
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.
consider renaming to try_new(). So if we keep the old pub fn new()
and add this try_new()
then it can be constructed either way.
further musings
I don't (yet?) see why all this init code should be occurring inside GlobalStateLock's constructor rather than the caller(s), eg initialize() in lib.rs.
In theory GlobalStateLock should be just a thin wrapper around GlobalState, though admittedly its role has been growing over time.
I read the commit comment, but I'm still unclear on the motivation for the change. Is this necessary for the PR to "test real blocks"?
If the goal is to make the init code more reusable, perhaps consider a GlobalStateLock builder with a fallible build() method instead. It could be in a separate file.
also for a fallible constructor on such a central/public API type I'd really like to see it return a thiserror Error enum for all the error variants. Or alternatively not be pub.
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 read the commit comment, but I'm still unclear on the motivation for the change. Is this necessary for the PR to "test real blocks"?
Yes. The genesis block under the test flag is different from the real genesis block. Because under the test flag initial difficulty is 6.000 and otherwise it's 1.000.000.000. So the refactor is needed to allow the genesis block to be injected by the caller when creating a new GlobalState
/GlobalStateLock
.
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's just for test purposes, couldn't it be done after GlobalStateLock is created, eg?
let gsl = GlobalStateLock::new(...); // using the original new() method
let mut gsm = gsl.lock_guard_mut().await;
gsm.chain = BlockchainState::Archival( ... );
or perhaps cleaner the fallible try_new() could be in an impl block inside the test module, eg:
#[cfg(test}]
mod tests {
impl GlobalStateLock {
fn try_new(...) -> anyhow::Result<Self> { .. }
}
}
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's just for test purposes, couldn't it be done after GlobalStateLock is created, eg?
These state updates are quite tricky, as the wallet state also needs to be updated with the right block, in which potential premine rewards are received. The genesis block needs to be injected like this.
src/models/state/mod.rs
Outdated
@@ -161,8 +166,7 @@ pub struct GlobalStateLock { | |||
} | |||
|
|||
impl GlobalStateLock { | |||
/// the key to the watery kingdom. | |||
pub fn new( | |||
pub(crate) fn new_internal( |
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 feel like this should still be pub fn new()
.
network: Network, | ||
) -> Self { | ||
let genesis_block = Box::new(Block::genesis(network)); | ||
pub(crate) async fn new(data_dir: DataDirectory, genesis_block: Block) -> Self { |
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.
This method is now fallible. consider renaming to try_new() and returning a result rather than panicking within the method. Or at least document it can panic and under what conditions.
c576b96
to
59ee436
Compare
I addressed some concerns:
|
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.
The cli_args::Args::default_with_network(network)
seems a nice shortcut.
I left a few more comments/suggestions, but overall it seems ok to merge.
src/models/state/mod.rs
Outdated
net: NetworkingState, | ||
cli: cli_args::Args, | ||
mempool: Mempool, | ||
pub(crate) fn from_global_state( |
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.
this is an interesting change. I think it is positive to build the GlobalState first, and then the GlobalStateLock from it, as this change implies.
I think where I'd really like to get to is impl From<GlobalState> for GlobalStateLock {..}
seems really clean.
But that's not possible right now due to the mpsc::Sender for rpc. Maybe we can find a better place for that than GlobalStateLock.
Also, removing the pub fn new()
entirely is a breaking change to the public API. I don't know if anyone is using it, but there could be, in the community. I would probably leave that API in place for now, but I don't feel so strongly about it.
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 make the constructors for GlobalState
and GlobalStateLock
public again.
@@ -616,6 +617,49 @@ impl Drop for GlobalState { | |||
} | |||
|
|||
impl GlobalState { |
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'm still not convinced this fallible initialization code needs to exist in state/mod.rs at all. However, since it is only pub(crate), I am satisfied, as we can always move it later without changing public API.
@@ -456,6 +452,160 @@ impl<Item> stream::Stream for Mock<Item> { | |||
} | |||
} | |||
|
|||
/// Return path for the directory containing test data, like proofs and block |
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.
this file is growing large. maybe it's time to consider splitting into separate file(s).
src/tests/shared.rs
Outdated
@@ -1330,3 +1458,16 @@ where | |||
} | |||
Ok(()) | |||
} | |||
|
|||
#[cfg(test)] |
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.
redundant. This entire file is already #[cfg(test)].
809a1e6
to
b79b98d
Compare
Move initialization of databases used by the archival state into its constructor.
b79b98d
to
29597cb
Compare
Change function signature and logic of `GlobalState::new` to move more of the database initialization into this constructor. Previously, this database initialization happened directly in lib.rs's `initialize`. Also allow caller of this constructor to specify the genesis block, as this will widen our testing capabilities somewhat. Big diff because this changes many tests. But the diff of non-testing, mainline, code is quite small.
Refactor this code to fetch proofs from server so it can be used for other data as well, specifically to also fetch blk files containing block data.
Add a test of `GlobalState::bootstrap_from_directory` using real data from main net. The test uses the `blk0.dat` file from a node that has been online since genesis, thus containing reorganizations that some previously untested branches of `GlobalState::bootstrap_from_directory`. This test also serves as a check that the first 113 main net blocks are still considered valid by future versions of the software.
29597cb
to
568b952
Compare
test: Recover state from real main net blocks
Add a test of
GlobalState::bootstrap_from_directory
using real datafrom main net. The test uses the
blk0.dat
file from a node that hasbeen online since genesis, thus containing reorganizations that some
previously untested branches of
GlobalState::bootstrap_from_directory
.This test also serves as a check that the first 113 main net blocks are
still considered valid by future versions of the software.
Closes #515
This PR introduces a big file,
blk0.dat
, added withgit lfs
. But an alternative would be to download theblk0.dat
from our test servers instead, and store it intest_data
so that it would only ever have to be downloaded once.