-
Notifications
You must be signed in to change notification settings - Fork 84
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
Conversation
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 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
// 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 { |
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.
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.
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.
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.
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.
Ah, I wasn't aware the chain config was immutable between upgrades. What's the reasoning for 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.
It's meant to be immutable configuration for the block_chain. Part of blockchain the safety concerns I think.
cc46f2a
to
1f1615e
Compare
fc0cab9
to
5756051
Compare
910ce81
to
f7926c1
Compare
proposal_state.block_merkle_tree.commitment(), | ||
proposal.block_merkle_tree_root() | ||
); | ||
// ValidatedTransition::new( |
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.
Is this intentionally left commented out?
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.
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> { |
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 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.
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.
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.
types/src/v0/impls/state.rs
Outdated
.. | ||
} = state; | ||
// Validate timestamp hasn't drifted too much from system time. | ||
// Do this check first so we don't add unnecessary drift. |
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.
Nit: comment is now potentially misleading because in this function the drift check is done last.
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 can move the comment about this check being time sensitive up to the doc string of validate_timestamp
.
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.
#[derive(Debug)] | ||
pub(crate) struct Proposal<'a> { | ||
header: &'a Header, | ||
block_size: u32, |
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 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 🙄
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.
🤔
types/src/v0/impls/state.rs
Outdated
self.validate_fee()?; | ||
self.validate_fee_merkle_tree()?; | ||
self.validate_block_merkle_tree()?; | ||
self.validate_proposed_finalized()?; |
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.
self.validate_proposed_finalized()?; | |
self.validate_l1_finalized()?; |
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.
|
||
charge_fee( | ||
&mut validated_state, | ||
validated_state.charge_fees( |
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 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. |
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.
/// Replaces builder signature w/ invalid one. | |
/// Replaces builder signature w/ a valid one from a random key pair |
?
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 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).
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.
Thinking again I see your point... The signature is structurally valid but will fail verification.
types/src/v0/impls/state.rs
Outdated
} | ||
|
||
impl<'a> ValidatedTransition<'a> { | ||
async fn mock(instance: NodeState, parent: &'a Header, proposal: Proposal<'a>) -> 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.
Remove 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.
types/src/v0/impls/state.rs
Outdated
@@ -1259,4 +1855,112 @@ mod test { | |||
|
|||
validate_builder_fee(&header).unwrap(); | |||
} | |||
|
|||
// #[async_std::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.
Commented 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.
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. I think this is a great improvement in terms of readability. Just some suggestions.
I also think @0xkato should review this PR as well.
* 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
I was going to move this test but decided not to.
and the TODO that goes w/ it
da1f3f4
to
3ea125f
Compare
Closes #2090
This PR:
Refactors contents of
validate_and_apply_header
by introducing two new internal (non-pub) types. This should facilitate:Basically this PR:
Proposal
andValidatedTransition
typesReview
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