Motivation
During the implementation of #316 we added a condition that consistency tokens started to be collapsed differently than all other instances, which in fact added a constraint to nifs::FS that now only traces with two elements in the first instance column can be collapsed. Otherwise, the behavior is undefined. This PR solves the problem of checking this restriction
Overview
The newtype pattern was used to solve the problem in this way. An example of using such a pattern is the NonZero<T> wrapper from the standard library. Now, instead of checking in all functions that involve consistency tokens, we accept vanilla::FoldablePlonkTrace instead of PlonkTrace. This type can only be created with a single constructor, which performs the trace validity check at the point of creation.
For instance:
// Old way with PlonkTrace
fn old_function(trace: &PlonkTrace) -> Result<(), Error> {
// Every use site needed to check preconditions
if trace.instances.first().map(|x| x.len()) != Some(2) {
return Err(Error::InvalidTrace);
}
// function body...
}
// New way with FoldablePlonkTrace
fn new_function(foldable_trace: &FoldablePlonkTrace) -> Result<(), Error> {
// No need for precondition checks here
// function body...
}
This pattern encapsulates the validation logic within the FoldablePlonkTrace type, ensuring that all instances of FoldablePlonkTrace are valid by construction. This approach significantly reduces verbosity and potential for error, improving both safety and readability of the code. Moreover, it ensures that the invariant (traces having two elements in the first instance column) is enforced in a single place, thus avoiding scattered checks throughout the codebase.
Here, the new method of FoldablePlonkInstance ensures that it can only be instantiated if the PlonkInstance meets the specific requirement. This is less verbose than returning an error through multiple layers of modules and provides a more accurate check compared to panicking if an implicit invariant is violated.
Motivation During the implementation of #316 we added a condition that consistency tokens started to be collapsed differently than all other instances, which in fact added a constraint to
nifs::FS
that now only traces with two elements in the first instance column can be collapsed. Otherwise, the behavior is undefined. This PR solves the problem of checking this restrictionOverview The newtype pattern was used to solve the problem in this way. An example of using such a pattern is the
NonZero<T>
wrapper from the standard library. Now, instead of checking in all functions that involve consistency tokens, we acceptvanilla::FoldablePlonkTrace
instead ofPlonkTrace
. This type can only be created with a single constructor, which performs the trace validity check at the point of creation.For instance:
This pattern encapsulates the validation logic within the
FoldablePlonkTrace
type, ensuring that all instances ofFoldablePlonkTrace
are valid by construction. This approach significantly reduces verbosity and potential for error, improving both safety and readability of the code. Moreover, it ensures that the invariant (traces having two elements in the first instance column) is enforced in a single place, thus avoiding scattered checks throughout the codebase.Here, the
new
method ofFoldablePlonkInstance
ensures that it can only be instantiated if thePlonkInstance
meets the specific requirement. This is less verbose than returning an error through multiple layers of modules and provides a more accurate check compared to panicking if an implicit invariant is violated.