-
Notifications
You must be signed in to change notification settings - Fork 67
feat: add Pedersen hash #627
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
Conversation
✅ Deploy Preview for contracts-stylus canceled.
|
✅ Deploy Preview for contracts-stylus canceled.
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
✅ All tests successful. No failed tests found. Additional details and impacted files
|
8b3af08
to
53e3f6f
Compare
53e3f6f
to
eadb81f
Compare
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 job!
First pass
lib/crypto/src/pedersen/mod.rs
Outdated
type Output = Affine<P>; | ||
|
||
/// Update the hash state with a new element. | ||
fn update(&mut self, input: impl AsRef<[u8]>) { |
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 don't think it is a good API for this kind of hash. Since after update is called you recreate U256
from variable size of bytes.
And e.g. calling update()
two times with inputs [42, 42]
and [43,43]
. Or calling it with inputs [42, 42, 0, 0]
and [43, 43]
should produce the same hash, since bytes are not padded. And [42, 42]
and [42, 42, 0, 0]
will be parsed to the same integer. So we can easily peek different set of bytes, that will produce the same hash. It is an actual vulnerability to preimage attack. I don't think we should implement Hasher
in this case (more simple) or redesign the trait and make it more generic (able to accept U256 as an argument)
I see that starknet-rs has only api where you can pass 256-bit
integer.
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.
Fair point, I removed Hasher
trait implementation.
Co-authored-by: Alisander Qoshqosh <[email protected]>
}; | ||
use stylus_sdk::prelude::*; | ||
#[entrypoint] | ||
#[storage] |
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.
}; | |
use stylus_sdk::prelude::*; | |
#[entrypoint] | |
#[storage] | |
}; | |
use stylus_sdk::prelude::*; | |
#[entrypoint] | |
#[storage] |
# | ||
# It is recommended to check this file in to source control so that | ||
# everyone who runs the test benefits from these saved cases. | ||
cc 9f552914238459525586fa596ededdce984599cffe1af7515181e7f8890fabf6 # shrinks to input = [3618502788666131219974424518481750869458896638539263116075447500599906533376] |
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 proptest regression important enough to have in repo? If this was the result on some mishap in the impl, we can remove it (this is the PR that first introduces the Pedersen hash after all); if this is a specific edge case, we can leave it in
//! This module contains pedersen hash instances for some popular curve | ||
//! instances. |
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 module contains pedersen hash instances for some popular curve | |
//! instances. | |
//! This module contains pedersen hash instances for some popular curves. |
}; | ||
#[derive(Clone, Default, PartialEq, Eq)] | ||
/// Starknet's Curve Details. | ||
pub struct StarknetCurveConfig; |
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(Clone, Default, PartialEq, Eq)] | |
/// Starknet's Curve Details. | |
pub struct StarknetCurveConfig; | |
}; | |
/// Starknet's Curve Details. | |
#[derive(Clone, Default, PartialEq, Eq)] | |
pub struct StarknetCurveConfig; |
// TODO: confirm this | ||
const COFACTOR: &'static [u64] = &[0x1]; |
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.
TODO
params: core::marker::PhantomData<F>, | ||
curve: core::marker::PhantomData<P>, |
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.
params: core::marker::PhantomData<F>, | |
curve: core::marker::PhantomData<P>, | |
params: PhantomData<F>, | |
curve: PhantomData<P>, |
nit: import PhantomData
directly instead of using absolute path repeatedly
pub mod instance; | ||
pub mod params; | ||
use alloc::{vec, vec::Vec}; |
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: place pub mod
s below imports for clarity, I almost didn't realize these modules were declared here (confused them with additional imports)
/// Constant points for Starknet Curve. | ||
static CONSTANT_POINTS: Lazy<Vec<Affine<StarknetCurveConfig>>> = Lazy::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.
A link to where these constant points were taken from would be useful, helps maintainability and review
// Starknet's base field modulus. | ||
const MODULUS: U256 = from_num!("3618502788666131213697322783095070105623107215331596699973092056135872020481"); |
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.
Link to source of this const, if not here then at the module-level docs //!
assert!(point_list.len() == F::N_ELEMENT_BITS_HASH); | ||
|
||
for pt in point_list { | ||
assert!(pt.x != point.x, "Unhashable input."); |
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 should assert!
things that must always hold for our code to be valid, the "invariants" of our code.
Otherwise returning a Result::Err
might be clearer and more in line with Rust's way of doing things.
Not saying this or any other assert should be converted to an error as I lack enough in-depth knowledge to determine whether it should be done, I'm just pointing this out so that you can determine the right approach and that we're on the same page.
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.
Approved by mistake
Solved in #644. |
Resolves #269
PR Checklist