Skip to content
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

Replica Validation Refactor #2170

Merged
merged 11 commits into from
Oct 24, 2024
Merged

Replica Validation Refactor #2170

merged 11 commits into from
Oct 24, 2024

Conversation

tbro
Copy link
Contributor

@tbro tbro commented Oct 11, 2024

Closes #2090

This PR:

Refactors contents of validate_and_apply_header by introducing two new internal (non-pub) types. This should facilitate:

  • comprehension
  • documentation
  • testing

Basically this PR:

  • adds Proposal and ValidatedTransition types
  • moves validation steps to isolated methods.
  • adds doc comments to methods
  • updates error enum
  • adds many tests

Review

Most important changes are isolated ./types/src/v0/impls/state.rs. Many unit tests have been added there. Tests should pass and you should be convinced that there is sufficient coverage. Small changes were made to ./types/src/v0/impls/header.rs where we previously had testing for this validation in the form of high level success cases and eror cases tests. The success case test has been renamed and the error case test removed in favor of the more comprehensive error case tests in the new unit tests.

Review Documentation

You can run just doc and navigate here in your browser:
./target/doc/espresso_types/v0/impls/state/struct.ValidatedTransition.html

Copy link
Member

@zacshowa zacshowa left a 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 a WIP, but I left some general discussion points from my first read. I think that this will be a great use of the type system to make validation more readable.

types/src/v0/impls/state.rs Outdated Show resolved Hide resolved
types/src/v0/impls/state.rs Outdated Show resolved Hide resolved
Comment on lines 480 to 482
// TODO 2 seconds of tolerance should be enough for reasonably
// configured nodes, but we should make this configurable.
if self.proposal.header.timestamp().abs_diff(system_time) > 2 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense for this value to live in the chain config? Given we have the chain config here, implementing this be low effort.

Copy link
Contributor Author

@tbro tbro Oct 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires some thought. Putting it in chain config means we require an upgrade to modify it. Maybe we can just pass it in on the command line.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I wasn't aware the chain config was immutable between upgrades. What's the reasoning for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's meant to be immutable configuration for the block_chain. Part of blockchain the safety concerns I think.

types/src/v0/impls/state.rs Outdated Show resolved Hide resolved
@tbro tbro force-pushed the tb/validated_state_transition_refactor branch from cc46f2a to 1f1615e Compare October 15, 2024 19:15
@tbro tbro force-pushed the tb/validated_state_transition_refactor branch from fc0cab9 to 5756051 Compare October 23, 2024 20:09
@tbro tbro marked this pull request as ready for review October 23, 2024 21:43
@tbro tbro requested review from sveitser and removed request for sveitser October 23, 2024 21:44
@tbro tbro force-pushed the tb/validated_state_transition_refactor branch from 910ce81 to f7926c1 Compare October 24, 2024 00:50
proposal_state.block_merkle_tree.commitment(),
proposal.block_merkle_tree_root()
);
// ValidatedTransition::new(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intentionally left commented out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Humm I thought this was previously commented in relation to the above TODO... Maybe I got confused will double check.

}
/// Type to hold cloned validated state and provide validation methods.
#[derive(Debug)]
pub(crate) struct ValidatedTransition<'a> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of a nitpick: the transition is only validated if validate() does not return an error but given current naming one might expect it to be validated upon creation unless one actually inspects the return type. I'm totally fine with the current name just thinking maybe we can make it even clearer at some point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its a tough one. It's a type that only exists to facilitate a state transition by encapsulating validation logic. The state is actually held in ValidatedState. Open to ideas, but I don't have any at the time being.

..
} = state;
// Validate timestamp hasn't drifted too much from system time.
// Do this check first so we don't add unnecessary drift.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: comment is now potentially misleading because in this function the drift check is done last.

Copy link
Collaborator

@sveitser sveitser Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can move the comment about this check being time sensitive up to the doc string of validate_timestamp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[derive(Debug)]
pub(crate) struct Proposal<'a> {
header: &'a Header,
block_size: u32,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also a Proposal type in hotshot that we use in this repo, so I think we can use a different name here. ProposalValidationInput? A bit of a mouthful 🙄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔

self.validate_fee()?;
self.validate_fee_merkle_tree()?;
self.validate_block_merkle_tree()?;
self.validate_proposed_finalized()?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self.validate_proposed_finalized()?;
self.validate_l1_finalized()?;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


charge_fee(
&mut validated_state,
validated_state.charge_fees(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do the fee charging as part of apply_proposal?

Header::V3(_) => panic!("You called `Header.next()` on unimplemented version (v3)"),
}
}
/// Replaces builder signature w/ invalid one.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Replaces builder signature w/ invalid one.
/// Replaces builder signature w/ a valid one from a random key pair

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent is convey that signature validation will fail because we are adding a signature that doesn't match the fee_info. It is therefore invalid (relative to what it will be validated against).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking again I see your point... The signature is structurally valid but will fail verification.

}

impl<'a> ValidatedTransition<'a> {
async fn mock(instance: NodeState, parent: &'a Header, proposal: Proposal<'a>) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove async?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -1259,4 +1855,112 @@ mod test {

validate_builder_fee(&header).unwrap();
}

// #[async_std::test]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

@sveitser sveitser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I think this is a great improvement in terms of readability. Just some suggestions.

I also think @0xkato should review this PR as well.

@sveitser sveitser requested a review from 0xkato October 24, 2024 10:25
tbro and others added 7 commits October 24, 2024 10:38
  * add `Proposal` and `ValidatedTransition` types
  * move validation to isolated methods.
  * add doc comments to methods
  * update error enum
  * update tests

  * less clones
  * only get vid byte len once
Replace references to `validate_proposal` /w
`ValidatedTransition`. Remove `validate_proposal_error_cases` as it
nightmarish to navigate that and error cases are more thoroughly tested
in unit tests now.
`validate_proposal` fn no longer exists
- Move the validate function to the top so it shows up first in docs.
- Try to provide more context in doc strings.
now hotshot prints the same thing
Rename `validate_proposed_finalized()` to `self.validate_l1_finalized()`
tbro added 4 commits October 24, 2024 10:38
I was going to move this test but decided not to.
and the TODO that goes w/ it
@tbro tbro force-pushed the tb/validated_state_transition_refactor branch from da1f3f4 to 3ea125f Compare October 24, 2024 16:39
@tbro tbro merged commit 4144ba4 into main Oct 24, 2024
13 checks passed
@tbro tbro deleted the tb/validated_state_transition_refactor branch October 24, 2024 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Review and refactor state validation logic
3 participants