From c68a49a9e83a652aa50efccff7a7dc660e54b77e Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 16 Sep 2024 10:53:43 +0100 Subject: [PATCH] chore: update to target nargo 0.34.0 --- .github/NIGHTLY_CANARY_DIED.md | 8 ++++ .github/workflows/nightly-canary.yml | 43 +++++++++++++++++++++ .github/workflows/test.yml | 33 +++++++++------- Nargo.toml | 4 +- src/bjj.nr | 16 ++++++-- src/lib.nr | 58 ++++++++++++++-------------- src/scalar_field.nr | 17 +++----- src/test.nr | 3 -- 8 files changed, 117 insertions(+), 65 deletions(-) create mode 100644 .github/NIGHTLY_CANARY_DIED.md create mode 100644 .github/workflows/nightly-canary.yml diff --git a/.github/NIGHTLY_CANARY_DIED.md b/.github/NIGHTLY_CANARY_DIED.md new file mode 100644 index 0000000..f72f3e1 --- /dev/null +++ b/.github/NIGHTLY_CANARY_DIED.md @@ -0,0 +1,8 @@ +--- +title: "Tests fail on latest Nargo nightly release" +assignees: TomAFrench +--- + +The tests on this Noir project have started failing when using the latest nightly release of the Noir compiler. This likely means that there have been breaking changes for which this project needs to be updated to take into account. + +Check the [{{env.WORKFLOW_NAME}}]({{env.WORKFLOW_URL}}) workflow for details. \ No newline at end of file diff --git a/.github/workflows/nightly-canary.yml b/.github/workflows/nightly-canary.yml new file mode 100644 index 0000000..fb614ee --- /dev/null +++ b/.github/workflows/nightly-canary.yml @@ -0,0 +1,43 @@ +name: Noir Nightly Canary + +on: + schedule: + # Run a check at 9 AM UTC + - cron: "0 9 * * *" + +env: + CARGO_TERM_COLOR: always + +permissions: + issues: write + +jobs: + test: + name: Test on Nargo ${{matrix.toolchain}} + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Install Nargo + uses: noir-lang/noirup@v0.1.3 + with: + toolchain: nightly + + - name: Run Noir tests + run: nargo test + + - name: Run formatter + run: nargo fmt --check + + - name: Alert on dead links + uses: JasonEtco/create-an-issue@v2 + if: ${{ failure() }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WORKFLOW_NAME: ${{ github.workflow }} + WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + update_existing: true + filename: .github/NIGHTLY_CANARY_DIED.md + \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 58d31fc..d8ab990 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,16 +3,20 @@ name: Noir tests on: push: branches: - - master + - main pull_request: env: CARGO_TERM_COLOR: always - NARGO_VERSION: 0.32.0 jobs: test: + name: Test on Nargo ${{matrix.toolchain}} runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + toolchain: [nightly, 0.34.0] steps: - name: Checkout sources uses: actions/checkout@v4 @@ -20,22 +24,21 @@ jobs: - name: Install Nargo uses: noir-lang/noirup@v0.1.3 with: - toolchain: $NARGO_VERSION + toolchain: ${{ matrix.toolchain }} - name: Run Noir tests run: nargo test - # Disabled as the formatter panics - # format: - # runs-on: ubuntu-latest - # steps: - # - name: Checkout sources - # uses: actions/checkout@v4 + format: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 - # - name: Install Nargo - # uses: noir-lang/noirup@v0.1.3 - # with: - # toolchain: $NARGO_VERSION + - name: Install Nargo + uses: noir-lang/noirup@v0.1.3 + with: + toolchain: 0.34.0 - # - name: Run formatter - # run: nargo fmt --check \ No newline at end of file + - name: Run formatter + run: nargo fmt --check diff --git a/Nargo.toml b/Nargo.toml index 3310487..de6d9ac 100644 --- a/Nargo.toml +++ b/Nargo.toml @@ -2,6 +2,6 @@ name = "edwards" type = "lib" authors = [""] -compiler_version = ">=0.32.0" +compiler_version = ">=0.34.0" -[dependencies] \ No newline at end of file +[dependencies] diff --git a/src/bjj.nr b/src/bjj.nr index 12a4171..78b238c 100644 --- a/src/bjj.nr +++ b/src/bjj.nr @@ -3,8 +3,16 @@ use crate::Curve; struct BabyJubJubParams {} impl TECurveParameterTrait for BabyJubJubParams { - fn a() -> Field { 168700 } - fn d() -> Field { 168696 } - fn gen() -> (Field, Field) { (0x0bb77a6ad63e739b4eacb2e09d6277c12ab8d8010534e0b62893f3f6bb957051, 0x25797203f7a0b24925572e1cd16bf9edfce0051fb9e133774b3c257a872d7d8b)} + fn a() -> Field { + 168700 + } + fn d() -> Field { + 168696 + } + fn gen() -> (Field, Field) { + ( + 0x0bb77a6ad63e739b4eacb2e09d6277c12ab8d8010534e0b62893f3f6bb957051, 0x25797203f7a0b24925572e1cd16bf9edfce0051fb9e133774b3c257a872d7d8b + ) + } } -type BabyJubJub = Curve; \ No newline at end of file +type BabyJubJub = Curve; diff --git a/src/lib.nr b/src/lib.nr index a7878af..0fed608 100644 --- a/src/lib.nr +++ b/src/lib.nr @@ -2,7 +2,6 @@ mod scalar_field; mod test; mod bjj; -use dep::std; use crate::scalar_field::ScalarField; struct Curve { @@ -70,7 +69,7 @@ impl std::ops::Add for Curve where Params: TECurveParameterTrait * * Cost: 7 gates **/ - fn add(self, other:Self) -> Self { + fn add(self, other: Self) -> Self { Curve::add_internal(self, other, Params::a(), Params::d()) } } @@ -82,7 +81,7 @@ impl std::ops::Neg for Curve where Params: TECurveParameterTrait * Cost: usually 0, will cost 1 gate if the `x` coordinate needs to be converted into a witness **/ fn neg(self) -> Self { - Curve{ x: -self.x, y: self.y } + Curve { x: -self.x, y: self.y } } } @@ -92,7 +91,7 @@ impl std::ops::Sub for Curve where Params: TECurveParameterTrait * * Cost: 7 gates **/ - fn sub(self, other:Self) -> Self { + fn sub(self, other: Self) -> Self { Curve::add_internal(self, other.neg(), Params::a(), Params::d()) } } @@ -103,7 +102,7 @@ impl std::cmp::Eq for Curve where Params: TECurveParameterTrait * * Cost: 6 gates **/ - fn eq(self, other:Self) -> bool { + fn eq(self, other: Self) -> bool { (self.x == other.x) & (self.y == other.y) } } @@ -116,7 +115,7 @@ impl std::convert::From<(Field, Field)> for Curve where Params: * Cost: 0 gates **/ fn from((x, y): (Field, Field)) -> Self { - Curve{ x, y } + Curve { x, y } } } @@ -132,7 +131,7 @@ impl CurveTrait for Curve where Params: TECurveParameter * Cost: 3 gates **/ fn new(x: Field, y: Field) -> Self { - let result = Curve{ x, y }; + let result = Curve { x, y }; result.assert_is_on_curve(); result } @@ -142,16 +141,18 @@ impl CurveTrait for Curve where Params: TECurveParameter * * Cost: 0 gates **/ - fn zero() -> Self { Curve{ x: 0, y: 1 } } + fn zero() -> Self { + Curve { x: 0, y: 1 } + } /** * @brief return the Generator of the group * * Cost: 0 gates (assuming Params trait returns values known at compile time!) **/ - fn one() -> Self { + fn one() -> Self { let (x, y) = Params::gen(); - Curve{ x, y } + Curve { x, y } } /** @@ -195,7 +196,7 @@ impl CurveTrait for Curve where Params: TECurveParameter let t2 = Params::a() * t0 + t1; let t3 = 1 + Params::d() * t0 * t1; (t2 == t3) - } + } /** * @brief compute `self + self` @@ -277,8 +278,7 @@ impl CurveTrait for Curve where Params: TECurveParameter * * TODO: use windowed non-adjacent form to remove 7 point additions per point when creating lookup table **/ - fn msm (points: [Self; N], scalars: [ScalarField; N]) -> Self - { + fn msm(points: [Self; N], scalars: [ScalarField; N]) -> Self { let a = Params::a(); let d = Params::d(); @@ -289,10 +289,10 @@ impl CurveTrait for Curve where Params: TECurveParameter } let idx = scalars[0].base4_slices[0]; - let mut accumulator: Self = Curve{ x: point_tables[0].0[idx], y: point_tables[0].1[idx] }; + let mut accumulator: Self = Curve { x: point_tables[0].0[idx], y: point_tables[0].1[idx] }; for j in 1..N { let idx = scalars[j].base4_slices[0]; - let P = Curve{ x: point_tables[j].0[idx], y: point_tables[j].1[idx] }; + let P = Curve { x: point_tables[j].0[idx], y: point_tables[j].1[idx] }; accumulator = accumulator.add_internal(P, a, d); } for i in 1..NScalarSlices { @@ -309,8 +309,7 @@ impl CurveTrait for Curve where Params: TECurveParameter } for j in 0..N { - if (scalars[j].skew == true) - { + if (scalars[j].skew == true) { accumulator = accumulator - points[j]; } } @@ -324,15 +323,6 @@ impl CurveTrait for Curve where Params: TECurveParameter // #################################################################################################################### // #################################################################################################################### impl Curve { - /** - * @brief add points together, return output + lambda term - **/ - unconstrained pub fn __add_unconstrained(x1: Field, x2: Field, y1: Field, y2: Field, a: Field, d: Field) -> (Field, Field, Field) { - let lambda = y1 * y2 * x1 * x2; - let y = (x1 * x2 * a - y1 * y2) / (lambda * d - 1); - let x = (x1 * y2 + y1 * x2) / (lambda * d + 1); - (x, y, lambda) - } /** * @brief add two points together @@ -345,7 +335,7 @@ impl Curve { let x2 = other.x; let y1 = self.y; let y2 = other.y; - let (x, y, lambda) = Curve::__add_unconstrained(x1, x2, y1, y2, a, d); + let (x, y, lambda) = __add_unconstrained(x1, x2, y1, y2, a, d); let x1x2 = x1 * x2; let x1y2 = x1 * y2; std::as_witness(x1x2); @@ -372,7 +362,7 @@ impl Curve { fn dbl_internal(self, a: Field, d: Field) -> Self { let x1 = self.x; let y1 = self.y; - let (x3, y3, _) = Curve::__add_unconstrained(x1, x1, y1, y1, a, d); + let (x3, y3, _) = __add_unconstrained(x1, x1, y1, y1, a, d); let x1x1a = x1 * x1 * a; std::as_witness(x1x1a); // t1 = a*x_1^2 + y_1^2 @@ -429,7 +419,7 @@ impl Curve { table_y[8] = self.y; let D = self.dbl_internal(a, d); for i in 1..8 { - let Q = Curve { x: table_x[7 + i], y: table_y[7 + i] }; + let Q = Self { x: table_x[7 + i], y: table_y[7 + i] }; let V = D.add_internal(Q, a, d); table_x[8 + i] = V.x; table_y[8 + i] = V.y; @@ -441,3 +431,13 @@ impl Curve { (table_x, table_y) } } + +/** + * @brief add points together, return output + lambda term + **/ +unconstrained fn __add_unconstrained(x1: Field, x2: Field, y1: Field, y2: Field, a: Field, d: Field) -> (Field, Field, Field) { + let lambda = y1 * y2 * x1 * x2; + let y = (x1 * x2 * a - y1 * y2) / (lambda * d - 1); + let x = (x1 * y2 + y1 * x2) / (lambda * d + 1); + (x, y, lambda) +} diff --git a/src/scalar_field.nr b/src/scalar_field.nr index 79a85e5..6105aa4 100644 --- a/src/scalar_field.nr +++ b/src/scalar_field.nr @@ -17,9 +17,8 @@ struct ScalarField { } unconstrained fn get_wnaf_slices(x: Field) -> ([u8; N], bool) { - let mut result: [u8; N] = [0; N]; - let mut nibbles = x.to_le_radix(16, N); + let mut nibbles: [u8; N] = x.to_le_radix(16); let skew: bool = nibbles[0] & 1 == 0; nibbles[0] += skew as u8; @@ -48,7 +47,6 @@ unconstrained fn from_wnaf_slices(x: [u8; 64], skew: bool) -> Field { #[test] fn test_wnaf() { - let result: Field = 0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0; let (t0, t1) = get_wnaf_slices(result); let expected = from_wnaf_slices(t0, t1); @@ -78,8 +76,6 @@ unconstrained fn get_borrow_flag(lhs_lo: Field, rhs_lo: Field) -> bool { } impl std::convert::From for ScalarField { - - /** * @brief construct from a field element * @details if N >= 64 we perform extra checks to ensure the slice decomposition represents the same integral value as the input @@ -97,22 +93,19 @@ impl std::convert::From for ScalarField { acc += (slices[i] as Field) * 2 - 15; } assert(acc - skew as Field == x); - } - else - { + } else { // TODO: if num bits = 64, validate in sum of the bits is smaller than the Field modulus - let mut lo: Field = slices[(N/2)] as Field; + let mut lo: Field = slices[(N / 2)] as Field; let mut hi: Field = slices[0] as Field; let mut borrow_shift = 1; - for i in 1..(N/2) { + for i in 1..(N / 2) { borrow_shift *= 16; lo *= 16; lo += (slices[(N/2) + i] as Field) * 2 - 15; hi *= 16; hi += (slices[i] as Field) * 2 - 15; } - if ((N & 1) == 1) - { + if ((N & 1) == 1) { borrow_shift *= 16; lo *= 16; lo += (slices[N-1] as Field) * 2 - 15; diff --git a/src/test.nr b/src/test.nr index f151d80..fcf2404 100644 --- a/src/test.nr +++ b/src/test.nr @@ -1,8 +1,5 @@ -use dep::std; -use dep::std::ec; use crate::scalar_field::ScalarField; use crate::Curve; -use crate::TECurveParameterTrait; use crate::bjj::BabyJubJubParams; use std::ec::consts::te::baby_jubjub; use std::ec::tecurve::affine::Point as TEPoint;