-
Notifications
You must be signed in to change notification settings - Fork 8
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
feat: add initial ethereum light client #150
feat: add initial ethereum light client #150
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #150 +/- ##
=======================================
Coverage 96.83% 96.83%
=======================================
Files 11 11
Lines 537 537
=======================================
Hits 520 520
Misses 17 17 ☔ View full report in Codecov by Sentry. |
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 not really a review but some early suggestions
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.
Added some comments and explanations + in the PR itself described what is covered and not.
# dev-dependencies | ||
cw-multi-test = { version = "2.2.0", default-features = false } | ||
milagro_bls = { git = "https://github.com/Snowfork/milagro_bls", rev = "bc2b5b5e8d48b7e2e1bfaa56dc2d93e13cb32095", default-features = false } # Only used for testing, not to be used in production! | ||
|
||
[patch.crates-io] |
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 these patches actually be moved to where they are needed only? Not sure if it's a great idea to do SP1 specific patching on the workspace level?
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 patches only work in the top level. Happy to move it lower if a PR can make that work
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.
Yeah, seems like it is not possible. We should be very sure that this will not create any issues because it seems less than ideal to have to pin to these patches for all packages here :/
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 shouldn't because sp1 is the most security critical part of our code. Given that we would use these patches in the sp1 programs, it doesn't matter whether other apps use these or not. They shouldn't be changing functionality if the target isn't riscv anyway
@@ -439,3 +440,12 @@ func (s *TestSuite) CreateTMClientHeader( | |||
TrustedValidators: oldHeader.TrustedValidators, | |||
} | |||
} | |||
|
|||
func (s *TestSuite) GetTopLevelTestName() string { |
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.
Used to create the rust fixture file names.
generateFixtures bool | ||
// Whether to generate fixtures for tests or not | ||
generateSolidityFixtures bool | ||
rustFixtureGenerator *types.RustFixtureGenerator |
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 decided to create a "persistent" generator so that I could create fixtures that are numbered in the order they happen (to be able to run them like that in unit tests as well).
@@ -116,23 +116,23 @@ deploy-sp1-ics07: genesis-sp1-ics07 | |||
generate-fixtures-solidity: clean |
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 add the rust fixtures here in #143
Did not want to add them just yet because the output is not 100% compatible until the issue over is done.
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.
Hmm. Can we still add a separate recipe generate-fixtures-rust
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.
Yeah, I did mean adding it as a separate recipe in #143
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.
Can we add it in this PR? Given that the fixtures are added in this 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.
I'll add them in #143 because I don't know which ones we will need and how much tweaking is needed for them to be fully functional. They will also be compressed like we talked about, so we don't have to have all those files. The recipe doesn't add any value at this point.
@@ -0,0 +1,382 @@ | |||
use core::{ |
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 copied in from union for convenience, but it should be cleaned up or removed eventually. Tracking that in #147
depth: {depth}, index: {index}, root: {root}, found: {found})", | ||
branch = .branch.iter().map(ToString::to_string).collect::<Vec<_>>().join(", ") | ||
)] | ||
pub struct InvalidMerkleBranch { |
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 am a bit ambivalent about this one. It is very convenient when debugging issues, but it is quite a large error. I added this a long time ago after some long painful debugging sessions with the union light client.
Maybe we should have like a "debug" feature flag or something that enables more output and info. Not sure...
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.
Why is this not a part of the enum
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.
Mostly just to be able to box it, since it is big ^^ Does not need to be separate for any other reason
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.
Can we add it into the enum then
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.
Not in its current form, it causes a warning for too big error type - so that is why the box is there.
@@ -0,0 +1,162 @@ | |||
use alloy_primitives::{aliases::B32, Bloom, Bytes, FixedBytes, B256}; |
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.
A lot of these wrapped types are added to enable tree_hash_root in special corner cases where tree_hash_derive did not work properly for some reason. I think it might be possible to have way fewer of these, but I didn't manage in a reasonable time and didn't want to spend too much time on it right now. Tracking in #147
programs/08-wasm-eth/src/contract.rs
Outdated
@@ -0,0 +1,649 @@ | |||
use std::convert::Into; |
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.
Quite a lot of things to improve here, but I mostly added it to be able to test building and checking the wasm file to make sure I didn't have any bad dependencies and so on. It will be cleaned up and done proper in #143
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.
That goes for all the files in programs/08-wasm-eth, really. It does seem to work pretty well already though :)
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 did my first pass. I found some structural improvements, some inaccuracies related to the ibc-go's 08-wasm interface.
The lack of documentation made it difficult to review at times, currently, in our project, all other crates require documentation on public interfaces. And it will become more difficult to introduce docs as time passes (since codebase grows). So I think it would be good to address it sooner rather than later.
Given the fact that it doesn't fully function yet, missing docs, and uncertainties around some crates. It seems it would be better to have a feature branch until POS e2e's pass and docs are added. I also want to start contributing to the feature branch if we have one. What do you think?
.github/workflows/rust.yml
Outdated
uses: actions-rs/cargo@v1 | ||
with: | ||
command: run-script | ||
args: build-08-wasm-eth |
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 we shouldn't be building with docker in this CI, and use the rust toolchain instead. I'm also not a fan of using cargo scripts. justfile
should suffice
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 the docker build to actually verify that we can build the optimized wasm file and then verify it. I don't see any issues with building with docker in CI here?
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.
There aren't any issues. the docker uses a specific version of rust whereas I'd like us to use the latest stable. That's all
programs/08-wasm-eth/src/contract.rs
Outdated
QueryMsg::VerifyClientMessage(verify_client_message_msg) => { | ||
verify_client_message(deps, env, verify_client_message_msg) | ||
} | ||
QueryMsg::CheckForMisbehaviour(_) => check_for_misbehaviour(), | ||
QueryMsg::TimestampAtHeight(_) => timestamp_at_height(env), | ||
QueryMsg::Status(_) => status(), |
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.
These should all be moved to a query
submodule
QueryMsg::VerifyClientMessage(verify_client_message_msg) => { | |
verify_client_message(deps, env, verify_client_message_msg) | |
} | |
QueryMsg::CheckForMisbehaviour(_) => check_for_misbehaviour(), | |
QueryMsg::TimestampAtHeight(_) => timestamp_at_height(env), | |
QueryMsg::Status(_) => status(), | |
QueryMsg::VerifyClientMessage(verify_client_message_msg) => { | |
query::verify_client_message(deps, env, verify_client_message_msg) | |
} | |
QueryMsg::CheckForMisbehaviour(_) => query::check_for_misbehaviour(), | |
QueryMsg::TimestampAtHeight(_) => query::timestamp_at_height(env), | |
QueryMsg::Status(_) => query::status(), |
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, but not necessary in this PR. The wasm client itself will be cleaned up and made proper in #143
|
||
#[derive(serde::Serialize, serde::Deserialize, Clone)] | ||
#[serde(rename_all = "snake_case")] | ||
pub enum EthereumCustomQuery { |
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 this?
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 for the custom query to bls verification (BlsVerify)
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 sucks. Should we create an issue to try and do this fully in wasm?
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.
Would love that. I don't want us to write this ourselves, but created an issue for it: #163
If Union didn't want to do it rewrite it themselves, I doubt we should :D
There is a rust library we use for tests (same that Union uses for their tests): https://github.com/Snowfork/milagro_bls, but it is not production ready (big warning on the repo about that).
Co-authored-by: srdtrk <59252793+srdtrk@users.noreply.github.com>
Co-authored-by: srdtrk <59252793+srdtrk@users.noreply.github.com>
I believe the most relevant issues have been fixed at this point. I have commented on those that will be covered in separate issues so we can get this merged and not sit with a big PR over a long time that will get conflicts and get out of hand to both review and keep track of all the comments. |
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 the updates. I think we can merge this before all the POS e2es are passing, but it'd be great to address a couple more issues before merging. Some of the issues I commented on and also:
- Updating repo
README.md
to include a bit of info about the eth light client and mentioning that it is WIP (⏳) - Adding a
README.md
inprograms/cw-ics08-wasm-eth/
which gives more info about the light client and mentions that it is WIP. - Yes, adding docs on everything will not be necessary. Since we expect large changes in
ethereum-utils
,tree_hash
, and others, so it makes sense to not add docs there. But I think we should still add docs onethereum-light-client
andcw-ics08-wasm-eth
to make it easier to read. - It'd also be great if we could reduce the number of fixtures (by merging them), but we can defer it if it is somehow difficult.
|
||
#[derive(serde::Serialize, serde::Deserialize, Clone)] | ||
#[serde(rename_all = "snake_case")] | ||
pub enum EthereumCustomQuery { |
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 sucks. Should we create an issue to try and do this fully in wasm?
depth: {depth}, index: {index}, root: {root}, found: {found})", | ||
branch = .branch.iter().map(ToString::to_string).collect::<Vec<_>>().join(", ") | ||
)] | ||
pub struct InvalidMerkleBranch { |
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.
Can we add it into the enum then
# dev-dependencies | ||
cw-multi-test = { version = "2.2.0", default-features = false } | ||
milagro_bls = { git = "https://github.com/Snowfork/milagro_bls", rev = "bc2b5b5e8d48b7e2e1bfaa56dc2d93e13cb32095", default-features = false } # Only used for testing, not to be used in production! | ||
|
||
[patch.crates-io] |
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 shouldn't because sp1 is the most security critical part of our code. Given that we would use these patches in the sp1 programs, it doesn't matter whether other apps use these or not. They shouldn't be changing functionality if the target isn't riscv anyway
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.
Can we add a README.md in this directory to provide some info about cw-ics08-wasm-eth
and mention that it is work-in-progress.
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.
Yeah, that makes sense, will do that 👍
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.
Done
pub fn get_active_sync_committee(&self) -> ActiveSyncCommittee { | ||
if let Some(sync_committee) = &self.current_sync_committee { | ||
ActiveSyncCommittee::Current(sync_committee.clone()) | ||
} else if let Some(sync_committee) = &self.next_sync_committee { | ||
ActiveSyncCommittee::Next(sync_committee.clone()) | ||
} else { | ||
ActiveSyncCommittee::default() | ||
} | ||
} |
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 is not an enum in TrustedSyncCommittee
, instead it is a pair of options which we only expect one to be present, right?
// | ||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#process_light_client_update | ||
pub fn validate_signature_supermajority(&self) -> bool { | ||
self.num_sync_committe_participants() * 3 >= self.sync_committee_bits.len() * 8 * 2 |
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 you merged my suggestion. So are we sure I was correct? I'm a bit confused about whether this comes from union or where?
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 did, but the types have changed, which is where the problem came from. It was correct, but it still needs better unit testing which will be done later
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.
Added unit tests for it, your fix was correct
bls_verifier: V, | ||
) -> Result<(), EthereumIBCError> { | ||
// Verify sync committee has sufficient participants | ||
ensure( |
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.
Then we would have to use this in the entire project (not just the ethereum light client) for consistency. I don't want to have multiple ways of asserting things in the repo. Moreover, something like this would make more sense as a macro rather than a function.
Did you base this upon an example from another repo?
.clone() | ||
.unwrap_or_default() | ||
.into(), | ||
floorlog2(NEXT_SYNC_COMMITTEE_INDEX), |
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.
Don't you already have a constant for this NEXT_SYNC_COMMITTEE_BRANCH_SIZE
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.
Yup! Have moved them all and using them everywhere now.
validate_merkle_branch( | ||
get_lc_execution_root(client_state, header), | ||
header.execution_branch.0.into(), | ||
floorlog2(EXECUTION_PAYLOAD_INDEX), |
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.
There is a constant for this EXECUTION_BRANCH_SIZE
right?
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.
Good point. Will go through them and see if I can consolidate and get rid of floorlog2
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 just noticed that floorlog2 has some extra safety added in. Not sure if we want to have that?
/// Convenience function safely to call [`u64::ilog2`] and convert the result into a usize.
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
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 kept the floorlog2, but only using it inside the config.rs which needs to be cleaned up anyway. I think this is fine for now at least. The rest of the code does not use it.
wrappers::{WrappedBloom, WrappedBranch, WrappedBytes}, | ||
}; | ||
|
||
const EXECUTION_BRANCH_SIZE: usize = floorlog2(EXECUTION_PAYLOAD_INDEX); |
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.
Some of the places where floorlog2
is used could actually reuse these constants. Made comments about those as well
.github/workflows/rust.yml
Outdated
# checks that the wasm binary is a proper cosmwasm smart contract | ||
# it checks for things like memories, exports, imports, available capabilities, and non-determinism | ||
- name: Check cosmwasm file | ||
run: cosmwasm-check artifacts/cw_08_wasm_etheruem_light_client.wasm |
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.
Name of the file should have changed
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.
Indeed!
@srdtrk Take a look now. I think this can be merged unless there are any big issues. |
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.
Lgtm now. I refactored and added full rustdocs to:
ethereum-light-client
ethereum-trie-db
cw-ics08-wasm-eth
So, I'd like you to review my changes. Make improvements to docs if you see the need, and then you can merge the PR
I reviewed the changes and I think it looks good! Thank you for the effort you put in! I will want to have a discussion at some point on documentation, because I think we end up with a lot of things like this, which is adding noice with no value, as far as I can tell: /// the value name
pub value_name: Type But this goes for the entire repo, so it's a broader discussion, and for now it's better to be consistent :) |
Yes but in general, all public interfaces should have rustdocs. There are also many other fields that are very ambiguous without rustdocs and I find hard to review. I don't think we should every attempt to change this @gjermundgaraba And sometimes, the variable names are not fully self explanotary. I'd argue that the example you gave is still not very well documented since I have no idea what it is referring to from the snippet you gave. The documentation I wrote could still be improved a lot, for example, I found: /// The time of genesis
pub genesis_time: u64, But the docs should actually be mentioning whether it is in seconds or nanoseconds or something else. So we can do another pass once the crate is more finalized |
That is fair. Perhaps the solution is indeed to just have docs that actually bring some useful information. :) |
Description
closes: #142
What is not covered here:
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
godoc
comments.Files changed
in the GitHub PR explorer.SonarCloud Report
in the comment section below once CI passes.