-
Notifications
You must be signed in to change notification settings - Fork 228
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
Abscissify light node #125
Conversation
7dbeca3
to
1226b4b
Compare
lite-node/tests/acceptance.rs
Outdated
|
||
/// Use `LiteNodeConfig::default()` value if no config or args | ||
#[test] | ||
#[ignore] |
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.
Note: To do proper tests here (throughout the file), we'd need to mock the requester.
lite-node/src/config.rs
Outdated
/// The duration until we consider a trusted state as expired. | ||
pub trusting_period: Duration, | ||
/// Subjective initialization. | ||
pub subjective_init: SubjectiveInit, |
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.
We need to figure out a clever way to represent TrustThreshold
as sth that can be written to a file. It's currently just defined via it's behaviour.
lite-node/src/commands/start.rs
Outdated
let now = &SystemTime::now(); | ||
lite::verify_and_update_bisection( | ||
latest_peer_height, | ||
THRESHOLD, // TODO |
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.
lite-node/src/commands/start.rs
Outdated
|
||
// TODO: this should also somehow be configurable ... | ||
// we can't simply add this as a field in the config because this either would | ||
// be a trait (`TrustThreshold`) or immediately and impl thereof (`TrustThresholdOneThird`). |
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.
lite-node/src/lib.rs
Outdated
pub mod commands; | ||
pub mod config; | ||
pub mod error; | ||
pub mod prelude; |
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.
Everything below prelude
should likely live somewhere else (in a different module)?
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 know this is WIP, but I'd like to see some rationale why a framework is a good choice to bootstrap two commands. At a glance it looks like a lot of overhead to setup, could you outline what dimensions should be considered and how abscissa is going to make any other (e.g. structopt, pico-args into function invocation) option non-viable. Obviously I come with the bias of fearing complexities in places where they aren't necessary, likely tho I'm missing a lot of important points. It would be good to also provide such rationale to other readers, was there a discussion/decision that informed this change and its necessity?
@xla I can give a short rationale: Abscissa provides solutions for: command-line option parsing, components (i.e. dependency injection), configuration, error handling, logging, secrets management, and terminal interactions. To the extent it has "a lot of overhead to setup", I'd argue that it has less than wiring all of these things up subsystem-by-subsystem, and that you probably need all of these things.
Abscissa provides the full functionality of I'll also note that Abscissa is being used by Zebra, a clean-room Rust implementation of a Zcash node, as well as Tendermint KMS. As such, we're able to work on common solutions to problems like how to integrate Abscissa and Tokio. If you'd like to read more about Abscissa, here's a blog post: https://iqlusion.blog/introducing-abscissa-rust-application-framework |
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.
Sweet! We should try to capture the rationale for using Abscissa here in a short ADR.
* trusted state and store it in the store ... | ||
* TODO: this should take traits ... but how to deal with the State ? | ||
* TODO: better name ? | ||
*/ |
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.
@ebuchman @Shivani912 @milosevic I'll move this into the lite crate in a separate PR. Note that we need to rework the spec to match the initialization via a pair of subjective (height, vals_hash). Currently, it only talks about init. through a header.
Codecov Report
@@ Coverage Diff @@
## master #125 +/- ##
==========================================
+ Coverage 38.64% 38.71% +0.06%
==========================================
Files 88 88
Lines 2919 2919
Branches 440 440
==========================================
+ Hits 1128 1130 +2
+ Misses 1506 1504 -2
Partials 285 285
Continue to review full report at Codecov.
|
- ran `abscissa new lite-node` - added deps (Cargo.toml) and minimal changes to README.md - add to root workspace
- copied from tendermint-lite/src/main.rs to lite-node/src/command/start.rs
minor improvements to comments / docs
rename some vars and more logical bisection in cmd
8c5a779
to
5cd3724
Compare
* adr-002 lite client (#54) * adr-002 lite client * finish adr * address Dev's comments * lite -> light * Apply suggestions from code review Co-Authored-By: Ismail Khoffi <Ismail.Khoffi@gmail.com> * updates from review * Apply suggestions from code review Co-Authored-By: Ismail Khoffi <Ismail.Khoffi@gmail.com> * update for better abstraction and latest changes * note about detection * update image. manager -> syncer * update image * update image * More detailed diagram of lite client data flow (#106) * refactor * refactor into more adrs * minor fixes from review * sync adr-003 with latest and call it * rust code blocks Co-authored-by: Ismail Khoffi <Ismail.Khoffi@gmail.com> Co-authored-by: jibrown <jackie.ilana.brown@gmail.com> * working on adr-004 Co-authored-by: Ismail Khoffi <Ismail.Khoffi@gmail.com> Co-authored-by: jibrown <jackie.ilana.brown@gmail.com>
What's needed to move this into Ready for Review? Would be awesome to get merged so future work (eg fork detection) can be based on it |
I haven't tested it against a running node. I think everything that worked in the previous main.rs is still working as before though (only we have config flags / can have config files now). I'll move this ready to review now. |
Have a bunch of merge conflicts now. Will resolve them after I resolved those in #142 . |
…issify_lite_node # Conflicts: # tendermint-lite/src/main.rs
…issify_lite_node # Conflicts: # tendermint-lite/src/main.rs
light-node/src/commands/start.rs
Outdated
Ok(()) | ||
} | ||
|
||
fn block_on<F: Future>(future: F) -> F::Output { |
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.
Have you considered not building a new runtime on each call?
You could probably do something like:
lazy_static! {
pub static ref RUNTIME: Runtime = { Builder::new()
.basic_scheduler()
.enable_all()
.build()
.unwrap() };
}
fn block_on<F: Future>(future: F) -> F::Output {
RUNTIME.block_on(future)
}
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.
You might want to check out abscissa_tokio
which allows you to launch the Tokio runtime as an Abscissa component (so you can spawn things onto it during application startup if you so desire) and boot the runtime using:
https://docs.rs/abscissa_tokio/0.5.1/abscissa_tokio/#add-tokiocomponent-to-your-abscissa-application
use crate::application::APPLICATION;
impl Runnable for StartCmd {
fn run(&self) {
abscissa_tokio::run(&APPLICATION, async {
println!("now running inside the Tokio runtime");
});
}
}
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.
It seems the current approach is to block on the future in the current thread, I assume the solution linked to above spawns the future onto Tokio asynchronously instead? It might be useful and it would seem like a change from the current approach.
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 think you are right @gterzian.
Note that currently there is only one call to this particular block_on
method and runtime. But yes, we need to do this properly throughout the repo. We currently copy&pasted this throughout the repo when async/await was introduced here.
Currently the rpc integration tests, above start command and the requester use this approach. Maybe worth to have a closer look into this in a separate issue, too?
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.
@gterzian the semantics are the same, but yes it would use the Tokio executor.
You can make it synchronous by replacing block_on
with await
to wait for the future to complete, otherwise the semantics are the same (except with async/await, you can add async behavior in the future)
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 think it's worth discussing the overall approach in a separate issue(it shouldn't matter much to create a new runtime on each call for now).
Yes if we call await
from inside an async context we'll get the equivalent of the current block_on
, so if we run the entire application on Tokio, we could indeed use await
instead of block_on
, and I think the tricky part is block_on
is currently not called from an async context?
Probably best to keep the current block_on
, and then figure out how we want to run the light client.
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.
@@ -45,3 +45,47 @@ one correct full node in order to detect conflicts in a timely fashion. We keep | |||
this mechanism simple for now, but in the future a more advanced peer discovery | |||
mechanism may be utilized. | |||
|
|||
|
|||
#### Sequential Sync |
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.
Should this be split into it's own PR?
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.
Sure! It was a separate PR (see #148) but can definitely be broken out again if it makes sense.
Reading through the last comments it seems like we are more or less OK with the imperfect state of this PR (most objections broken out into follow up issues). It also seems that keeping it un-merged is a liability. Unless there are concrete objections in the next day or so I'm gunna go ahead and merge this. |
Agree with @brapse here. Review and merge as soon as possible makes sense. There is probably a lot to followup on. E.g. writing and enabling some acceptance / integration tests that run this against an actual tendermint instance is a major piece that is missing, even for an MVP. But we can followup on this leveraging the outcome of #120. |
…issify_lite_node # Conflicts: # tendermint-lite/src/main.rs
FYI, if you do end up merging #171 you'll almost certainly want to use |
Just merged #171. I'll look into |
…issify_lite_node # Conflicts: # tendermint-lite/Cargo.toml # tendermint-lite/src/main.rs
impl Runnable for StartCmd { | ||
/// Start the application. | ||
fn run(&self) { | ||
if let Err(err) = abscissa_tokio::run(&APPLICATION, async { |
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.
Perhaps add a comment here about what this does? I assume spawning a task to run the async block? What kind of runtime does it start, threaded or current thread? If threaded, how many? I'd say we just need a basic scheduler for now as in https://docs.rs/tokio/0.1.20/tokio/runtime/current_thread/index.html
If we do want to parallelize some operations, I'm not sure a threaded tokio runtime is the way to do it, we might rather want to use our own thread-pool, something like rayon, or something entirely different.
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 runtime is started as an Abscissa component. You can use whatever runtime you'd like... see the From<Runtime>
impl on TokioComponent
:
https://docs.rs/abscissa_tokio/0.5.1/abscissa_tokio/struct.TokioComponent.html
Right now it's using the default, which is equivalent to tokio::runtime::Runtime::new()
:
By using an Abscissa component to manage the runtime, other components can spawn additional tasks on the reactor or leverage other integrations (e.g. tracing, which Zebra is using extensively)
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.
Thanks for this. Will look forward the the next iterations of this mentioned in the comments and follow up issues 🙌
ref #112