Skip to content

Commit

Permalink
feat(stdlib)!: eddsa function using turbofish (#5050)
Browse files Browse the repository at this point in the history
# Description

## Problem\*

Resolves #4514 

## Summary\*

This updates `eddsa_verify_with_hasher` to have the following signature
now that we support the turbofish operator:
```rust
pub fn eddsa_verify_with_hasher<H>(
    pub_key_x: Field,
    pub_key_y: Field,
    signature_s: Field,
    signature_r8_x: Field,
    signature_r8_y: Field,
    message: Field
) -> bool 
where H: Hasher + Default {
  [function body ...]
}
``` 
This re-work was only possible with further bug fixes from
#5049 and
#5041. The original turbofish PR
can be found here (#3542).

## Additional Context

This PR can most likely be merged into its parent #5049 but I just made
this separate PR to separate the bug fix and the stdlib library breaking
change.

## Documentation\*

Check one:
- [ ] No documentation needed.
- [x] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.

---------

Co-authored-by: Jake Fecher <jake@aztecprotocol.com>
Co-authored-by: Jake Fecher <jfecher11@gmail.com>
Co-authored-by: Tom French <tom@tomfren.ch>
  • Loading branch information
4 people committed May 21, 2024
1 parent fd772e7 commit 7936262
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ Verifier for EdDSA signatures
fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool
```

It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following:
It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify` function by passing a type implementing the Hasher trait with the turbofish operator.
For instance, if you want to use Poseidon2 instead, you can do the following:
```rust
use dep::std::hash::poseidon2::Poseidon2Hasher;

let mut hasher = Poseidon2Hasher::default();
eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher);
eddsa_verify::<Poseidon2Hasher>(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg);
```

<BlackBoxInfo />
Expand Down
27 changes: 13 additions & 14 deletions noir_stdlib/src/eddsa.nr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::ec::consts::te::baby_jubjub;
use crate::ec::tecurve::affine::Point as TEPoint;
use crate::hash::{Hash, Hasher, BuildHasher, BuildHasherDefault};
use crate::hash::poseidon::PoseidonHasher;
use crate::default::Default;

// Returns true if signature is valid
pub fn eddsa_poseidon_verify(
Expand All @@ -13,28 +14,25 @@ pub fn eddsa_poseidon_verify(
signature_r8_y: Field,
message: Field
) -> bool {
let mut hasher = PoseidonHasher::default();
eddsa_verify_with_hasher(
eddsa_verify::<PoseidonHasher>(
pub_key_x,
pub_key_y,
signature_s,
signature_r8_x,
signature_r8_y,
message,
&mut hasher
message
)
}

pub fn eddsa_verify_with_hasher<H>(
pub fn eddsa_verify<H>(
pub_key_x: Field,
pub_key_y: Field,
signature_s: Field,
signature_r8_x: Field,
signature_r8_y: Field,
message: Field,
hasher: &mut H
message: Field
) -> bool
where H: Hasher {
where H: Hasher + Default {
// Verifies by testing:
// S * B8 = R8 + H(R8, A, m) * A8
let bjj = baby_jubjub();
Expand All @@ -47,12 +45,13 @@ where H: Hasher {
// Ensure S < Subgroup Order
assert(signature_s.lt(bjj.suborder));
// Calculate the h = H(R, A, msg)
signature_r8_x.hash(hasher);
signature_r8_y.hash(hasher);
pub_key_x.hash(hasher);
pub_key_y.hash(hasher);
message.hash(hasher);
let hash: Field = (*hasher).finish();
let mut hasher: H = H::default();
hasher.write(signature_r8_x);
hasher.write(signature_r8_y);
hasher.write(pub_key_x);
hasher.write(pub_key_y);
hasher.write(message);
let hash: Field = hasher.finish();
// Calculate second part of the right side: right2 = h*8*A
// Multiply by 8 by doubling 3 times. This also ensures that the result is in the subgroup.
let pub_key_mul_2 = bjj.curve.add(pub_key, pub_key);
Expand Down
5 changes: 2 additions & 3 deletions test_programs/execution_success/eddsa/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use dep::std::compat;
use dep::std::ec::consts::te::baby_jubjub;
use dep::std::ec::tecurve::affine::Point as TEPoint;
use dep::std::hash;
use dep::std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify, eddsa_verify_with_hasher};
use dep::std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify, eddsa_verify};
use dep::std::hash::poseidon2::Poseidon2Hasher;

fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) {
Expand Down Expand Up @@ -50,7 +50,6 @@ fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) {
// User A's signature over the message can't be used with another message
assert(!eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg + 1));
// Using a different hash should fail
let mut hasher = Poseidon2Hasher::default();
assert(!eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher));
assert(!eddsa_verify::<Poseidon2Hasher>(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg));
}
}

0 comments on commit 7936262

Please sign in to comment.