From f08b5bb49dc9c78f8d9aad7d33278a9e899a2c1d Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 09:07:43 +0200 Subject: [PATCH 01/38] fixed fromAffine and toProj in golang --- wrappers/golang/core/internal/mock_curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/bls12377/curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/bls12377/g2/curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/bls12381/curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/bls12381/g2/curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/bn254/curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/bn254/g2/curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/bw6761/curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/bw6761/g2/curve.go | 20 ++++++++++++++++--- wrappers/golang/curves/grumpkin/curve.go | 20 ++++++++++++++++--- .../generator/curves/templates/curve.go.tmpl | 16 ++++++++++++++- 11 files changed, 185 insertions(+), 31 deletions(-) diff --git a/wrappers/golang/core/internal/mock_curve.go b/wrappers/golang/core/internal/mock_curve.go index 0a6fe8be4..a980aeb38 100644 --- a/wrappers/golang/core/internal/mock_curve.go +++ b/wrappers/golang/core/internal/mock_curve.go @@ -32,9 +32,15 @@ func (p *MockProjective) FromAffine(a MockAffine) MockProjective { z := MockBaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -68,6 +74,14 @@ func (a *MockAffine) FromLimbs(x, y []uint32) MockAffine { func (a MockAffine) ToProjective() MockProjective { var z MockBaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return MockProjective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return MockProjective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go index e21dd5808..c24c71731 100644 --- a/wrappers/golang/curves/bls12377/curve.go +++ b/wrappers/golang/curves/bls12377/curve.go @@ -43,9 +43,15 @@ func (p *Projective) FromAffine(a Affine) Projective { z := BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { func (a Affine) ToProjective() Projective { var z BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/bls12377/g2/curve.go b/wrappers/golang/curves/bls12377/g2/curve.go index 50ac2a110..433e83642 100644 --- a/wrappers/golang/curves/bls12377/g2/curve.go +++ b/wrappers/golang/curves/bls12377/g2/curve.go @@ -43,9 +43,15 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z := G2BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { func (a G2Affine) ToProjective() G2Projective { var z G2BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return G2Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return G2Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/bls12381/curve.go b/wrappers/golang/curves/bls12381/curve.go index d376c5c21..f4646914b 100644 --- a/wrappers/golang/curves/bls12381/curve.go +++ b/wrappers/golang/curves/bls12381/curve.go @@ -43,9 +43,15 @@ func (p *Projective) FromAffine(a Affine) Projective { z := BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { func (a Affine) ToProjective() Projective { var z BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/bls12381/g2/curve.go b/wrappers/golang/curves/bls12381/g2/curve.go index 2b8caa002..701513316 100644 --- a/wrappers/golang/curves/bls12381/g2/curve.go +++ b/wrappers/golang/curves/bls12381/g2/curve.go @@ -43,9 +43,15 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z := G2BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { func (a G2Affine) ToProjective() G2Projective { var z G2BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return G2Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return G2Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go index 80a844c7a..c91ee0cd6 100644 --- a/wrappers/golang/curves/bn254/curve.go +++ b/wrappers/golang/curves/bn254/curve.go @@ -43,9 +43,15 @@ func (p *Projective) FromAffine(a Affine) Projective { z := BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { func (a Affine) ToProjective() Projective { var z BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/bn254/g2/curve.go b/wrappers/golang/curves/bn254/g2/curve.go index 586d23831..58456188a 100644 --- a/wrappers/golang/curves/bn254/g2/curve.go +++ b/wrappers/golang/curves/bn254/g2/curve.go @@ -43,9 +43,15 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z := G2BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { func (a G2Affine) ToProjective() G2Projective { var z G2BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return G2Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return G2Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go index 907971405..7d881dd90 100644 --- a/wrappers/golang/curves/bw6761/curve.go +++ b/wrappers/golang/curves/bw6761/curve.go @@ -43,9 +43,15 @@ func (p *Projective) FromAffine(a Affine) Projective { z := BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { func (a Affine) ToProjective() Projective { var z BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/bw6761/g2/curve.go b/wrappers/golang/curves/bw6761/g2/curve.go index 4167674ef..dcb523e34 100644 --- a/wrappers/golang/curves/bw6761/g2/curve.go +++ b/wrappers/golang/curves/bw6761/g2/curve.go @@ -43,9 +43,15 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z := G2BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { func (a G2Affine) ToProjective() G2Projective { var z G2BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return G2Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return G2Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/curves/grumpkin/curve.go b/wrappers/golang/curves/grumpkin/curve.go index 653cbc8ed..d23ff2417 100644 --- a/wrappers/golang/curves/grumpkin/curve.go +++ b/wrappers/golang/curves/grumpkin/curve.go @@ -43,9 +43,15 @@ func (p *Projective) FromAffine(a Affine) Projective { z := BaseField{} z.One() - p.X = a.X - p.Y = a.Y - p.Z = z + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + } else { + p.X = a.X + p.Y = a.Y + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { func (a Affine) ToProjective() Projective { var z BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return Projective{ X: a.X, Y: a.Y, diff --git a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl index e6bd59d55..15eecef98 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl @@ -43,9 +43,15 @@ func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.Cur z := {{.CurvePrefix}}BaseField{} z.One() + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() + }else{ p.X = a.X p.Y = a.Y - p.Z = z + p.Z = z.One() + } return *p } @@ -109,6 +115,14 @@ func (a *{{.CurvePrefix}}Affine) FromLimbs(x, y []uint32) {{.CurvePrefix}}Affine func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { var z {{.CurvePrefix}}BaseField + if (a.X == z.Zero()) && (a.Y == z.Zero()) { + return {{.CurvePrefix}}Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } + } + return {{.CurvePrefix}}Projective{ X: a.X, Y: a.Y, From 9e057c835dafd72f8e265eb9b3bb032c08ae559d Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 09:18:41 +0200 Subject: [PATCH 02/38] fixed to_projective in rust --- wrappers/rust/icicle-core/src/curve.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wrappers/rust/icicle-core/src/curve.rs b/wrappers/rust/icicle-core/src/curve.rs index 89bec1c2e..c0b82d113 100644 --- a/wrappers/rust/icicle-core/src/curve.rs +++ b/wrappers/rust/icicle-core/src/curve.rs @@ -79,6 +79,9 @@ impl Affine { } pub fn to_projective(&self) -> Projective { + if *self == Self::zero() { + return Projective::::zero(); + } Projective { x: self.x, y: self.y, From 17732ea013729170add5a97c5ac2dadca8af621f Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:36:14 +0200 Subject: [PATCH 03/38] use zero method of projective in fromAffine Co-authored-by: Jeremy Felder --- .../golang/internal/generator/curves/templates/curve.go.tmpl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl index 15eecef98..a43bee98e 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl @@ -44,9 +44,7 @@ func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.Cur z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() }else{ p.X = a.X p.Y = a.Y From 81644fc28c2c4d35b12b83146821a5861fff4658 Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:37:02 +0200 Subject: [PATCH 04/38] use zero method of projective in toProjective Co-authored-by: Jeremy Felder --- .../internal/generator/curves/templates/curve.go.tmpl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl index a43bee98e..d02fe6a96 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl @@ -114,11 +114,8 @@ func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { var z {{.CurvePrefix}}BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return {{.CurvePrefix}}Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p {{.CurvePrefix}}Projective + return p.Zero() } return {{.CurvePrefix}}Projective{ From 279cdc66e05c434244b99890e764c2c68d371101 Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:41:32 +0200 Subject: [PATCH 05/38] generated go files --- wrappers/golang/core/internal/mock_curve.go | 11 +++-------- wrappers/golang/curves/bls12377/curve.go | 11 +++-------- wrappers/golang/curves/bls12377/g2/curve.go | 11 +++-------- wrappers/golang/curves/bls12381/curve.go | 11 +++-------- wrappers/golang/curves/bls12381/g2/curve.go | 11 +++-------- wrappers/golang/curves/bn254/curve.go | 11 +++-------- wrappers/golang/curves/bn254/g2/curve.go | 11 +++-------- wrappers/golang/curves/bw6761/curve.go | 11 +++-------- wrappers/golang/curves/bw6761/g2/curve.go | 11 +++-------- wrappers/golang/curves/grumpkin/curve.go | 11 +++-------- 10 files changed, 30 insertions(+), 80 deletions(-) diff --git a/wrappers/golang/core/internal/mock_curve.go b/wrappers/golang/core/internal/mock_curve.go index a980aeb38..de21b3d92 100644 --- a/wrappers/golang/core/internal/mock_curve.go +++ b/wrappers/golang/core/internal/mock_curve.go @@ -33,9 +33,7 @@ func (p *MockProjective) FromAffine(a MockAffine) MockProjective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -75,11 +73,8 @@ func (a MockAffine) ToProjective() MockProjective { var z MockBaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return MockProjective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p MockProjective + return p.Zero() } return MockProjective{ diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go index c24c71731..8083669ab 100644 --- a/wrappers/golang/curves/bls12377/curve.go +++ b/wrappers/golang/curves/bls12377/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ diff --git a/wrappers/golang/curves/bls12377/g2/curve.go b/wrappers/golang/curves/bls12377/g2/curve.go index 433e83642..7da1d2717 100644 --- a/wrappers/golang/curves/bls12377/g2/curve.go +++ b/wrappers/golang/curves/bls12377/g2/curve.go @@ -44,9 +44,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return G2Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p G2Projective + return p.Zero() } return G2Projective{ diff --git a/wrappers/golang/curves/bls12381/curve.go b/wrappers/golang/curves/bls12381/curve.go index f4646914b..02cee7b64 100644 --- a/wrappers/golang/curves/bls12381/curve.go +++ b/wrappers/golang/curves/bls12381/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ diff --git a/wrappers/golang/curves/bls12381/g2/curve.go b/wrappers/golang/curves/bls12381/g2/curve.go index 701513316..d4fced658 100644 --- a/wrappers/golang/curves/bls12381/g2/curve.go +++ b/wrappers/golang/curves/bls12381/g2/curve.go @@ -44,9 +44,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return G2Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p G2Projective + return p.Zero() } return G2Projective{ diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go index c91ee0cd6..3bc94a8f0 100644 --- a/wrappers/golang/curves/bn254/curve.go +++ b/wrappers/golang/curves/bn254/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ diff --git a/wrappers/golang/curves/bn254/g2/curve.go b/wrappers/golang/curves/bn254/g2/curve.go index 58456188a..7ee0ec7f9 100644 --- a/wrappers/golang/curves/bn254/g2/curve.go +++ b/wrappers/golang/curves/bn254/g2/curve.go @@ -44,9 +44,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return G2Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p G2Projective + return p.Zero() } return G2Projective{ diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go index 7d881dd90..2e8518be9 100644 --- a/wrappers/golang/curves/bw6761/curve.go +++ b/wrappers/golang/curves/bw6761/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ diff --git a/wrappers/golang/curves/bw6761/g2/curve.go b/wrappers/golang/curves/bw6761/g2/curve.go index dcb523e34..1433602a2 100644 --- a/wrappers/golang/curves/bw6761/g2/curve.go +++ b/wrappers/golang/curves/bw6761/g2/curve.go @@ -44,9 +44,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return G2Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p G2Projective + return p.Zero() } return G2Projective{ diff --git a/wrappers/golang/curves/grumpkin/curve.go b/wrappers/golang/curves/grumpkin/curve.go index d23ff2417..1079ce2e4 100644 --- a/wrappers/golang/curves/grumpkin/curve.go +++ b/wrappers/golang/curves/grumpkin/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ From 6336e74d5a0944e7f782563d7ce2c41db386d9c1 Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:03:58 +0200 Subject: [PATCH 06/38] refactor from_affine with C link --- icicle/src/curves/extern.cu | 5 +++ icicle/src/curves/extern_g2.cu | 5 +++ wrappers/golang/core/internal/mock_curve.go | 30 -------------- wrappers/golang/curves/bls12377/curve.go | 31 ++++---------- wrappers/golang/curves/bls12377/g2/curve.go | 31 ++++---------- .../golang/curves/bls12377/g2/include/curve.h | 1 + .../golang/curves/bls12377/include/curve.h | 1 + wrappers/golang/curves/bls12381/curve.go | 31 ++++---------- wrappers/golang/curves/bls12381/g2/curve.go | 31 ++++---------- .../golang/curves/bls12381/g2/include/curve.h | 1 + .../golang/curves/bls12381/include/curve.h | 1 + wrappers/golang/curves/bn254/curve.go | 31 ++++---------- wrappers/golang/curves/bn254/g2/curve.go | 31 ++++---------- .../golang/curves/bn254/g2/include/curve.h | 1 + wrappers/golang/curves/bn254/include/curve.h | 1 + wrappers/golang/curves/bw6761/curve.go | 31 ++++---------- wrappers/golang/curves/bw6761/g2/curve.go | 31 ++++---------- .../golang/curves/bw6761/g2/include/curve.h | 1 + wrappers/golang/curves/bw6761/include/curve.h | 1 + wrappers/golang/curves/grumpkin/curve.go | 31 ++++---------- .../golang/curves/grumpkin/include/curve.h | 1 + .../generator/curves/templates/curve.go.tmpl | 41 ++++++++----------- .../generator/curves/templates/curve.h.tmpl | 1 + wrappers/rust/icicle-core/src/curve.rs | 30 +++++++------- 24 files changed, 131 insertions(+), 269 deletions(-) diff --git a/icicle/src/curves/extern.cu b/icicle/src/curves/extern.cu index 8ea5bce2f..a40d24ffd 100644 --- a/icicle/src/curves/extern.cu +++ b/icicle/src/curves/extern.cu @@ -20,6 +20,11 @@ extern "C" void CONCAT_EXPAND(CURVE, to_affine)(projective_t* point, affine_t* p *point_out = projective_t::to_affine(*point); } +extern "C" void CONCAT_EXPAND(CURVE, from_affine)(affine_t* point, projective_t* point_out) +{ + *point_out = projective_t::from_affine(*point); +} + extern "C" void CONCAT_EXPAND(CURVE, generate_projective_points)(projective_t* points, int size) { projective_t::rand_host_many(points, size); diff --git a/icicle/src/curves/extern_g2.cu b/icicle/src/curves/extern_g2.cu index e8daa5e11..6d1e44146 100644 --- a/icicle/src/curves/extern_g2.cu +++ b/icicle/src/curves/extern_g2.cu @@ -20,6 +20,11 @@ extern "C" void CONCAT_EXPAND(CURVE, g2_to_affine)(g2_projective_t* point, g2_af *point_out = g2_projective_t::to_affine(*point); } +extern "C" void CONCAT_EXPAND(CURVE, g2_from_affine)(g2_affine_t* point, g2_projective_t* point_out) +{ + *point_out = g2_projective_t::from_affine(*point); +} + extern "C" void CONCAT_EXPAND(CURVE, g2_generate_projective_points)(g2_projective_t* points, int size) { g2_projective_t::rand_host_many(points, size); diff --git a/wrappers/golang/core/internal/mock_curve.go b/wrappers/golang/core/internal/mock_curve.go index de21b3d92..dddbddee7 100644 --- a/wrappers/golang/core/internal/mock_curve.go +++ b/wrappers/golang/core/internal/mock_curve.go @@ -28,21 +28,6 @@ func (p *MockProjective) FromLimbs(x, y, z []uint32) MockProjective { return *p } -func (p *MockProjective) FromAffine(a MockAffine) MockProjective { - z := MockBaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } - - return *p -} - type MockAffine struct { X, Y MockBaseField } @@ -68,18 +53,3 @@ func (a *MockAffine) FromLimbs(x, y []uint32) MockAffine { return *a } - -func (a MockAffine) ToProjective() MockProjective { - var z MockBaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p MockProjective - return p.Zero() - } - - return MockProjective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } -} diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go index 8083669ab..43184ff56 100644 --- a/wrappers/golang/curves/bls12377/curve.go +++ b/wrappers/golang/curves/bls12377/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.bls12_377_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.bls12_377_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bls12_377_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/bls12377/g2/curve.go b/wrappers/golang/curves/bls12377/g2/curve.go index 7da1d2717..4544e9735 100644 --- a/wrappers/golang/curves/bls12377/g2/curve.go +++ b/wrappers/golang/curves/bls12377/g2/curve.go @@ -40,17 +40,10 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { } func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) + C.bls12_377_g2_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine { var a G2Affine cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bls12_377_g2_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { } func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() - } + var p G2Projective - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bls12_377_g2_from_affine(cA, cP) + return p } func G2AffineFromProjective(p *G2Projective) G2Affine { diff --git a/wrappers/golang/curves/bls12377/g2/include/curve.h b/wrappers/golang/curves/bls12377/g2/include/curve.h index b136de9a8..57d5e148f 100644 --- a/wrappers/golang/curves/bls12377/g2/include/curve.h +++ b/wrappers/golang/curves/bls12377/g2/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bls12_377_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bls12_377_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bls12_377_g2_from_affine(g2_affine_t* point, g2_projective_t* point_out); void bls12_377_g2_generate_projective_points(g2_projective_t* points, int size); void bls12_377_g2_generate_affine_points(g2_affine_t* points, int size); cudaError_t bls12_377_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bls12377/include/curve.h b/wrappers/golang/curves/bls12377/include/curve.h index 87a0229b6..6f32d1c36 100644 --- a/wrappers/golang/curves/bls12377/include/curve.h +++ b/wrappers/golang/curves/bls12377/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bls12_377_eq(projective_t* point1, projective_t* point2); void bls12_377_to_affine(projective_t* point, affine_t* point_out); +void bls12_377_from_affine(affine_t* point, projective_t* point_out); void bls12_377_generate_projective_points(projective_t* points, int size); void bls12_377_generate_affine_points(affine_t* points, int size); cudaError_t bls12_377_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bls12381/curve.go b/wrappers/golang/curves/bls12381/curve.go index 02cee7b64..3b1b59ea2 100644 --- a/wrappers/golang/curves/bls12381/curve.go +++ b/wrappers/golang/curves/bls12381/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.bls12_381_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.bls12_381_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bls12_381_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/bls12381/g2/curve.go b/wrappers/golang/curves/bls12381/g2/curve.go index d4fced658..b9256e002 100644 --- a/wrappers/golang/curves/bls12381/g2/curve.go +++ b/wrappers/golang/curves/bls12381/g2/curve.go @@ -40,17 +40,10 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { } func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) + C.bls12_381_g2_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine { var a G2Affine cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bls12_381_g2_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { } func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() - } + var p G2Projective - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bls12_381_g2_from_affine(cA, cP) + return p } func G2AffineFromProjective(p *G2Projective) G2Affine { diff --git a/wrappers/golang/curves/bls12381/g2/include/curve.h b/wrappers/golang/curves/bls12381/g2/include/curve.h index b7710244d..274f3ec16 100644 --- a/wrappers/golang/curves/bls12381/g2/include/curve.h +++ b/wrappers/golang/curves/bls12381/g2/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bls12_381_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bls12_381_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bls12_381_g2_from_affine(g2_affine_t* point, g2_projective_t* point_out); void bls12_381_g2_generate_projective_points(g2_projective_t* points, int size); void bls12_381_g2_generate_affine_points(g2_affine_t* points, int size); cudaError_t bls12_381_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bls12381/include/curve.h b/wrappers/golang/curves/bls12381/include/curve.h index 1cb3bd61e..b9a50675c 100644 --- a/wrappers/golang/curves/bls12381/include/curve.h +++ b/wrappers/golang/curves/bls12381/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bls12_381_eq(projective_t* point1, projective_t* point2); void bls12_381_to_affine(projective_t* point, affine_t* point_out); +void bls12_381_from_affine(affine_t* point, projective_t* point_out); void bls12_381_generate_projective_points(projective_t* points, int size); void bls12_381_generate_affine_points(affine_t* points, int size); cudaError_t bls12_381_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go index 3bc94a8f0..c2b6b1b8d 100644 --- a/wrappers/golang/curves/bn254/curve.go +++ b/wrappers/golang/curves/bn254/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.bn254_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.bn254_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bn254_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/bn254/g2/curve.go b/wrappers/golang/curves/bn254/g2/curve.go index 7ee0ec7f9..72245e02b 100644 --- a/wrappers/golang/curves/bn254/g2/curve.go +++ b/wrappers/golang/curves/bn254/g2/curve.go @@ -40,17 +40,10 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { } func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) + C.bn254_g2_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine { var a G2Affine cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bn254_g2_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { } func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() - } + var p G2Projective - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bn254_g2_from_affine(cA, cP) + return p } func G2AffineFromProjective(p *G2Projective) G2Affine { diff --git a/wrappers/golang/curves/bn254/g2/include/curve.h b/wrappers/golang/curves/bn254/g2/include/curve.h index e8863f1ef..c24deb307 100644 --- a/wrappers/golang/curves/bn254/g2/include/curve.h +++ b/wrappers/golang/curves/bn254/g2/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bn254_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bn254_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bn254_g2_from_affine(g2_affine_t* point, g2_projective_t* point_out); void bn254_g2_generate_projective_points(g2_projective_t* points, int size); void bn254_g2_generate_affine_points(g2_affine_t* points, int size); cudaError_t bn254_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bn254/include/curve.h b/wrappers/golang/curves/bn254/include/curve.h index 069600aa4..ce29f587a 100644 --- a/wrappers/golang/curves/bn254/include/curve.h +++ b/wrappers/golang/curves/bn254/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bn254_eq(projective_t* point1, projective_t* point2); void bn254_to_affine(projective_t* point, affine_t* point_out); +void bn254_from_affine(affine_t* point, projective_t* point_out); void bn254_generate_projective_points(projective_t* points, int size); void bn254_generate_affine_points(affine_t* points, int size); cudaError_t bn254_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go index 2e8518be9..334499441 100644 --- a/wrappers/golang/curves/bw6761/curve.go +++ b/wrappers/golang/curves/bw6761/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.bw6_761_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.bw6_761_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bw6_761_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/bw6761/g2/curve.go b/wrappers/golang/curves/bw6761/g2/curve.go index 1433602a2..f38bf134f 100644 --- a/wrappers/golang/curves/bw6761/g2/curve.go +++ b/wrappers/golang/curves/bw6761/g2/curve.go @@ -40,17 +40,10 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { } func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) + C.bw6_761_g2_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine { var a G2Affine cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bw6_761_g2_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { } func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() - } + var p G2Projective - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bw6_761_g2_from_affine(cA, cP) + return p } func G2AffineFromProjective(p *G2Projective) G2Affine { diff --git a/wrappers/golang/curves/bw6761/g2/include/curve.h b/wrappers/golang/curves/bw6761/g2/include/curve.h index b57b55cfc..8d113fc90 100644 --- a/wrappers/golang/curves/bw6761/g2/include/curve.h +++ b/wrappers/golang/curves/bw6761/g2/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bw6_761_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bw6_761_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bw6_761_g2_from_affine(g2_affine_t* point, g2_projective_t* point_out); void bw6_761_g2_generate_projective_points(g2_projective_t* points, int size); void bw6_761_g2_generate_affine_points(g2_affine_t* points, int size); cudaError_t bw6_761_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bw6761/include/curve.h b/wrappers/golang/curves/bw6761/include/curve.h index cc6e401cb..ba243029c 100644 --- a/wrappers/golang/curves/bw6761/include/curve.h +++ b/wrappers/golang/curves/bw6761/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bw6_761_eq(projective_t* point1, projective_t* point2); void bw6_761_to_affine(projective_t* point, affine_t* point_out); +void bw6_761_from_affine(affine_t* point, projective_t* point_out); void bw6_761_generate_projective_points(projective_t* points, int size); void bw6_761_generate_affine_points(affine_t* points, int size); cudaError_t bw6_761_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/grumpkin/curve.go b/wrappers/golang/curves/grumpkin/curve.go index 1079ce2e4..1411a246b 100644 --- a/wrappers/golang/curves/grumpkin/curve.go +++ b/wrappers/golang/curves/grumpkin/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.grumpkin_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.grumpkin_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.grumpkin_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/grumpkin/include/curve.h b/wrappers/golang/curves/grumpkin/include/curve.h index 8466982ed..6005b280c 100644 --- a/wrappers/golang/curves/grumpkin/include/curve.h +++ b/wrappers/golang/curves/grumpkin/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool grumpkin_eq(projective_t* point1, projective_t* point2); void grumpkin_to_affine(projective_t* point, affine_t* point_out); +void grumpkin_from_affine(affine_t* point, projective_t* point_out); void grumpkin_generate_projective_points(projective_t* points, int size); void grumpkin_generate_affine_points(affine_t* points, int size); cudaError_t grumpkin_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl index d02fe6a96..1378557e3 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl @@ -39,21 +39,16 @@ func (p *{{.CurvePrefix}}Projective) FromLimbs(x, y, z []uint32) {{.CurvePrefix} return *p } -func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.CurvePrefix}}Projective { - z := {{.CurvePrefix}}BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - }else{ - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } +{{if ne .CurvePrefix "Mock"}} +func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.CurvePrefix}}Projective { + + cA := (*C.{{toCName .CurvePrefix}}affine_t)(unsafe.Pointer(&a)) + cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(p)) + C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_from_affine(cA, cP) return *p } -{{if ne .CurvePrefix "Mock"}} + func (p {{.CurvePrefix}}Projective) ProjectiveEq(p2 *{{.CurvePrefix}}Projective) bool { cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p)) cP2 := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p2)) @@ -65,7 +60,7 @@ func (p *{{.CurvePrefix}}Projective) ProjectiveToAffine() {{.CurvePrefix}}Affine var a {{.CurvePrefix}}Affine cA := (*C.{{toCName .CurvePrefix}}affine_t)(unsafe.Pointer(&a)) - cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p)) + cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(p)) C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_to_affine(cP, cA) return a } @@ -110,21 +105,17 @@ func (a *{{.CurvePrefix}}Affine) FromLimbs(x, y []uint32) {{.CurvePrefix}}Affine return *a } -func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { - var z {{.CurvePrefix}}BaseField - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p {{.CurvePrefix}}Projective - return p.Zero() - } +{{if ne .CurvePrefix "Mock"}} +func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { + var p {{.CurvePrefix}}Projective - return {{.CurvePrefix}}Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.{{toCName .CurvePrefix}}affine_t)(unsafe.Pointer(&a)) + cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p)) + C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_from_affine(cA, cP) + return p } -{{if ne .CurvePrefix "Mock"}} + func {{.CurvePrefix}}AffineFromProjective(p *{{.CurvePrefix}}Projective) {{.CurvePrefix}}Affine { return p.ProjectiveToAffine() } diff --git a/wrappers/golang/internal/generator/curves/templates/curve.h.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.h.tmpl index 22179e6f6..0dffd240f 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.h.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.h.tmpl @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool {{.Curve}}{{toCNameBackwards .CurvePrefix}}_eq({{toCName .CurvePrefix}}projective_t* point1, {{toCName .CurvePrefix}}projective_t* point2); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_to_affine({{toCName .CurvePrefix}}projective_t* point, {{toCName .CurvePrefix}}affine_t* point_out); +void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_from_affine({{toCName .CurvePrefix}}affine_t* point, {{toCName .CurvePrefix}}projective_t* point_out); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_projective_points({{toCName .CurvePrefix}}projective_t* points, int size); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_affine_points({{toCName .CurvePrefix}}affine_t* points, int size); cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_affine_convert_montgomery({{toCName .CurvePrefix}}affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/rust/icicle-core/src/curve.rs b/wrappers/rust/icicle-core/src/curve.rs index c0b82d113..a0bf70bc6 100644 --- a/wrappers/rust/icicle-core/src/curve.rs +++ b/wrappers/rust/icicle-core/src/curve.rs @@ -22,6 +22,8 @@ pub trait Curve: Debug + PartialEq + Copy + Clone { #[doc(hidden)] fn to_affine(point: *const Projective, point_aff: *mut Affine); #[doc(hidden)] + fn from_affine(point: *const Affine, point_proj: *mut Projective); + #[doc(hidden)] fn generate_random_projective_points(size: usize) -> Vec>; #[doc(hidden)] fn generate_random_affine_points(size: usize) -> Vec>; @@ -79,27 +81,17 @@ impl Affine { } pub fn to_projective(&self) -> Projective { - if *self == Self::zero() { - return Projective::::zero(); - } - Projective { - x: self.x, - y: self.y, - z: C::BaseField::one(), - } + let mut proj = Projective::::zero(); + C::from_affine(self as *const Self, &mut proj as *mut Projective); + proj } } impl From> for Projective { fn from(item: Affine) -> Self { - if item == (Affine::::zero()) { - return Self::zero(); - } - Self { - x: item.x, - y: item.y, - z: C::BaseField::one(), - } + let mut proj = Self::zero(); + C::from_affine(&item as *const Affine, &mut proj as *mut Self); + proj } } @@ -282,6 +274,8 @@ macro_rules! impl_curve { pub(crate) fn eq(point1: *const $projective_type, point2: *const $projective_type) -> bool; #[link_name = concat!($curve_prefix, "_to_affine")] pub(crate) fn proj_to_affine(point: *const $projective_type, point_out: *mut $affine_type); + #[link_name = concat!($curve_prefix, "_from_affine")] + pub(crate) fn proj_from_affine(point: *const $affine_type, point_out: *mut $projective_type); #[link_name = concat!($curve_prefix, "_generate_projective_points")] pub(crate) fn generate_projective_points(points: *mut $projective_type, size: usize); #[link_name = concat!($curve_prefix, "_generate_affine_points")] @@ -315,6 +309,10 @@ macro_rules! impl_curve { unsafe { $curve_prefix_ident::proj_to_affine(point, point_out) }; } + fn from_affine(point: *const $affine_type, point_out: *mut $projective_type) { + unsafe { $curve_prefix_ident::proj_from_affine(point, point_out) }; + } + fn generate_random_projective_points(size: usize) -> Vec<$projective_type> { let mut res = vec![$projective_type::zero(); size]; unsafe { From e4eda8938d513d82225d0f1a65ab14b79b3e370b Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Fri, 5 Jul 2024 21:29:44 +0200 Subject: [PATCH 07/38] go fmt --- wrappers/golang/curves/bls12377/curve.go | 3 +-- wrappers/golang/curves/bn254/curve.go | 1 - wrappers/golang/curves/bw6761/curve.go | 1 - wrappers/golang/curves/grumpkin/curve.go | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go index 7691e83a2..43184ff56 100644 --- a/wrappers/golang/curves/bls12377/curve.go +++ b/wrappers/golang/curves/bls12377/curve.go @@ -41,7 +41,6 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { func (p *Projective) FromAffine(a Affine) Projective { - cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(p)) C.bls12_377_from_affine(cA, cP) @@ -106,7 +105,7 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { func (a Affine) ToProjective() Projective { var p Projective - + cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(&p)) C.bls12_377_from_affine(cA, cP) diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go index fe55536b0..f78e02840 100644 --- a/wrappers/golang/curves/bn254/curve.go +++ b/wrappers/golang/curves/bn254/curve.go @@ -41,7 +41,6 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { func (p *Projective) FromAffine(a Affine) Projective { - cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(p)) C.bn254_from_affine(cA, cP) diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go index 21486af4a..38a68fd94 100644 --- a/wrappers/golang/curves/bw6761/curve.go +++ b/wrappers/golang/curves/bw6761/curve.go @@ -41,7 +41,6 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { func (p *Projective) FromAffine(a Affine) Projective { - cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(p)) C.bw6_761_from_affine(cA, cP) diff --git a/wrappers/golang/curves/grumpkin/curve.go b/wrappers/golang/curves/grumpkin/curve.go index 13e9b99a1..4ad6e2321 100644 --- a/wrappers/golang/curves/grumpkin/curve.go +++ b/wrappers/golang/curves/grumpkin/curve.go @@ -41,7 +41,6 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { func (p *Projective) FromAffine(a Affine) Projective { - cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(p)) C.grumpkin_from_affine(cA, cP) From 46e6c2044093b93a8bb7ff1e5776fdfb07d2ac48 Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Fri, 5 Jul 2024 21:29:44 +0200 Subject: [PATCH 08/38] go fmt --- wrappers/golang/curves/bls12377/curve.go | 3 +-- wrappers/golang/curves/bn254/curve.go | 1 - wrappers/golang/curves/bw6761/curve.go | 1 - wrappers/golang/curves/grumpkin/curve.go | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go index 7691e83a2..43184ff56 100644 --- a/wrappers/golang/curves/bls12377/curve.go +++ b/wrappers/golang/curves/bls12377/curve.go @@ -41,7 +41,6 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { func (p *Projective) FromAffine(a Affine) Projective { - cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(p)) C.bls12_377_from_affine(cA, cP) @@ -106,7 +105,7 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { func (a Affine) ToProjective() Projective { var p Projective - + cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(&p)) C.bls12_377_from_affine(cA, cP) diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go index fe55536b0..f78e02840 100644 --- a/wrappers/golang/curves/bn254/curve.go +++ b/wrappers/golang/curves/bn254/curve.go @@ -41,7 +41,6 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { func (p *Projective) FromAffine(a Affine) Projective { - cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(p)) C.bn254_from_affine(cA, cP) diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go index 21486af4a..38a68fd94 100644 --- a/wrappers/golang/curves/bw6761/curve.go +++ b/wrappers/golang/curves/bw6761/curve.go @@ -41,7 +41,6 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { func (p *Projective) FromAffine(a Affine) Projective { - cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(p)) C.bw6_761_from_affine(cA, cP) diff --git a/wrappers/golang/curves/grumpkin/curve.go b/wrappers/golang/curves/grumpkin/curve.go index 13e9b99a1..4ad6e2321 100644 --- a/wrappers/golang/curves/grumpkin/curve.go +++ b/wrappers/golang/curves/grumpkin/curve.go @@ -41,7 +41,6 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { func (p *Projective) FromAffine(a Affine) Projective { - cA := (*C.affine_t)(unsafe.Pointer(&a)) cP := (*C.projective_t)(unsafe.Pointer(p)) C.grumpkin_from_affine(cA, cP) From 877018c84cd165d47f75f1c1cd9b991bbb581c2d Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Mon, 15 Jul 2024 16:55:40 +0200 Subject: [PATCH 09/38] more go fmt --- wrappers/golang/core/internal/mock_curve.go | 2 -- wrappers/golang/curves/bls12377/g2/curve.go | 1 - wrappers/golang/curves/bls12381/g2/curve.go | 2 +- wrappers/golang/curves/bn254/g2/curve.go | 1 - wrappers/golang/curves/bw6761/g2/curve.go | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/wrappers/golang/core/internal/mock_curve.go b/wrappers/golang/core/internal/mock_curve.go index 98739df7c..dddbddee7 100644 --- a/wrappers/golang/core/internal/mock_curve.go +++ b/wrappers/golang/core/internal/mock_curve.go @@ -28,7 +28,6 @@ func (p *MockProjective) FromLimbs(x, y, z []uint32) MockProjective { return *p } - type MockAffine struct { X, Y MockBaseField } @@ -54,4 +53,3 @@ func (a *MockAffine) FromLimbs(x, y []uint32) MockAffine { return *a } - diff --git a/wrappers/golang/curves/bls12377/g2/curve.go b/wrappers/golang/curves/bls12377/g2/curve.go index 31d290aa3..4544e9735 100644 --- a/wrappers/golang/curves/bls12377/g2/curve.go +++ b/wrappers/golang/curves/bls12377/g2/curve.go @@ -41,7 +41,6 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bls12_377_g2_from_affine(cA, cP) diff --git a/wrappers/golang/curves/bls12381/g2/curve.go b/wrappers/golang/curves/bls12381/g2/curve.go index db368887e..b711be658 100644 --- a/wrappers/golang/curves/bls12381/g2/curve.go +++ b/wrappers/golang/curves/bls12381/g2/curve.go @@ -105,7 +105,7 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { func (a G2Affine) ToProjective() G2Projective { var p G2Projective - + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) C.bls12_381_g2_from_affine(cA, cP) diff --git a/wrappers/golang/curves/bn254/g2/curve.go b/wrappers/golang/curves/bn254/g2/curve.go index cd568d373..72245e02b 100644 --- a/wrappers/golang/curves/bn254/g2/curve.go +++ b/wrappers/golang/curves/bn254/g2/curve.go @@ -41,7 +41,6 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bn254_g2_from_affine(cA, cP) diff --git a/wrappers/golang/curves/bw6761/g2/curve.go b/wrappers/golang/curves/bw6761/g2/curve.go index c18d6fcb6..f38bf134f 100644 --- a/wrappers/golang/curves/bw6761/g2/curve.go +++ b/wrappers/golang/curves/bw6761/g2/curve.go @@ -41,7 +41,6 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bw6_761_g2_from_affine(cA, cP) From 53f34aade57ff2b54a7eb1afadd563c143d4aa69 Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:58:04 +0200 Subject: [PATCH 10/38] Fix typos (#558) Fix typos --- docs/docs/contributor-guide.md | 6 +++--- docs/docs/icicle/golang-bindings/ecntt.md | 2 +- docs/docs/icicle/golang-bindings/msm.md | 4 ++-- docs/docs/icicle/polynomials/overview.md | 2 +- docs/docs/icicle/primitives/msm.md | 6 +++--- docs/docs/icicle/primitives/ntt.md | 2 +- docs/docs/icicle/primitives/poseidon.md | 8 ++++---- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/docs/contributor-guide.md b/docs/docs/contributor-guide.md index ffd82cd9c..fbbf8b569 100644 --- a/docs/docs/contributor-guide.md +++ b/docs/docs/contributor-guide.md @@ -1,6 +1,6 @@ # Contributor's Guide -We welcome all contributions with open arms. At Ingonyama we take a village approach, believing it takes many hands and minds to build a ecosystem. +We welcome all contributions with open arms. At Ingonyama we take a village approach, believing it takes many hands and minds to build an ecosystem. ## Contributing to ICICLE @@ -14,9 +14,9 @@ We welcome all contributions with open arms. At Ingonyama we take a village appr When opening a [pull request](https://github.com/ingonyama-zk/icicle/pulls) please keep the following in mind. - `Clear Purpose` - The pull request should solve a single issue and be clean of any unrelated changes. -- `Clear description` - If the pull request is for a new feature describe what you built, why you added it and how its best that we test it. For bug fixes please describe the issue and the solution. +- `Clear description` - If the pull request is for a new feature describe what you built, why you added it and how it's best that we test it. For bug fixes please describe the issue and the solution. - `Consistent style` - Rust and Golang code should be linted by the official linters (golang fmt and rust fmt) and maintain a proper style. For CUDA and C++ code we use [`clang-format`](https://github.com/ingonyama-zk/icicle/blob/main/.clang-format), [here](https://github.com/ingonyama-zk/icicle/blob/605c25f9d22135c54ac49683b710fe2ce06e2300/.github/workflows/main-format.yml#L46) you can see how we run it. -- `Minimal Tests` - please add test which cover basic usage of your changes . +- `Minimal Tests` - please add test which cover basic usage of your changes. ## Questions? diff --git a/docs/docs/icicle/golang-bindings/ecntt.md b/docs/docs/icicle/golang-bindings/ecntt.md index 3947995ed..31b94671a 100644 --- a/docs/docs/icicle/golang-bindings/ecntt.md +++ b/docs/docs/icicle/golang-bindings/ecntt.md @@ -47,7 +47,7 @@ type NTTConfig[T any] struct { - **`areInputsOnDevice`**: Indicates if input scalars are located on the device. - **`areOutputsOnDevice`**: Indicates if results are stored on the device. - **`IsAsync`**: Controls whether the NTT operation runs asynchronously. -- **`NttAlgorithm`**: Explicitly select the NTT algorithm. ECNTT supports running on `Radix2` algoruithm. +- **`NttAlgorithm`**: Explicitly select the NTT algorithm. ECNTT supports running on `Radix2` algorithm. ### Default Configuration diff --git a/docs/docs/icicle/golang-bindings/msm.md b/docs/docs/icicle/golang-bindings/msm.md index 72710c551..1780950b7 100644 --- a/docs/docs/icicle/golang-bindings/msm.md +++ b/docs/docs/icicle/golang-bindings/msm.md @@ -139,7 +139,7 @@ cfg.Ctx.IsBigTriangle = true Toggling between MSM modes occurs automatically based on the number of results you are expecting from the `MSM` function. -The number of results is interpreted from the size of `var out core.DeviceSlice`. Thus its important when allocating memory for `var out core.DeviceSlice` to make sure that you are allocating ` X `. +The number of results is interpreted from the size of `var out core.DeviceSlice`. Thus it's important when allocating memory for `var out core.DeviceSlice` to make sure that you are allocating ` X `. ```go ... @@ -168,7 +168,7 @@ import ( ) ``` -This package include `G2Projective` and `G2Affine` points as well as a `G2Msm` method. +This package includes `G2Projective` and `G2Affine` points as well as a `G2Msm` method. ```go package main diff --git a/docs/docs/icicle/polynomials/overview.md b/docs/docs/icicle/polynomials/overview.md index 06058ffe4..25ba9dee8 100644 --- a/docs/docs/icicle/polynomials/overview.md +++ b/docs/docs/icicle/polynomials/overview.md @@ -171,7 +171,7 @@ Polynomial& add_monomial_inplace(Coeff monomial_coeff, uint64_t monomial = 0); Polynomial& sub_monomial_inplace(Coeff monomial_coeff, uint64_t monomial = 0); ``` -The ability to add or subtract monomials directly and in-place is an efficient way to manipualte polynomials. +The ability to add or subtract monomials directly and in-place is an efficient way to manipulate polynomials. Example: diff --git a/docs/docs/icicle/primitives/msm.md b/docs/docs/icicle/primitives/msm.md index 7cb4a0abf..7b12f96ef 100644 --- a/docs/docs/icicle/primitives/msm.md +++ b/docs/docs/icicle/primitives/msm.md @@ -1,6 +1,6 @@ # MSM - Multi scalar multiplication -MSM stands for Multi scalar multiplication, its defined as: +MSM stands for Multi scalar multiplication, it's defined as: M @@ -43,7 +43,7 @@ $a_0, \ldots, a_n$ - Scalars $MSM(a, G) \in G$ - a single EC (elliptic curve) point -In words, MSM is the sum of scalar and EC point multiplications. We can see from this definition that the core operations occurring are Modular Multiplication and Elliptic curve point addition. Its obvious that multiplication can be computed in parallel and then the products summed, making MSM inherently parallelizable. +In words, MSM is the sum of scalar and EC point multiplications. We can see from this definition that the core operations occurring are Modular Multiplication and Elliptic curve point addition. It's obvious that multiplication can be computed in parallel and then the products summed, making MSM inherently parallelizable. Accelerating MSM is crucial to a ZK protocol's performance due to the [large percent of run time](https://hackmd.io/@0xMonia/SkQ6-oRz3#Hardware-acceleration-in-action) they take when generating proofs. @@ -131,7 +131,7 @@ Large buckets exist in two cases: 2. When `c` does not divide the scalar bit-size. `large_bucket_factor` that is equal to 10 yields good results for most cases, but it's best to fine tune this parameter per `c` and per scalar distribution. -The two most important parameters for performance are `c` and the `precompute_factor`. They affect the number of EC additions as well as the memory size. When the points are not known in advance we cannot use precomputation. In this case the best `c` value is usually around $log_2(msmSize) - 4$. However, in most protocols the points are known in advanced and precomputation can be used unless limited by memory. Usually it's best to use maximum precomputation (such that we end up with only a single bucket module) combined we a `c` value around $log_2(msmSize) - 1$. +The two most important parameters for performance are `c` and the `precompute_factor`. They affect the number of EC additions as well as the memory size. When the points are not known in advance we cannot use precomputation. In this case the best `c` value is usually around $log_2(msmSize) - 4$. However, in most protocols the points are known in advance and precomputation can be used unless limited by memory. Usually it's best to use maximum precomputation (such that we end up with only a single bucket module) combined with a `c` value around $log_2(msmSize) - 1$. ## Memory usage estimation diff --git a/docs/docs/icicle/primitives/ntt.md b/docs/docs/icicle/primitives/ntt.md index 9816b3dce..3dd014086 100644 --- a/docs/docs/icicle/primitives/ntt.md +++ b/docs/docs/icicle/primitives/ntt.md @@ -56,7 +56,7 @@ Choosing an algorithm is heavily dependent on your use case. For example Cooley- NTT also supports two different modes `Batch NTT` and `Single NTT` -Deciding weather to use `batch NTT` vs `single NTT` is highly dependent on your application and use case. +Deciding whether to use `batch NTT` vs `single NTT` is highly dependent on your application and use case. #### Single NTT diff --git a/docs/docs/icicle/primitives/poseidon.md b/docs/docs/icicle/primitives/poseidon.md index 5626701b9..3a59f06e4 100644 --- a/docs/docs/icicle/primitives/poseidon.md +++ b/docs/docs/icicle/primitives/poseidon.md @@ -1,6 +1,6 @@ # Poseidon -[Poseidon](https://eprint.iacr.org/2019/458.pdf) is a popular hash in the ZK ecosystem primarily because its optimized to work over large prime fields, a common setting for ZK proofs, thereby minimizing the number of multiplicative operations required. +[Poseidon](https://eprint.iacr.org/2019/458.pdf) is a popular hash in the ZK ecosystem primarily because it's optimized to work over large prime fields, a common setting for ZK proofs, thereby minimizing the number of multiplicative operations required. Poseidon has also been specifically designed to be efficient when implemented within ZK circuits, Poseidon uses far less constraints compared to other hash functions like Keccak or SHA-256 in the context of ZK circuits. @@ -42,7 +42,7 @@ To generate a secure hash output, the algorithm goes through a series of "full r **Linear Transformation and Round Constants:** A linear transformation is performed and round constants are added. The linear transformation in partial rounds can be designed to be less computationally intensive (this is done by using a sparse matrix) than in full rounds, further optimizing the function's efficiency. -The user of Poseidon can often choose how many partial or full rounds he wishes to apply; more full rounds will increase security but degrade performance. The choice and balance is highly dependent on the use case. +The user of Poseidon can often choose how many partial or full rounds he wishes to apply; more full rounds will increase security but degrade performance. The choice and balance are highly dependent on the use case. ## Using Poseidon @@ -60,7 +60,7 @@ So for Poseidon of arity 2 and input of size 1024 * 2, we would expect 1024 elem Poseidon is extremely customizable and using different constants will produce different hashes, security levels and performance results. -We support pre-calculated and optimized constants for each of the [supported curves](../core#supported-curves-and-operations).The constants can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants) and are labeled clearly per curve `_poseidon.h`. +We support pre-calculated and optimized constants for each of the [supported curves](../core#supported-curves-and-operations). The constants can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants) and are labeled clearly per curve `_poseidon.h`. If you wish to generate your own constants you can use our python script which can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants/generate_parameters.py). @@ -135,7 +135,7 @@ impl<'a> Default for HashConfig<'a> { } ``` -In the example above `Poseidon::load(arity, &ctx).unwrap();` is used which will load the correct constants based on arity and curve. Its possible to [generate](#constants) your own constants and load them. +In the example above `Poseidon::load(arity, &ctx).unwrap();` is used which will load the correct constants based on arity and curve. It's possible to [generate](#constants) your own constants and load them. ```rust let ctx = get_default_device_context(); From 3ac9811f9208c47574d66e80fab6caabf0273c80 Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:58:04 +0200 Subject: [PATCH 11/38] Fix typos (#558) Fix typos --- docs/docs/contributor-guide.md | 6 +++--- docs/docs/icicle/golang-bindings/ecntt.md | 2 +- docs/docs/icicle/golang-bindings/msm.md | 4 ++-- docs/docs/icicle/polynomials/overview.md | 2 +- docs/docs/icicle/primitives/msm.md | 6 +++--- docs/docs/icicle/primitives/ntt.md | 2 +- docs/docs/icicle/primitives/poseidon.md | 8 ++++---- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/docs/contributor-guide.md b/docs/docs/contributor-guide.md index ffd82cd9c..fbbf8b569 100644 --- a/docs/docs/contributor-guide.md +++ b/docs/docs/contributor-guide.md @@ -1,6 +1,6 @@ # Contributor's Guide -We welcome all contributions with open arms. At Ingonyama we take a village approach, believing it takes many hands and minds to build a ecosystem. +We welcome all contributions with open arms. At Ingonyama we take a village approach, believing it takes many hands and minds to build an ecosystem. ## Contributing to ICICLE @@ -14,9 +14,9 @@ We welcome all contributions with open arms. At Ingonyama we take a village appr When opening a [pull request](https://github.com/ingonyama-zk/icicle/pulls) please keep the following in mind. - `Clear Purpose` - The pull request should solve a single issue and be clean of any unrelated changes. -- `Clear description` - If the pull request is for a new feature describe what you built, why you added it and how its best that we test it. For bug fixes please describe the issue and the solution. +- `Clear description` - If the pull request is for a new feature describe what you built, why you added it and how it's best that we test it. For bug fixes please describe the issue and the solution. - `Consistent style` - Rust and Golang code should be linted by the official linters (golang fmt and rust fmt) and maintain a proper style. For CUDA and C++ code we use [`clang-format`](https://github.com/ingonyama-zk/icicle/blob/main/.clang-format), [here](https://github.com/ingonyama-zk/icicle/blob/605c25f9d22135c54ac49683b710fe2ce06e2300/.github/workflows/main-format.yml#L46) you can see how we run it. -- `Minimal Tests` - please add test which cover basic usage of your changes . +- `Minimal Tests` - please add test which cover basic usage of your changes. ## Questions? diff --git a/docs/docs/icicle/golang-bindings/ecntt.md b/docs/docs/icicle/golang-bindings/ecntt.md index 3947995ed..31b94671a 100644 --- a/docs/docs/icicle/golang-bindings/ecntt.md +++ b/docs/docs/icicle/golang-bindings/ecntt.md @@ -47,7 +47,7 @@ type NTTConfig[T any] struct { - **`areInputsOnDevice`**: Indicates if input scalars are located on the device. - **`areOutputsOnDevice`**: Indicates if results are stored on the device. - **`IsAsync`**: Controls whether the NTT operation runs asynchronously. -- **`NttAlgorithm`**: Explicitly select the NTT algorithm. ECNTT supports running on `Radix2` algoruithm. +- **`NttAlgorithm`**: Explicitly select the NTT algorithm. ECNTT supports running on `Radix2` algorithm. ### Default Configuration diff --git a/docs/docs/icicle/golang-bindings/msm.md b/docs/docs/icicle/golang-bindings/msm.md index 72710c551..1780950b7 100644 --- a/docs/docs/icicle/golang-bindings/msm.md +++ b/docs/docs/icicle/golang-bindings/msm.md @@ -139,7 +139,7 @@ cfg.Ctx.IsBigTriangle = true Toggling between MSM modes occurs automatically based on the number of results you are expecting from the `MSM` function. -The number of results is interpreted from the size of `var out core.DeviceSlice`. Thus its important when allocating memory for `var out core.DeviceSlice` to make sure that you are allocating ` X `. +The number of results is interpreted from the size of `var out core.DeviceSlice`. Thus it's important when allocating memory for `var out core.DeviceSlice` to make sure that you are allocating ` X `. ```go ... @@ -168,7 +168,7 @@ import ( ) ``` -This package include `G2Projective` and `G2Affine` points as well as a `G2Msm` method. +This package includes `G2Projective` and `G2Affine` points as well as a `G2Msm` method. ```go package main diff --git a/docs/docs/icicle/polynomials/overview.md b/docs/docs/icicle/polynomials/overview.md index 06058ffe4..25ba9dee8 100644 --- a/docs/docs/icicle/polynomials/overview.md +++ b/docs/docs/icicle/polynomials/overview.md @@ -171,7 +171,7 @@ Polynomial& add_monomial_inplace(Coeff monomial_coeff, uint64_t monomial = 0); Polynomial& sub_monomial_inplace(Coeff monomial_coeff, uint64_t monomial = 0); ``` -The ability to add or subtract monomials directly and in-place is an efficient way to manipualte polynomials. +The ability to add or subtract monomials directly and in-place is an efficient way to manipulate polynomials. Example: diff --git a/docs/docs/icicle/primitives/msm.md b/docs/docs/icicle/primitives/msm.md index 7cb4a0abf..7b12f96ef 100644 --- a/docs/docs/icicle/primitives/msm.md +++ b/docs/docs/icicle/primitives/msm.md @@ -1,6 +1,6 @@ # MSM - Multi scalar multiplication -MSM stands for Multi scalar multiplication, its defined as: +MSM stands for Multi scalar multiplication, it's defined as: M @@ -43,7 +43,7 @@ $a_0, \ldots, a_n$ - Scalars $MSM(a, G) \in G$ - a single EC (elliptic curve) point -In words, MSM is the sum of scalar and EC point multiplications. We can see from this definition that the core operations occurring are Modular Multiplication and Elliptic curve point addition. Its obvious that multiplication can be computed in parallel and then the products summed, making MSM inherently parallelizable. +In words, MSM is the sum of scalar and EC point multiplications. We can see from this definition that the core operations occurring are Modular Multiplication and Elliptic curve point addition. It's obvious that multiplication can be computed in parallel and then the products summed, making MSM inherently parallelizable. Accelerating MSM is crucial to a ZK protocol's performance due to the [large percent of run time](https://hackmd.io/@0xMonia/SkQ6-oRz3#Hardware-acceleration-in-action) they take when generating proofs. @@ -131,7 +131,7 @@ Large buckets exist in two cases: 2. When `c` does not divide the scalar bit-size. `large_bucket_factor` that is equal to 10 yields good results for most cases, but it's best to fine tune this parameter per `c` and per scalar distribution. -The two most important parameters for performance are `c` and the `precompute_factor`. They affect the number of EC additions as well as the memory size. When the points are not known in advance we cannot use precomputation. In this case the best `c` value is usually around $log_2(msmSize) - 4$. However, in most protocols the points are known in advanced and precomputation can be used unless limited by memory. Usually it's best to use maximum precomputation (such that we end up with only a single bucket module) combined we a `c` value around $log_2(msmSize) - 1$. +The two most important parameters for performance are `c` and the `precompute_factor`. They affect the number of EC additions as well as the memory size. When the points are not known in advance we cannot use precomputation. In this case the best `c` value is usually around $log_2(msmSize) - 4$. However, in most protocols the points are known in advance and precomputation can be used unless limited by memory. Usually it's best to use maximum precomputation (such that we end up with only a single bucket module) combined with a `c` value around $log_2(msmSize) - 1$. ## Memory usage estimation diff --git a/docs/docs/icicle/primitives/ntt.md b/docs/docs/icicle/primitives/ntt.md index 9816b3dce..3dd014086 100644 --- a/docs/docs/icicle/primitives/ntt.md +++ b/docs/docs/icicle/primitives/ntt.md @@ -56,7 +56,7 @@ Choosing an algorithm is heavily dependent on your use case. For example Cooley- NTT also supports two different modes `Batch NTT` and `Single NTT` -Deciding weather to use `batch NTT` vs `single NTT` is highly dependent on your application and use case. +Deciding whether to use `batch NTT` vs `single NTT` is highly dependent on your application and use case. #### Single NTT diff --git a/docs/docs/icicle/primitives/poseidon.md b/docs/docs/icicle/primitives/poseidon.md index 5626701b9..3a59f06e4 100644 --- a/docs/docs/icicle/primitives/poseidon.md +++ b/docs/docs/icicle/primitives/poseidon.md @@ -1,6 +1,6 @@ # Poseidon -[Poseidon](https://eprint.iacr.org/2019/458.pdf) is a popular hash in the ZK ecosystem primarily because its optimized to work over large prime fields, a common setting for ZK proofs, thereby minimizing the number of multiplicative operations required. +[Poseidon](https://eprint.iacr.org/2019/458.pdf) is a popular hash in the ZK ecosystem primarily because it's optimized to work over large prime fields, a common setting for ZK proofs, thereby minimizing the number of multiplicative operations required. Poseidon has also been specifically designed to be efficient when implemented within ZK circuits, Poseidon uses far less constraints compared to other hash functions like Keccak or SHA-256 in the context of ZK circuits. @@ -42,7 +42,7 @@ To generate a secure hash output, the algorithm goes through a series of "full r **Linear Transformation and Round Constants:** A linear transformation is performed and round constants are added. The linear transformation in partial rounds can be designed to be less computationally intensive (this is done by using a sparse matrix) than in full rounds, further optimizing the function's efficiency. -The user of Poseidon can often choose how many partial or full rounds he wishes to apply; more full rounds will increase security but degrade performance. The choice and balance is highly dependent on the use case. +The user of Poseidon can often choose how many partial or full rounds he wishes to apply; more full rounds will increase security but degrade performance. The choice and balance are highly dependent on the use case. ## Using Poseidon @@ -60,7 +60,7 @@ So for Poseidon of arity 2 and input of size 1024 * 2, we would expect 1024 elem Poseidon is extremely customizable and using different constants will produce different hashes, security levels and performance results. -We support pre-calculated and optimized constants for each of the [supported curves](../core#supported-curves-and-operations).The constants can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants) and are labeled clearly per curve `_poseidon.h`. +We support pre-calculated and optimized constants for each of the [supported curves](../core#supported-curves-and-operations). The constants can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants) and are labeled clearly per curve `_poseidon.h`. If you wish to generate your own constants you can use our python script which can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants/generate_parameters.py). @@ -135,7 +135,7 @@ impl<'a> Default for HashConfig<'a> { } ``` -In the example above `Poseidon::load(arity, &ctx).unwrap();` is used which will load the correct constants based on arity and curve. Its possible to [generate](#constants) your own constants and load them. +In the example above `Poseidon::load(arity, &ctx).unwrap();` is used which will load the correct constants based on arity and curve. It's possible to [generate](#constants) your own constants and load them. ```rust let ctx = get_default_device_context(); From 1eb6a7e3d6f910023eec2c3e149cc8cba8fded36 Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 09:07:43 +0200 Subject: [PATCH 12/38] fixed fromAffine and toProj in golang --- wrappers/golang/core/internal/mock_curve.go | 11 ++++++++--- wrappers/golang/curves/bls12377/curve.go | 11 ++++++++--- wrappers/golang/curves/bls12377/g2/curve.go | 11 ++++++++--- wrappers/golang/curves/bls12381/curve.go | 11 ++++++++--- wrappers/golang/curves/bls12381/g2/curve.go | 11 ++++++++--- wrappers/golang/curves/bn254/curve.go | 11 ++++++++--- wrappers/golang/curves/bn254/g2/curve.go | 11 ++++++++--- wrappers/golang/curves/bw6761/curve.go | 11 ++++++++--- wrappers/golang/curves/bw6761/g2/curve.go | 11 ++++++++--- wrappers/golang/curves/grumpkin/curve.go | 11 ++++++++--- .../internal/generator/curves/templates/curve.go.tmpl | 11 ++++++++--- 11 files changed, 88 insertions(+), 33 deletions(-) diff --git a/wrappers/golang/core/internal/mock_curve.go b/wrappers/golang/core/internal/mock_curve.go index de21b3d92..a980aeb38 100644 --- a/wrappers/golang/core/internal/mock_curve.go +++ b/wrappers/golang/core/internal/mock_curve.go @@ -33,7 +33,9 @@ func (p *MockProjective) FromAffine(a MockAffine) MockProjective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -73,8 +75,11 @@ func (a MockAffine) ToProjective() MockProjective { var z MockBaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p MockProjective - return p.Zero() + return MockProjective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return MockProjective{ diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go index 8083669ab..c24c71731 100644 --- a/wrappers/golang/curves/bls12377/curve.go +++ b/wrappers/golang/curves/bls12377/curve.go @@ -44,7 +44,9 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return Projective{ diff --git a/wrappers/golang/curves/bls12377/g2/curve.go b/wrappers/golang/curves/bls12377/g2/curve.go index 7da1d2717..433e83642 100644 --- a/wrappers/golang/curves/bls12377/g2/curve.go +++ b/wrappers/golang/curves/bls12377/g2/curve.go @@ -44,7 +44,9 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() + return G2Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return G2Projective{ diff --git a/wrappers/golang/curves/bls12381/curve.go b/wrappers/golang/curves/bls12381/curve.go index 02cee7b64..f4646914b 100644 --- a/wrappers/golang/curves/bls12381/curve.go +++ b/wrappers/golang/curves/bls12381/curve.go @@ -44,7 +44,9 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return Projective{ diff --git a/wrappers/golang/curves/bls12381/g2/curve.go b/wrappers/golang/curves/bls12381/g2/curve.go index d4fced658..701513316 100644 --- a/wrappers/golang/curves/bls12381/g2/curve.go +++ b/wrappers/golang/curves/bls12381/g2/curve.go @@ -44,7 +44,9 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() + return G2Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return G2Projective{ diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go index 3bc94a8f0..c91ee0cd6 100644 --- a/wrappers/golang/curves/bn254/curve.go +++ b/wrappers/golang/curves/bn254/curve.go @@ -44,7 +44,9 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return Projective{ diff --git a/wrappers/golang/curves/bn254/g2/curve.go b/wrappers/golang/curves/bn254/g2/curve.go index 7ee0ec7f9..58456188a 100644 --- a/wrappers/golang/curves/bn254/g2/curve.go +++ b/wrappers/golang/curves/bn254/g2/curve.go @@ -44,7 +44,9 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() + return G2Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return G2Projective{ diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go index 2e8518be9..7d881dd90 100644 --- a/wrappers/golang/curves/bw6761/curve.go +++ b/wrappers/golang/curves/bw6761/curve.go @@ -44,7 +44,9 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return Projective{ diff --git a/wrappers/golang/curves/bw6761/g2/curve.go b/wrappers/golang/curves/bw6761/g2/curve.go index 1433602a2..dcb523e34 100644 --- a/wrappers/golang/curves/bw6761/g2/curve.go +++ b/wrappers/golang/curves/bw6761/g2/curve.go @@ -44,7 +44,9 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() + return G2Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return G2Projective{ diff --git a/wrappers/golang/curves/grumpkin/curve.go b/wrappers/golang/curves/grumpkin/curve.go index 1079ce2e4..d23ff2417 100644 --- a/wrappers/golang/curves/grumpkin/curve.go +++ b/wrappers/golang/curves/grumpkin/curve.go @@ -44,7 +44,9 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() } else { p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() + return Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return Projective{ diff --git a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl index d02fe6a96..15eecef98 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl @@ -44,7 +44,9 @@ func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.Cur z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() + p.X = z.Zero() + p.Y = z.One() + p.Z = z.Zero() }else{ p.X = a.X p.Y = a.Y @@ -114,8 +116,11 @@ func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { var z {{.CurvePrefix}}BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p {{.CurvePrefix}}Projective - return p.Zero() + return {{.CurvePrefix}}Projective{ + X: z.Zero(), + Y: z.One(), + Z: z.Zero(), + } } return {{.CurvePrefix}}Projective{ From d2f8c30ec3346e778b5f8839c9d26441a475d98a Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:36:14 +0200 Subject: [PATCH 13/38] use zero method of projective in fromAffine Co-authored-by: Jeremy Felder --- .../golang/internal/generator/curves/templates/curve.go.tmpl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl index 15eecef98..a43bee98e 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl @@ -44,9 +44,7 @@ func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.Cur z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() }else{ p.X = a.X p.Y = a.Y From 0d22e9b05819ad556394e5c75a619f51a79b687f Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:37:02 +0200 Subject: [PATCH 14/38] use zero method of projective in toProjective Co-authored-by: Jeremy Felder --- .../internal/generator/curves/templates/curve.go.tmpl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl index a43bee98e..d02fe6a96 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl @@ -114,11 +114,8 @@ func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { var z {{.CurvePrefix}}BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return {{.CurvePrefix}}Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p {{.CurvePrefix}}Projective + return p.Zero() } return {{.CurvePrefix}}Projective{ From a7ca5ddb87aa5d6b409988101cf0fac56b3e36d2 Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:41:32 +0200 Subject: [PATCH 15/38] generated go files --- wrappers/golang/core/internal/mock_curve.go | 11 +++-------- wrappers/golang/curves/bls12377/curve.go | 11 +++-------- wrappers/golang/curves/bls12377/g2/curve.go | 11 +++-------- wrappers/golang/curves/bls12381/curve.go | 11 +++-------- wrappers/golang/curves/bls12381/g2/curve.go | 11 +++-------- wrappers/golang/curves/bn254/curve.go | 11 +++-------- wrappers/golang/curves/bn254/g2/curve.go | 11 +++-------- wrappers/golang/curves/bw6761/curve.go | 11 +++-------- wrappers/golang/curves/bw6761/g2/curve.go | 11 +++-------- wrappers/golang/curves/grumpkin/curve.go | 11 +++-------- 10 files changed, 30 insertions(+), 80 deletions(-) diff --git a/wrappers/golang/core/internal/mock_curve.go b/wrappers/golang/core/internal/mock_curve.go index a980aeb38..de21b3d92 100644 --- a/wrappers/golang/core/internal/mock_curve.go +++ b/wrappers/golang/core/internal/mock_curve.go @@ -33,9 +33,7 @@ func (p *MockProjective) FromAffine(a MockAffine) MockProjective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -75,11 +73,8 @@ func (a MockAffine) ToProjective() MockProjective { var z MockBaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return MockProjective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p MockProjective + return p.Zero() } return MockProjective{ diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go index c24c71731..8083669ab 100644 --- a/wrappers/golang/curves/bls12377/curve.go +++ b/wrappers/golang/curves/bls12377/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ diff --git a/wrappers/golang/curves/bls12377/g2/curve.go b/wrappers/golang/curves/bls12377/g2/curve.go index 433e83642..7da1d2717 100644 --- a/wrappers/golang/curves/bls12377/g2/curve.go +++ b/wrappers/golang/curves/bls12377/g2/curve.go @@ -44,9 +44,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return G2Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p G2Projective + return p.Zero() } return G2Projective{ diff --git a/wrappers/golang/curves/bls12381/curve.go b/wrappers/golang/curves/bls12381/curve.go index f4646914b..02cee7b64 100644 --- a/wrappers/golang/curves/bls12381/curve.go +++ b/wrappers/golang/curves/bls12381/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ diff --git a/wrappers/golang/curves/bls12381/g2/curve.go b/wrappers/golang/curves/bls12381/g2/curve.go index 701513316..d4fced658 100644 --- a/wrappers/golang/curves/bls12381/g2/curve.go +++ b/wrappers/golang/curves/bls12381/g2/curve.go @@ -44,9 +44,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return G2Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p G2Projective + return p.Zero() } return G2Projective{ diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go index c91ee0cd6..3bc94a8f0 100644 --- a/wrappers/golang/curves/bn254/curve.go +++ b/wrappers/golang/curves/bn254/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ diff --git a/wrappers/golang/curves/bn254/g2/curve.go b/wrappers/golang/curves/bn254/g2/curve.go index 58456188a..7ee0ec7f9 100644 --- a/wrappers/golang/curves/bn254/g2/curve.go +++ b/wrappers/golang/curves/bn254/g2/curve.go @@ -44,9 +44,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return G2Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p G2Projective + return p.Zero() } return G2Projective{ diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go index 7d881dd90..2e8518be9 100644 --- a/wrappers/golang/curves/bw6761/curve.go +++ b/wrappers/golang/curves/bw6761/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ diff --git a/wrappers/golang/curves/bw6761/g2/curve.go b/wrappers/golang/curves/bw6761/g2/curve.go index dcb523e34..1433602a2 100644 --- a/wrappers/golang/curves/bw6761/g2/curve.go +++ b/wrappers/golang/curves/bw6761/g2/curve.go @@ -44,9 +44,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a G2Affine) ToProjective() G2Projective { var z G2BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return G2Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p G2Projective + return p.Zero() } return G2Projective{ diff --git a/wrappers/golang/curves/grumpkin/curve.go b/wrappers/golang/curves/grumpkin/curve.go index d23ff2417..1079ce2e4 100644 --- a/wrappers/golang/curves/grumpkin/curve.go +++ b/wrappers/golang/curves/grumpkin/curve.go @@ -44,9 +44,7 @@ func (p *Projective) FromAffine(a Affine) Projective { z.One() if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.X = z.Zero() - p.Y = z.One() - p.Z = z.Zero() + p.Zero() } else { p.X = a.X p.Y = a.Y @@ -116,11 +114,8 @@ func (a Affine) ToProjective() Projective { var z BaseField if (a.X == z.Zero()) && (a.Y == z.Zero()) { - return Projective{ - X: z.Zero(), - Y: z.One(), - Z: z.Zero(), - } + var p Projective + return p.Zero() } return Projective{ From c7863d465ef3ea8e489f69df3f694d1dc8ef7185 Mon Sep 17 00:00:00 2001 From: Vlad <88586482+vladfdp@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:03:58 +0200 Subject: [PATCH 16/38] refactor from_affine with C link --- icicle/src/curves/extern.cu | 5 +++ icicle/src/curves/extern_g2.cu | 5 +++ wrappers/golang/core/internal/mock_curve.go | 30 -------------- wrappers/golang/curves/bls12377/curve.go | 31 ++++---------- wrappers/golang/curves/bls12377/g2/curve.go | 31 ++++---------- .../golang/curves/bls12377/g2/include/curve.h | 1 + .../golang/curves/bls12377/include/curve.h | 1 + wrappers/golang/curves/bls12381/curve.go | 31 ++++---------- wrappers/golang/curves/bls12381/g2/curve.go | 31 ++++---------- .../golang/curves/bls12381/g2/include/curve.h | 1 + .../golang/curves/bls12381/include/curve.h | 1 + wrappers/golang/curves/bn254/curve.go | 31 ++++---------- wrappers/golang/curves/bn254/g2/curve.go | 31 ++++---------- .../golang/curves/bn254/g2/include/curve.h | 1 + wrappers/golang/curves/bn254/include/curve.h | 1 + wrappers/golang/curves/bw6761/curve.go | 31 ++++---------- wrappers/golang/curves/bw6761/g2/curve.go | 31 ++++---------- .../golang/curves/bw6761/g2/include/curve.h | 1 + wrappers/golang/curves/bw6761/include/curve.h | 1 + wrappers/golang/curves/grumpkin/curve.go | 31 ++++---------- .../golang/curves/grumpkin/include/curve.h | 1 + .../generator/curves/templates/curve.go.tmpl | 41 ++++++++----------- .../generator/curves/templates/curve.h.tmpl | 1 + wrappers/rust/icicle-core/src/curve.rs | 30 +++++++------- 24 files changed, 131 insertions(+), 269 deletions(-) diff --git a/icicle/src/curves/extern.cu b/icicle/src/curves/extern.cu index 8ea5bce2f..a40d24ffd 100644 --- a/icicle/src/curves/extern.cu +++ b/icicle/src/curves/extern.cu @@ -20,6 +20,11 @@ extern "C" void CONCAT_EXPAND(CURVE, to_affine)(projective_t* point, affine_t* p *point_out = projective_t::to_affine(*point); } +extern "C" void CONCAT_EXPAND(CURVE, from_affine)(affine_t* point, projective_t* point_out) +{ + *point_out = projective_t::from_affine(*point); +} + extern "C" void CONCAT_EXPAND(CURVE, generate_projective_points)(projective_t* points, int size) { projective_t::rand_host_many(points, size); diff --git a/icicle/src/curves/extern_g2.cu b/icicle/src/curves/extern_g2.cu index e8daa5e11..6d1e44146 100644 --- a/icicle/src/curves/extern_g2.cu +++ b/icicle/src/curves/extern_g2.cu @@ -20,6 +20,11 @@ extern "C" void CONCAT_EXPAND(CURVE, g2_to_affine)(g2_projective_t* point, g2_af *point_out = g2_projective_t::to_affine(*point); } +extern "C" void CONCAT_EXPAND(CURVE, g2_from_affine)(g2_affine_t* point, g2_projective_t* point_out) +{ + *point_out = g2_projective_t::from_affine(*point); +} + extern "C" void CONCAT_EXPAND(CURVE, g2_generate_projective_points)(g2_projective_t* points, int size) { g2_projective_t::rand_host_many(points, size); diff --git a/wrappers/golang/core/internal/mock_curve.go b/wrappers/golang/core/internal/mock_curve.go index de21b3d92..dddbddee7 100644 --- a/wrappers/golang/core/internal/mock_curve.go +++ b/wrappers/golang/core/internal/mock_curve.go @@ -28,21 +28,6 @@ func (p *MockProjective) FromLimbs(x, y, z []uint32) MockProjective { return *p } -func (p *MockProjective) FromAffine(a MockAffine) MockProjective { - z := MockBaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } - - return *p -} - type MockAffine struct { X, Y MockBaseField } @@ -68,18 +53,3 @@ func (a *MockAffine) FromLimbs(x, y []uint32) MockAffine { return *a } - -func (a MockAffine) ToProjective() MockProjective { - var z MockBaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p MockProjective - return p.Zero() - } - - return MockProjective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } -} diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go index 8083669ab..43184ff56 100644 --- a/wrappers/golang/curves/bls12377/curve.go +++ b/wrappers/golang/curves/bls12377/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.bls12_377_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.bls12_377_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bls12_377_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/bls12377/g2/curve.go b/wrappers/golang/curves/bls12377/g2/curve.go index 7da1d2717..4544e9735 100644 --- a/wrappers/golang/curves/bls12377/g2/curve.go +++ b/wrappers/golang/curves/bls12377/g2/curve.go @@ -40,17 +40,10 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { } func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) + C.bls12_377_g2_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine { var a G2Affine cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bls12_377_g2_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { } func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() - } + var p G2Projective - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bls12_377_g2_from_affine(cA, cP) + return p } func G2AffineFromProjective(p *G2Projective) G2Affine { diff --git a/wrappers/golang/curves/bls12377/g2/include/curve.h b/wrappers/golang/curves/bls12377/g2/include/curve.h index b136de9a8..57d5e148f 100644 --- a/wrappers/golang/curves/bls12377/g2/include/curve.h +++ b/wrappers/golang/curves/bls12377/g2/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bls12_377_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bls12_377_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bls12_377_g2_from_affine(g2_affine_t* point, g2_projective_t* point_out); void bls12_377_g2_generate_projective_points(g2_projective_t* points, int size); void bls12_377_g2_generate_affine_points(g2_affine_t* points, int size); cudaError_t bls12_377_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bls12377/include/curve.h b/wrappers/golang/curves/bls12377/include/curve.h index 87a0229b6..6f32d1c36 100644 --- a/wrappers/golang/curves/bls12377/include/curve.h +++ b/wrappers/golang/curves/bls12377/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bls12_377_eq(projective_t* point1, projective_t* point2); void bls12_377_to_affine(projective_t* point, affine_t* point_out); +void bls12_377_from_affine(affine_t* point, projective_t* point_out); void bls12_377_generate_projective_points(projective_t* points, int size); void bls12_377_generate_affine_points(affine_t* points, int size); cudaError_t bls12_377_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bls12381/curve.go b/wrappers/golang/curves/bls12381/curve.go index 02cee7b64..3b1b59ea2 100644 --- a/wrappers/golang/curves/bls12381/curve.go +++ b/wrappers/golang/curves/bls12381/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.bls12_381_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.bls12_381_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bls12_381_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/bls12381/g2/curve.go b/wrappers/golang/curves/bls12381/g2/curve.go index d4fced658..b9256e002 100644 --- a/wrappers/golang/curves/bls12381/g2/curve.go +++ b/wrappers/golang/curves/bls12381/g2/curve.go @@ -40,17 +40,10 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { } func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) + C.bls12_381_g2_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine { var a G2Affine cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bls12_381_g2_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { } func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() - } + var p G2Projective - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bls12_381_g2_from_affine(cA, cP) + return p } func G2AffineFromProjective(p *G2Projective) G2Affine { diff --git a/wrappers/golang/curves/bls12381/g2/include/curve.h b/wrappers/golang/curves/bls12381/g2/include/curve.h index b7710244d..274f3ec16 100644 --- a/wrappers/golang/curves/bls12381/g2/include/curve.h +++ b/wrappers/golang/curves/bls12381/g2/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bls12_381_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bls12_381_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bls12_381_g2_from_affine(g2_affine_t* point, g2_projective_t* point_out); void bls12_381_g2_generate_projective_points(g2_projective_t* points, int size); void bls12_381_g2_generate_affine_points(g2_affine_t* points, int size); cudaError_t bls12_381_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bls12381/include/curve.h b/wrappers/golang/curves/bls12381/include/curve.h index 1cb3bd61e..b9a50675c 100644 --- a/wrappers/golang/curves/bls12381/include/curve.h +++ b/wrappers/golang/curves/bls12381/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bls12_381_eq(projective_t* point1, projective_t* point2); void bls12_381_to_affine(projective_t* point, affine_t* point_out); +void bls12_381_from_affine(affine_t* point, projective_t* point_out); void bls12_381_generate_projective_points(projective_t* points, int size); void bls12_381_generate_affine_points(affine_t* points, int size); cudaError_t bls12_381_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go index 3bc94a8f0..c2b6b1b8d 100644 --- a/wrappers/golang/curves/bn254/curve.go +++ b/wrappers/golang/curves/bn254/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.bn254_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.bn254_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bn254_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/bn254/g2/curve.go b/wrappers/golang/curves/bn254/g2/curve.go index 7ee0ec7f9..72245e02b 100644 --- a/wrappers/golang/curves/bn254/g2/curve.go +++ b/wrappers/golang/curves/bn254/g2/curve.go @@ -40,17 +40,10 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { } func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) + C.bn254_g2_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine { var a G2Affine cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bn254_g2_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { } func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() - } + var p G2Projective - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bn254_g2_from_affine(cA, cP) + return p } func G2AffineFromProjective(p *G2Projective) G2Affine { diff --git a/wrappers/golang/curves/bn254/g2/include/curve.h b/wrappers/golang/curves/bn254/g2/include/curve.h index e8863f1ef..c24deb307 100644 --- a/wrappers/golang/curves/bn254/g2/include/curve.h +++ b/wrappers/golang/curves/bn254/g2/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bn254_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bn254_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bn254_g2_from_affine(g2_affine_t* point, g2_projective_t* point_out); void bn254_g2_generate_projective_points(g2_projective_t* points, int size); void bn254_g2_generate_affine_points(g2_affine_t* points, int size); cudaError_t bn254_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bn254/include/curve.h b/wrappers/golang/curves/bn254/include/curve.h index 069600aa4..ce29f587a 100644 --- a/wrappers/golang/curves/bn254/include/curve.h +++ b/wrappers/golang/curves/bn254/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bn254_eq(projective_t* point1, projective_t* point2); void bn254_to_affine(projective_t* point, affine_t* point_out); +void bn254_from_affine(affine_t* point, projective_t* point_out); void bn254_generate_projective_points(projective_t* points, int size); void bn254_generate_affine_points(affine_t* points, int size); cudaError_t bn254_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go index 2e8518be9..334499441 100644 --- a/wrappers/golang/curves/bw6761/curve.go +++ b/wrappers/golang/curves/bw6761/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.bw6_761_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.bw6_761_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bw6_761_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/bw6761/g2/curve.go b/wrappers/golang/curves/bw6761/g2/curve.go index 1433602a2..f38bf134f 100644 --- a/wrappers/golang/curves/bw6761/g2/curve.go +++ b/wrappers/golang/curves/bw6761/g2/curve.go @@ -40,17 +40,10 @@ func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { } func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) + C.bw6_761_g2_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine { var a G2Affine cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP := (*C.g2_projective_t)(unsafe.Pointer(p)) C.bw6_761_g2_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { } func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p G2Projective - return p.Zero() - } + var p G2Projective - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bw6_761_g2_from_affine(cA, cP) + return p } func G2AffineFromProjective(p *G2Projective) G2Affine { diff --git a/wrappers/golang/curves/bw6761/g2/include/curve.h b/wrappers/golang/curves/bw6761/g2/include/curve.h index b57b55cfc..8d113fc90 100644 --- a/wrappers/golang/curves/bw6761/g2/include/curve.h +++ b/wrappers/golang/curves/bw6761/g2/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bw6_761_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bw6_761_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bw6_761_g2_from_affine(g2_affine_t* point, g2_projective_t* point_out); void bw6_761_g2_generate_projective_points(g2_projective_t* points, int size); void bw6_761_g2_generate_affine_points(g2_affine_t* points, int size); cudaError_t bw6_761_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/bw6761/include/curve.h b/wrappers/golang/curves/bw6761/include/curve.h index cc6e401cb..ba243029c 100644 --- a/wrappers/golang/curves/bw6761/include/curve.h +++ b/wrappers/golang/curves/bw6761/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool bw6_761_eq(projective_t* point1, projective_t* point2); void bw6_761_to_affine(projective_t* point, affine_t* point_out); +void bw6_761_from_affine(affine_t* point, projective_t* point_out); void bw6_761_generate_projective_points(projective_t* points, int size); void bw6_761_generate_affine_points(affine_t* points, int size); cudaError_t bw6_761_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/curves/grumpkin/curve.go b/wrappers/golang/curves/grumpkin/curve.go index 1079ce2e4..1411a246b 100644 --- a/wrappers/golang/curves/grumpkin/curve.go +++ b/wrappers/golang/curves/grumpkin/curve.go @@ -40,17 +40,10 @@ func (p *Projective) FromLimbs(x, y, z []uint32) Projective { } func (p *Projective) FromAffine(a Affine) Projective { - z := BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - } else { - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(p)) + C.grumpkin_from_affine(cA, cP) return *p } @@ -65,7 +58,7 @@ func (p *Projective) ProjectiveToAffine() Affine { var a Affine cA := (*C.affine_t)(unsafe.Pointer(&a)) - cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP := (*C.projective_t)(unsafe.Pointer(p)) C.grumpkin_to_affine(cP, cA) return a } @@ -111,18 +104,12 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine { } func (a Affine) ToProjective() Projective { - var z BaseField - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p Projective - return p.Zero() - } + var p Projective - return Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.grumpkin_from_affine(cA, cP) + return p } func AffineFromProjective(p *Projective) Affine { diff --git a/wrappers/golang/curves/grumpkin/include/curve.h b/wrappers/golang/curves/grumpkin/include/curve.h index 8466982ed..6005b280c 100644 --- a/wrappers/golang/curves/grumpkin/include/curve.h +++ b/wrappers/golang/curves/grumpkin/include/curve.h @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool grumpkin_eq(projective_t* point1, projective_t* point2); void grumpkin_to_affine(projective_t* point, affine_t* point_out); +void grumpkin_from_affine(affine_t* point, projective_t* point_out); void grumpkin_generate_projective_points(projective_t* points, int size); void grumpkin_generate_affine_points(affine_t* points, int size); cudaError_t grumpkin_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl index d02fe6a96..1378557e3 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.go.tmpl @@ -39,21 +39,16 @@ func (p *{{.CurvePrefix}}Projective) FromLimbs(x, y, z []uint32) {{.CurvePrefix} return *p } -func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.CurvePrefix}}Projective { - z := {{.CurvePrefix}}BaseField{} - z.One() - - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - p.Zero() - }else{ - p.X = a.X - p.Y = a.Y - p.Z = z.One() - } +{{if ne .CurvePrefix "Mock"}} +func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.CurvePrefix}}Projective { + + cA := (*C.{{toCName .CurvePrefix}}affine_t)(unsafe.Pointer(&a)) + cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(p)) + C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_from_affine(cA, cP) return *p } -{{if ne .CurvePrefix "Mock"}} + func (p {{.CurvePrefix}}Projective) ProjectiveEq(p2 *{{.CurvePrefix}}Projective) bool { cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p)) cP2 := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p2)) @@ -65,7 +60,7 @@ func (p *{{.CurvePrefix}}Projective) ProjectiveToAffine() {{.CurvePrefix}}Affine var a {{.CurvePrefix}}Affine cA := (*C.{{toCName .CurvePrefix}}affine_t)(unsafe.Pointer(&a)) - cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p)) + cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(p)) C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_to_affine(cP, cA) return a } @@ -110,21 +105,17 @@ func (a *{{.CurvePrefix}}Affine) FromLimbs(x, y []uint32) {{.CurvePrefix}}Affine return *a } -func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { - var z {{.CurvePrefix}}BaseField - if (a.X == z.Zero()) && (a.Y == z.Zero()) { - var p {{.CurvePrefix}}Projective - return p.Zero() - } +{{if ne .CurvePrefix "Mock"}} +func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { + var p {{.CurvePrefix}}Projective - return {{.CurvePrefix}}Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } + cA := (*C.{{toCName .CurvePrefix}}affine_t)(unsafe.Pointer(&a)) + cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p)) + C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_from_affine(cA, cP) + return p } -{{if ne .CurvePrefix "Mock"}} + func {{.CurvePrefix}}AffineFromProjective(p *{{.CurvePrefix}}Projective) {{.CurvePrefix}}Affine { return p.ProjectiveToAffine() } diff --git a/wrappers/golang/internal/generator/curves/templates/curve.h.tmpl b/wrappers/golang/internal/generator/curves/templates/curve.h.tmpl index 22179e6f6..0dffd240f 100644 --- a/wrappers/golang/internal/generator/curves/templates/curve.h.tmpl +++ b/wrappers/golang/internal/generator/curves/templates/curve.h.tmpl @@ -14,6 +14,7 @@ typedef struct DeviceContext DeviceContext; bool {{.Curve}}{{toCNameBackwards .CurvePrefix}}_eq({{toCName .CurvePrefix}}projective_t* point1, {{toCName .CurvePrefix}}projective_t* point2); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_to_affine({{toCName .CurvePrefix}}projective_t* point, {{toCName .CurvePrefix}}affine_t* point_out); +void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_from_affine({{toCName .CurvePrefix}}affine_t* point, {{toCName .CurvePrefix}}projective_t* point_out); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_projective_points({{toCName .CurvePrefix}}projective_t* points, int size); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_affine_points({{toCName .CurvePrefix}}affine_t* points, int size); cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_affine_convert_montgomery({{toCName .CurvePrefix}}affine_t* points, size_t n, bool is_into, DeviceContext* ctx); diff --git a/wrappers/rust/icicle-core/src/curve.rs b/wrappers/rust/icicle-core/src/curve.rs index c0b82d113..a0bf70bc6 100644 --- a/wrappers/rust/icicle-core/src/curve.rs +++ b/wrappers/rust/icicle-core/src/curve.rs @@ -22,6 +22,8 @@ pub trait Curve: Debug + PartialEq + Copy + Clone { #[doc(hidden)] fn to_affine(point: *const Projective, point_aff: *mut Affine); #[doc(hidden)] + fn from_affine(point: *const Affine, point_proj: *mut Projective); + #[doc(hidden)] fn generate_random_projective_points(size: usize) -> Vec>; #[doc(hidden)] fn generate_random_affine_points(size: usize) -> Vec>; @@ -79,27 +81,17 @@ impl Affine { } pub fn to_projective(&self) -> Projective { - if *self == Self::zero() { - return Projective::::zero(); - } - Projective { - x: self.x, - y: self.y, - z: C::BaseField::one(), - } + let mut proj = Projective::::zero(); + C::from_affine(self as *const Self, &mut proj as *mut Projective); + proj } } impl From> for Projective { fn from(item: Affine) -> Self { - if item == (Affine::::zero()) { - return Self::zero(); - } - Self { - x: item.x, - y: item.y, - z: C::BaseField::one(), - } + let mut proj = Self::zero(); + C::from_affine(&item as *const Affine, &mut proj as *mut Self); + proj } } @@ -282,6 +274,8 @@ macro_rules! impl_curve { pub(crate) fn eq(point1: *const $projective_type, point2: *const $projective_type) -> bool; #[link_name = concat!($curve_prefix, "_to_affine")] pub(crate) fn proj_to_affine(point: *const $projective_type, point_out: *mut $affine_type); + #[link_name = concat!($curve_prefix, "_from_affine")] + pub(crate) fn proj_from_affine(point: *const $affine_type, point_out: *mut $projective_type); #[link_name = concat!($curve_prefix, "_generate_projective_points")] pub(crate) fn generate_projective_points(points: *mut $projective_type, size: usize); #[link_name = concat!($curve_prefix, "_generate_affine_points")] @@ -315,6 +309,10 @@ macro_rules! impl_curve { unsafe { $curve_prefix_ident::proj_to_affine(point, point_out) }; } + fn from_affine(point: *const $affine_type, point_out: *mut $projective_type) { + unsafe { $curve_prefix_ident::proj_from_affine(point, point_out) }; + } + fn generate_random_projective_points(size: usize) -> Vec<$projective_type> { let mut res = vec![$projective_type::zero(); size]; unsafe { From 01b1dde0591f6a22bf3d7bf23c4b26a9aae33c46 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Tue, 16 Jul 2024 22:00:46 +0000 Subject: [PATCH 17/38] babybear v3 bindings --- wrappers/golang_v3/README.md | 121 +++++ wrappers/golang_v3/build.ps1 | 23 + wrappers/golang_v3/build.sh | 127 ++++++ .../golang_v3/core/internal/mock_curve.go | 76 ++++ .../golang_v3/core/internal/mock_field.go | 84 ++++ wrappers/golang_v3/core/msm.go | 121 +++++ wrappers/golang_v3/core/msm_test.go | 104 +++++ wrappers/golang_v3/core/ntt.go | 108 +++++ wrappers/golang_v3/core/ntt_test.go | 92 ++++ wrappers/golang_v3/core/slice.go | 275 ++++++++++++ wrappers/golang_v3/core/slice_test.go | 250 +++++++++++ wrappers/golang_v3/core/utils.go | 26 ++ wrappers/golang_v3/core/utils_test.go | 78 ++++ wrappers/golang_v3/core/vec_ops.go | 110 +++++ wrappers/golang_v3/core/vec_ops_test.go | 21 + .../golang_v3/curves/bls12377/base_field.go | 84 ++++ wrappers/golang_v3/curves/bls12377/curve.go | 177 ++++++++ .../golang_v3/curves/bls12377/ecntt/ecntt.go | 24 + .../curves/bls12377/ecntt/include/ecntt.h | 19 + .../golang_v3/curves/bls12377/g2/curve.go | 177 ++++++++ .../curves/bls12377/g2/g2base_field.go | 84 ++++ .../curves/bls12377/g2/include/curve.h | 26 ++ .../curves/bls12377/g2/include/msm.h | 25 ++ .../curves/bls12377/g2/include/scalar_field.h | 21 + wrappers/golang_v3/curves/bls12377/g2/msm.go | 63 +++ .../golang_v3/curves/bls12377/include/curve.h | 26 ++ .../curves/bls12377/include/scalar_field.h | 21 + wrappers/golang_v3/curves/bls12377/main.go | 4 + .../curves/bls12377/msm/include/msm.h | 25 ++ wrappers/golang_v3/curves/bls12377/msm/msm.go | 63 +++ .../curves/bls12377/ntt/include/ntt.h | 23 + wrappers/golang_v3/curves/bls12377/ntt/ntt.go | 56 +++ .../bls12377/polynomial/include/polynomial.h | 51 +++ .../curves/bls12377/polynomial/polynomial.go | 176 ++++++++ .../bls12377/poseidon/include/poseidon.h | 25 ++ .../curves/bls12377/poseidon/poseidon.go | 57 +++ .../golang_v3/curves/bls12377/scalar_field.go | 121 +++++ .../curves/bls12377/tests/base_field_test.go | 88 ++++ .../curves/bls12377/tests/curve_test.go | 103 +++++ .../curves/bls12377/tests/ecntt_test.go | 30 ++ .../curves/bls12377/tests/g2_curve_test.go | 103 +++++ .../bls12377/tests/g2_g2base_field_test.go | 88 ++++ .../curves/bls12377/tests/g2_msm_test.go | 371 ++++++++++++++++ .../curves/bls12377/tests/main_test.go | 48 ++ .../curves/bls12377/tests/msm_test.go | 331 ++++++++++++++ .../curves/bls12377/tests/ntt_test.go | 263 +++++++++++ .../curves/bls12377/tests/polynomial_test.go | 229 ++++++++++ .../curves/bls12377/tests/poseidon_test.go | 42 ++ .../bls12377/tests/scalar_field_test.go | 120 +++++ .../curves/bls12377/tests/vec_ops_test.go | 69 +++ .../curves/bls12377/vecOps/include/vec_ops.h | 53 +++ .../curves/bls12377/vecOps/vec_ops.go | 48 ++ .../golang_v3/curves/bls12381/base_field.go | 84 ++++ wrappers/golang_v3/curves/bls12381/curve.go | 177 ++++++++ .../golang_v3/curves/bls12381/ecntt/ecntt.go | 24 + .../curves/bls12381/ecntt/include/ecntt.h | 19 + .../golang_v3/curves/bls12381/g2/curve.go | 177 ++++++++ .../curves/bls12381/g2/g2base_field.go | 84 ++++ .../curves/bls12381/g2/include/curve.h | 26 ++ .../curves/bls12381/g2/include/msm.h | 25 ++ .../curves/bls12381/g2/include/scalar_field.h | 21 + wrappers/golang_v3/curves/bls12381/g2/msm.go | 63 +++ .../golang_v3/curves/bls12381/include/curve.h | 26 ++ .../curves/bls12381/include/scalar_field.h | 21 + wrappers/golang_v3/curves/bls12381/main.go | 4 + .../curves/bls12381/msm/include/msm.h | 25 ++ wrappers/golang_v3/curves/bls12381/msm/msm.go | 63 +++ .../curves/bls12381/ntt/include/ntt.h | 23 + wrappers/golang_v3/curves/bls12381/ntt/ntt.go | 56 +++ .../bls12381/polynomial/include/polynomial.h | 51 +++ .../curves/bls12381/polynomial/polynomial.go | 176 ++++++++ .../bls12381/poseidon/include/poseidon.h | 25 ++ .../curves/bls12381/poseidon/poseidon.go | 57 +++ .../golang_v3/curves/bls12381/scalar_field.go | 121 +++++ .../curves/bls12381/tests/base_field_test.go | 88 ++++ .../curves/bls12381/tests/curve_test.go | 103 +++++ .../curves/bls12381/tests/ecntt_test.go | 30 ++ .../curves/bls12381/tests/g2_curve_test.go | 103 +++++ .../bls12381/tests/g2_g2base_field_test.go | 88 ++++ .../curves/bls12381/tests/g2_msm_test.go | 371 ++++++++++++++++ .../curves/bls12381/tests/main_test.go | 48 ++ .../curves/bls12381/tests/msm_test.go | 331 ++++++++++++++ .../curves/bls12381/tests/ntt_test.go | 263 +++++++++++ .../curves/bls12381/tests/polynomial_test.go | 229 ++++++++++ .../curves/bls12381/tests/poseidon_test.go | 55 +++ .../bls12381/tests/scalar_field_test.go | 120 +++++ .../curves/bls12381/tests/vec_ops_test.go | 69 +++ .../curves/bls12381/vecOps/include/vec_ops.h | 53 +++ .../curves/bls12381/vecOps/vec_ops.go | 48 ++ wrappers/golang_v3/curves/bn254/base_field.go | 84 ++++ wrappers/golang_v3/curves/bn254/curve.go | 177 ++++++++ .../golang_v3/curves/bn254/ecntt/ecntt.go | 24 + .../curves/bn254/ecntt/include/ecntt.h | 19 + wrappers/golang_v3/curves/bn254/g2/curve.go | 177 ++++++++ .../golang_v3/curves/bn254/g2/g2base_field.go | 84 ++++ .../golang_v3/curves/bn254/g2/include/curve.h | 26 ++ .../golang_v3/curves/bn254/g2/include/msm.h | 25 ++ .../curves/bn254/g2/include/scalar_field.h | 21 + wrappers/golang_v3/curves/bn254/g2/msm.go | 63 +++ .../golang_v3/curves/bn254/include/curve.h | 26 ++ .../curves/bn254/include/scalar_field.h | 21 + wrappers/golang_v3/curves/bn254/main.go | 4 + .../golang_v3/curves/bn254/msm/include/msm.h | 25 ++ wrappers/golang_v3/curves/bn254/msm/msm.go | 63 +++ .../golang_v3/curves/bn254/ntt/include/ntt.h | 23 + wrappers/golang_v3/curves/bn254/ntt/ntt.go | 56 +++ .../bn254/polynomial/include/polynomial.h | 51 +++ .../curves/bn254/polynomial/polynomial.go | 176 ++++++++ .../curves/bn254/poseidon/include/poseidon.h | 25 ++ .../curves/bn254/poseidon/poseidon.go | 57 +++ .../golang_v3/curves/bn254/scalar_field.go | 121 +++++ .../curves/bn254/tests/base_field_test.go | 88 ++++ .../curves/bn254/tests/curve_test.go | 103 +++++ .../curves/bn254/tests/ecntt_test.go | 30 ++ .../curves/bn254/tests/g2_curve_test.go | 103 +++++ .../bn254/tests/g2_g2base_field_test.go | 88 ++++ .../curves/bn254/tests/g2_msm_test.go | 371 ++++++++++++++++ .../golang_v3/curves/bn254/tests/main_test.go | 48 ++ .../golang_v3/curves/bn254/tests/msm_test.go | 331 ++++++++++++++ .../golang_v3/curves/bn254/tests/ntt_test.go | 263 +++++++++++ .../curves/bn254/tests/polynomial_test.go | 229 ++++++++++ .../curves/bn254/tests/poseidon_test.go | 42 ++ .../curves/bn254/tests/scalar_field_test.go | 120 +++++ .../curves/bn254/tests/vec_ops_test.go | 69 +++ .../curves/bn254/vecOps/include/vec_ops.h | 53 +++ .../golang_v3/curves/bn254/vecOps/vec_ops.go | 48 ++ .../golang_v3/curves/bw6761/base_field.go | 84 ++++ wrappers/golang_v3/curves/bw6761/curve.go | 177 ++++++++ .../golang_v3/curves/bw6761/ecntt/ecntt.go | 24 + .../curves/bw6761/ecntt/include/ecntt.h | 19 + wrappers/golang_v3/curves/bw6761/g2/curve.go | 177 ++++++++ .../curves/bw6761/g2/g2base_field.go | 84 ++++ .../curves/bw6761/g2/include/curve.h | 26 ++ .../golang_v3/curves/bw6761/g2/include/msm.h | 25 ++ .../curves/bw6761/g2/include/scalar_field.h | 21 + wrappers/golang_v3/curves/bw6761/g2/msm.go | 63 +++ .../golang_v3/curves/bw6761/include/curve.h | 26 ++ .../curves/bw6761/include/scalar_field.h | 21 + wrappers/golang_v3/curves/bw6761/main.go | 4 + .../golang_v3/curves/bw6761/msm/include/msm.h | 25 ++ wrappers/golang_v3/curves/bw6761/msm/msm.go | 63 +++ .../golang_v3/curves/bw6761/ntt/include/ntt.h | 23 + wrappers/golang_v3/curves/bw6761/ntt/ntt.go | 56 +++ .../bw6761/polynomial/include/polynomial.h | 51 +++ .../curves/bw6761/polynomial/polynomial.go | 176 ++++++++ .../curves/bw6761/poseidon/include/poseidon.h | 25 ++ .../curves/bw6761/poseidon/poseidon.go | 57 +++ .../golang_v3/curves/bw6761/scalar_field.go | 121 +++++ .../curves/bw6761/tests/base_field_test.go | 88 ++++ .../curves/bw6761/tests/curve_test.go | 103 +++++ .../curves/bw6761/tests/ecntt_test.go | 30 ++ .../curves/bw6761/tests/g2_curve_test.go | 103 +++++ .../bw6761/tests/g2_g2base_field_test.go | 88 ++++ .../curves/bw6761/tests/g2_msm_test.go | 331 ++++++++++++++ .../curves/bw6761/tests/main_test.go | 48 ++ .../golang_v3/curves/bw6761/tests/msm_test.go | 331 ++++++++++++++ .../golang_v3/curves/bw6761/tests/ntt_test.go | 263 +++++++++++ .../curves/bw6761/tests/polynomial_test.go | 229 ++++++++++ .../curves/bw6761/tests/poseidon_test.go | 42 ++ .../curves/bw6761/tests/scalar_field_test.go | 120 +++++ .../curves/bw6761/tests/vec_ops_test.go | 69 +++ .../curves/bw6761/vecOps/include/vec_ops.h | 53 +++ .../golang_v3/curves/bw6761/vecOps/vec_ops.go | 48 ++ .../golang_v3/curves/grumpkin/base_field.go | 84 ++++ wrappers/golang_v3/curves/grumpkin/curve.go | 177 ++++++++ .../golang_v3/curves/grumpkin/include/curve.h | 26 ++ .../curves/grumpkin/include/scalar_field.h | 21 + wrappers/golang_v3/curves/grumpkin/main.go | 4 + .../curves/grumpkin/msm/include/msm.h | 25 ++ wrappers/golang_v3/curves/grumpkin/msm/msm.go | 63 +++ .../grumpkin/poseidon/include/poseidon.h | 25 ++ .../curves/grumpkin/poseidon/poseidon.go | 57 +++ .../golang_v3/curves/grumpkin/scalar_field.go | 121 +++++ .../curves/grumpkin/tests/base_field_test.go | 88 ++++ .../curves/grumpkin/tests/curve_test.go | 103 +++++ .../curves/grumpkin/tests/main_test.go | 17 + .../curves/grumpkin/tests/msm_test.go | 213 +++++++++ .../curves/grumpkin/tests/poseidon_test.go | 42 ++ .../grumpkin/tests/scalar_field_test.go | 120 +++++ .../curves/grumpkin/tests/vec_ops_test.go | 69 +++ .../curves/grumpkin/vecOps/include/vec_ops.h | 53 +++ .../curves/grumpkin/vecOps/vec_ops.go | 48 ++ .../babybear/extension/extension_field.go | 119 +++++ .../babybear/extension/include/scalar_field.h | 22 + .../babybear/extension/ntt/include/ntt.h | 22 + .../fields/babybear/extension/ntt/ntt.go | 24 + .../extension/vecOps/include/vec_ops.h | 51 +++ .../babybear/extension/vecOps/vec_ops.go | 44 ++ .../fields/babybear/include/scalar_field.h | 21 + wrappers/golang_v3/fields/babybear/main.go | 4 + .../fields/babybear/ntt/include/ntt.h | 24 + wrappers/golang_v3/fields/babybear/ntt/ntt.go | 59 +++ .../babybear/polynomial/include/polynomial.h | 50 +++ .../fields/babybear/polynomial/polynomial.go | 172 ++++++++ .../golang_v3/fields/babybear/scalar_field.go | 119 +++++ .../fields/babybear/tests/main_test.go | 46 ++ .../babybear/tests/ntt_no_domain_test.go | 82 ++++ .../fields/babybear/tests/ntt_test.go | 170 +++++++ .../fields/babybear/tests/polynomial_test.go | 230 ++++++++++ .../babybear/tests/scalar_field_test.go | 121 +++++ .../fields/babybear/tests/vec_ops_test.go | 66 +++ .../fields/babybear/vecOps/include/vec_ops.h | 51 +++ .../fields/babybear/vecOps/vec_ops.go | 44 ++ wrappers/golang_v3/hash/keccak/hasher.go | 88 ++++ .../golang_v3/hash/keccak/include/keccak.h | 20 + wrappers/golang_v3/hash/keccak/main.go | 4 + .../hash/keccak/tests/hasher_test.go | 66 +++ .../internal/generator/config/babybear.go | 17 + .../internal/generator/config/bls12377.go | 19 + .../internal/generator/config/bls12381.go | 19 + .../internal/generator/config/bn254.go | 19 + .../internal/generator/config/bw6761.go | 19 + .../internal/generator/config/config.go | 50 +++ .../internal/generator/config/grumpkin.go | 19 + .../internal/generator/curves/generate.go | 42 ++ .../generator/curves/templates/curve.go.tmpl | 178 ++++++++ .../generator/curves/templates/curve.h.tmpl | 26 ++ .../curves/templates/curve_test.go.tmpl | 103 +++++ .../generator/curves/templates/main.go.tmpl | 4 + .../internal/generator/ecntt/generate.go | 29 ++ .../generator/ecntt/templates/ecntt.go.tmpl | 24 + .../generator/ecntt/templates/ecntt.h.tmpl | 19 + .../ecntt/templates/ecntt_test.go.tmpl | 30 ++ .../internal/generator/fields/generate.go | 47 ++ .../generator/fields/templates/field.go.tmpl | 124 ++++++ .../fields/templates/field_test.go.tmpl | 121 +++++ .../generator/fields/templates/main.go.tmpl | 4 + .../fields/templates/scalar_field.h.tmpl | 21 + .../generator/generator_utils/generate.go | 107 +++++ .../internal/generator/lib_linker/generate.go | 33 ++ wrappers/golang_v3/internal/generator/main.go | 100 +++++ .../internal/generator/mock/generate.go | 38 ++ .../internal/generator/msm/generate.go | 39 ++ .../generator/msm/templates/msm.go.tmpl | 63 +++ .../generator/msm/templates/msm.h.tmpl | 25 ++ .../generator/msm/templates/msm_test.go.tmpl | 417 ++++++++++++++++++ .../internal/generator/ntt/generate.go | 54 +++ .../generator/ntt/templates/ntt.go.tmpl | 58 +++ .../generator/ntt/templates/ntt.h.tmpl | 24 + .../ntt/templates/ntt_no_domain_test.go.tmpl | 85 ++++ .../generator/ntt/templates/ntt_test.go.tmpl | 277 ++++++++++++ .../internal/generator/polynomial/generate.go | 31 ++ .../polynomial/templates/polynomial.go.tmpl | 176 ++++++++ .../polynomial/templates/polynomial.h.tmpl | 51 +++ .../templates/polynomial_test.go.tmpl | 229 ++++++++++ .../internal/generator/poseidon/generate.go | 32 ++ .../poseidon/templates/poseidon.go.tmpl | 57 +++ .../poseidon/templates/poseidon.h.tmpl | 25 ++ .../poseidon/templates/poseidon_test.go.tmpl | 59 +++ .../internal/generator/tests/generate.go | 29 ++ .../tests/templates/main_test.go.tmpl | 58 +++ .../internal/generator/vecOps/generate.go | 39 ++ .../vecOps/templates/vec_ops.go.tmpl | 48 ++ .../generator/vecOps/templates/vec_ops.h.tmpl | 53 +++ .../vecOps/templates/vec_ops_test.go.tmpl | 69 +++ wrappers/golang_v3/runtime/config.go | 51 +++ wrappers/golang_v3/runtime/device.go | 40 ++ wrappers/golang_v3/runtime/errors.go | 20 + .../runtime/include/config_extension.h | 24 + wrappers/golang_v3/runtime/include/runtime.h | 41 ++ wrappers/golang_v3/runtime/main.go | 4 + wrappers/golang_v3/runtime/memory.go | 76 ++++ wrappers/golang_v3/runtime/runtime.go | 116 +++++ wrappers/golang_v3/runtime/stream.go | 30 ++ .../golang_v3/runtime/tests/config_test.go | 71 +++ .../golang_v3/runtime/tests/device_test.go | 16 + .../golang_v3/runtime/tests/runtime_test.go | 84 ++++ .../golang_v3/runtime/tests/stream_test.go | 55 +++ wrappers/golang_v3/test_helpers/helpers.go | 31 ++ 269 files changed, 21869 insertions(+) create mode 100644 wrappers/golang_v3/README.md create mode 100644 wrappers/golang_v3/build.ps1 create mode 100755 wrappers/golang_v3/build.sh create mode 100644 wrappers/golang_v3/core/internal/mock_curve.go create mode 100644 wrappers/golang_v3/core/internal/mock_field.go create mode 100644 wrappers/golang_v3/core/msm.go create mode 100644 wrappers/golang_v3/core/msm_test.go create mode 100644 wrappers/golang_v3/core/ntt.go create mode 100644 wrappers/golang_v3/core/ntt_test.go create mode 100644 wrappers/golang_v3/core/slice.go create mode 100644 wrappers/golang_v3/core/slice_test.go create mode 100644 wrappers/golang_v3/core/utils.go create mode 100644 wrappers/golang_v3/core/utils_test.go create mode 100644 wrappers/golang_v3/core/vec_ops.go create mode 100644 wrappers/golang_v3/core/vec_ops_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/base_field.go create mode 100644 wrappers/golang_v3/curves/bls12377/curve.go create mode 100644 wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go create mode 100644 wrappers/golang_v3/curves/bls12377/ecntt/include/ecntt.h create mode 100644 wrappers/golang_v3/curves/bls12377/g2/curve.go create mode 100644 wrappers/golang_v3/curves/bls12377/g2/g2base_field.go create mode 100644 wrappers/golang_v3/curves/bls12377/g2/include/curve.h create mode 100644 wrappers/golang_v3/curves/bls12377/g2/include/msm.h create mode 100644 wrappers/golang_v3/curves/bls12377/g2/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/bls12377/g2/msm.go create mode 100644 wrappers/golang_v3/curves/bls12377/include/curve.h create mode 100644 wrappers/golang_v3/curves/bls12377/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/bls12377/main.go create mode 100644 wrappers/golang_v3/curves/bls12377/msm/include/msm.h create mode 100644 wrappers/golang_v3/curves/bls12377/msm/msm.go create mode 100644 wrappers/golang_v3/curves/bls12377/ntt/include/ntt.h create mode 100644 wrappers/golang_v3/curves/bls12377/ntt/ntt.go create mode 100644 wrappers/golang_v3/curves/bls12377/polynomial/include/polynomial.h create mode 100644 wrappers/golang_v3/curves/bls12377/polynomial/polynomial.go create mode 100644 wrappers/golang_v3/curves/bls12377/poseidon/include/poseidon.h create mode 100644 wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go create mode 100644 wrappers/golang_v3/curves/bls12377/scalar_field.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/base_field_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/curve_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/g2_g2base_field_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/main_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/msm_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/ntt_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/polynomial_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/scalar_field_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/tests/vec_ops_test.go create mode 100644 wrappers/golang_v3/curves/bls12377/vecOps/include/vec_ops.h create mode 100644 wrappers/golang_v3/curves/bls12377/vecOps/vec_ops.go create mode 100644 wrappers/golang_v3/curves/bls12381/base_field.go create mode 100644 wrappers/golang_v3/curves/bls12381/curve.go create mode 100644 wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go create mode 100644 wrappers/golang_v3/curves/bls12381/ecntt/include/ecntt.h create mode 100644 wrappers/golang_v3/curves/bls12381/g2/curve.go create mode 100644 wrappers/golang_v3/curves/bls12381/g2/g2base_field.go create mode 100644 wrappers/golang_v3/curves/bls12381/g2/include/curve.h create mode 100644 wrappers/golang_v3/curves/bls12381/g2/include/msm.h create mode 100644 wrappers/golang_v3/curves/bls12381/g2/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/bls12381/g2/msm.go create mode 100644 wrappers/golang_v3/curves/bls12381/include/curve.h create mode 100644 wrappers/golang_v3/curves/bls12381/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/bls12381/main.go create mode 100644 wrappers/golang_v3/curves/bls12381/msm/include/msm.h create mode 100644 wrappers/golang_v3/curves/bls12381/msm/msm.go create mode 100644 wrappers/golang_v3/curves/bls12381/ntt/include/ntt.h create mode 100644 wrappers/golang_v3/curves/bls12381/ntt/ntt.go create mode 100644 wrappers/golang_v3/curves/bls12381/polynomial/include/polynomial.h create mode 100644 wrappers/golang_v3/curves/bls12381/polynomial/polynomial.go create mode 100644 wrappers/golang_v3/curves/bls12381/poseidon/include/poseidon.h create mode 100644 wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go create mode 100644 wrappers/golang_v3/curves/bls12381/scalar_field.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/base_field_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/curve_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/g2_g2base_field_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/main_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/msm_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/ntt_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/polynomial_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/scalar_field_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/tests/vec_ops_test.go create mode 100644 wrappers/golang_v3/curves/bls12381/vecOps/include/vec_ops.h create mode 100644 wrappers/golang_v3/curves/bls12381/vecOps/vec_ops.go create mode 100644 wrappers/golang_v3/curves/bn254/base_field.go create mode 100644 wrappers/golang_v3/curves/bn254/curve.go create mode 100644 wrappers/golang_v3/curves/bn254/ecntt/ecntt.go create mode 100644 wrappers/golang_v3/curves/bn254/ecntt/include/ecntt.h create mode 100644 wrappers/golang_v3/curves/bn254/g2/curve.go create mode 100644 wrappers/golang_v3/curves/bn254/g2/g2base_field.go create mode 100644 wrappers/golang_v3/curves/bn254/g2/include/curve.h create mode 100644 wrappers/golang_v3/curves/bn254/g2/include/msm.h create mode 100644 wrappers/golang_v3/curves/bn254/g2/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/bn254/g2/msm.go create mode 100644 wrappers/golang_v3/curves/bn254/include/curve.h create mode 100644 wrappers/golang_v3/curves/bn254/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/bn254/main.go create mode 100644 wrappers/golang_v3/curves/bn254/msm/include/msm.h create mode 100644 wrappers/golang_v3/curves/bn254/msm/msm.go create mode 100644 wrappers/golang_v3/curves/bn254/ntt/include/ntt.h create mode 100644 wrappers/golang_v3/curves/bn254/ntt/ntt.go create mode 100644 wrappers/golang_v3/curves/bn254/polynomial/include/polynomial.h create mode 100644 wrappers/golang_v3/curves/bn254/polynomial/polynomial.go create mode 100644 wrappers/golang_v3/curves/bn254/poseidon/include/poseidon.h create mode 100644 wrappers/golang_v3/curves/bn254/poseidon/poseidon.go create mode 100644 wrappers/golang_v3/curves/bn254/scalar_field.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/base_field_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/curve_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/ecntt_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/main_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/msm_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/ntt_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/polynomial_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/poseidon_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/scalar_field_test.go create mode 100644 wrappers/golang_v3/curves/bn254/tests/vec_ops_test.go create mode 100644 wrappers/golang_v3/curves/bn254/vecOps/include/vec_ops.h create mode 100644 wrappers/golang_v3/curves/bn254/vecOps/vec_ops.go create mode 100644 wrappers/golang_v3/curves/bw6761/base_field.go create mode 100644 wrappers/golang_v3/curves/bw6761/curve.go create mode 100644 wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go create mode 100644 wrappers/golang_v3/curves/bw6761/ecntt/include/ecntt.h create mode 100644 wrappers/golang_v3/curves/bw6761/g2/curve.go create mode 100644 wrappers/golang_v3/curves/bw6761/g2/g2base_field.go create mode 100644 wrappers/golang_v3/curves/bw6761/g2/include/curve.h create mode 100644 wrappers/golang_v3/curves/bw6761/g2/include/msm.h create mode 100644 wrappers/golang_v3/curves/bw6761/g2/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/bw6761/g2/msm.go create mode 100644 wrappers/golang_v3/curves/bw6761/include/curve.h create mode 100644 wrappers/golang_v3/curves/bw6761/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/bw6761/main.go create mode 100644 wrappers/golang_v3/curves/bw6761/msm/include/msm.h create mode 100644 wrappers/golang_v3/curves/bw6761/msm/msm.go create mode 100644 wrappers/golang_v3/curves/bw6761/ntt/include/ntt.h create mode 100644 wrappers/golang_v3/curves/bw6761/ntt/ntt.go create mode 100644 wrappers/golang_v3/curves/bw6761/polynomial/include/polynomial.h create mode 100644 wrappers/golang_v3/curves/bw6761/polynomial/polynomial.go create mode 100644 wrappers/golang_v3/curves/bw6761/poseidon/include/poseidon.h create mode 100644 wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go create mode 100644 wrappers/golang_v3/curves/bw6761/scalar_field.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/base_field_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/curve_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/g2_g2base_field_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/main_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/msm_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/ntt_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/polynomial_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/scalar_field_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/tests/vec_ops_test.go create mode 100644 wrappers/golang_v3/curves/bw6761/vecOps/include/vec_ops.h create mode 100644 wrappers/golang_v3/curves/bw6761/vecOps/vec_ops.go create mode 100644 wrappers/golang_v3/curves/grumpkin/base_field.go create mode 100644 wrappers/golang_v3/curves/grumpkin/curve.go create mode 100644 wrappers/golang_v3/curves/grumpkin/include/curve.h create mode 100644 wrappers/golang_v3/curves/grumpkin/include/scalar_field.h create mode 100644 wrappers/golang_v3/curves/grumpkin/main.go create mode 100644 wrappers/golang_v3/curves/grumpkin/msm/include/msm.h create mode 100644 wrappers/golang_v3/curves/grumpkin/msm/msm.go create mode 100644 wrappers/golang_v3/curves/grumpkin/poseidon/include/poseidon.h create mode 100644 wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go create mode 100644 wrappers/golang_v3/curves/grumpkin/scalar_field.go create mode 100644 wrappers/golang_v3/curves/grumpkin/tests/base_field_test.go create mode 100644 wrappers/golang_v3/curves/grumpkin/tests/curve_test.go create mode 100644 wrappers/golang_v3/curves/grumpkin/tests/main_test.go create mode 100644 wrappers/golang_v3/curves/grumpkin/tests/msm_test.go create mode 100644 wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go create mode 100644 wrappers/golang_v3/curves/grumpkin/tests/scalar_field_test.go create mode 100644 wrappers/golang_v3/curves/grumpkin/tests/vec_ops_test.go create mode 100644 wrappers/golang_v3/curves/grumpkin/vecOps/include/vec_ops.h create mode 100644 wrappers/golang_v3/curves/grumpkin/vecOps/vec_ops.go create mode 100644 wrappers/golang_v3/fields/babybear/extension/extension_field.go create mode 100644 wrappers/golang_v3/fields/babybear/extension/include/scalar_field.h create mode 100644 wrappers/golang_v3/fields/babybear/extension/ntt/include/ntt.h create mode 100644 wrappers/golang_v3/fields/babybear/extension/ntt/ntt.go create mode 100644 wrappers/golang_v3/fields/babybear/extension/vecOps/include/vec_ops.h create mode 100644 wrappers/golang_v3/fields/babybear/extension/vecOps/vec_ops.go create mode 100644 wrappers/golang_v3/fields/babybear/include/scalar_field.h create mode 100644 wrappers/golang_v3/fields/babybear/main.go create mode 100644 wrappers/golang_v3/fields/babybear/ntt/include/ntt.h create mode 100644 wrappers/golang_v3/fields/babybear/ntt/ntt.go create mode 100644 wrappers/golang_v3/fields/babybear/polynomial/include/polynomial.h create mode 100644 wrappers/golang_v3/fields/babybear/polynomial/polynomial.go create mode 100644 wrappers/golang_v3/fields/babybear/scalar_field.go create mode 100644 wrappers/golang_v3/fields/babybear/tests/main_test.go create mode 100644 wrappers/golang_v3/fields/babybear/tests/ntt_no_domain_test.go create mode 100644 wrappers/golang_v3/fields/babybear/tests/ntt_test.go create mode 100644 wrappers/golang_v3/fields/babybear/tests/polynomial_test.go create mode 100644 wrappers/golang_v3/fields/babybear/tests/scalar_field_test.go create mode 100644 wrappers/golang_v3/fields/babybear/tests/vec_ops_test.go create mode 100644 wrappers/golang_v3/fields/babybear/vecOps/include/vec_ops.h create mode 100644 wrappers/golang_v3/fields/babybear/vecOps/vec_ops.go create mode 100644 wrappers/golang_v3/hash/keccak/hasher.go create mode 100644 wrappers/golang_v3/hash/keccak/include/keccak.h create mode 100644 wrappers/golang_v3/hash/keccak/main.go create mode 100644 wrappers/golang_v3/hash/keccak/tests/hasher_test.go create mode 100644 wrappers/golang_v3/internal/generator/config/babybear.go create mode 100644 wrappers/golang_v3/internal/generator/config/bls12377.go create mode 100644 wrappers/golang_v3/internal/generator/config/bls12381.go create mode 100644 wrappers/golang_v3/internal/generator/config/bn254.go create mode 100644 wrappers/golang_v3/internal/generator/config/bw6761.go create mode 100644 wrappers/golang_v3/internal/generator/config/config.go create mode 100644 wrappers/golang_v3/internal/generator/config/grumpkin.go create mode 100644 wrappers/golang_v3/internal/generator/curves/generate.go create mode 100644 wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/curves/templates/curve.h.tmpl create mode 100644 wrappers/golang_v3/internal/generator/curves/templates/curve_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/ecntt/generate.go create mode 100644 wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.h.tmpl create mode 100644 wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/fields/generate.go create mode 100644 wrappers/golang_v3/internal/generator/fields/templates/field.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/fields/templates/field_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/fields/templates/scalar_field.h.tmpl create mode 100644 wrappers/golang_v3/internal/generator/generator_utils/generate.go create mode 100644 wrappers/golang_v3/internal/generator/lib_linker/generate.go create mode 100644 wrappers/golang_v3/internal/generator/main.go create mode 100644 wrappers/golang_v3/internal/generator/mock/generate.go create mode 100644 wrappers/golang_v3/internal/generator/msm/generate.go create mode 100644 wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl create mode 100644 wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/ntt/generate.go create mode 100644 wrappers/golang_v3/internal/generator/ntt/templates/ntt.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/ntt/templates/ntt.h.tmpl create mode 100644 wrappers/golang_v3/internal/generator/ntt/templates/ntt_no_domain_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/polynomial/generate.go create mode 100644 wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.h.tmpl create mode 100644 wrappers/golang_v3/internal/generator/polynomial/templates/polynomial_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/poseidon/generate.go create mode 100644 wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.h.tmpl create mode 100644 wrappers/golang_v3/internal/generator/poseidon/templates/poseidon_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/tests/generate.go create mode 100644 wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/vecOps/generate.go create mode 100644 wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.go.tmpl create mode 100644 wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.h.tmpl create mode 100644 wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops_test.go.tmpl create mode 100644 wrappers/golang_v3/runtime/config.go create mode 100644 wrappers/golang_v3/runtime/device.go create mode 100644 wrappers/golang_v3/runtime/errors.go create mode 100644 wrappers/golang_v3/runtime/include/config_extension.h create mode 100644 wrappers/golang_v3/runtime/include/runtime.h create mode 100644 wrappers/golang_v3/runtime/main.go create mode 100644 wrappers/golang_v3/runtime/memory.go create mode 100644 wrappers/golang_v3/runtime/runtime.go create mode 100644 wrappers/golang_v3/runtime/stream.go create mode 100644 wrappers/golang_v3/runtime/tests/config_test.go create mode 100644 wrappers/golang_v3/runtime/tests/device_test.go create mode 100644 wrappers/golang_v3/runtime/tests/runtime_test.go create mode 100644 wrappers/golang_v3/runtime/tests/stream_test.go create mode 100644 wrappers/golang_v3/test_helpers/helpers.go diff --git a/wrappers/golang_v3/README.md b/wrappers/golang_v3/README.md new file mode 100644 index 000000000..dbd50cb6d --- /dev/null +++ b/wrappers/golang_v3/README.md @@ -0,0 +1,121 @@ +# Golang Bindings + +In order to build the underlying ICICLE libraries you should run the build script found [here](./build.sh). + +Build script USAGE + +```bash +./build.sh [-curve= | -field=] [-cuda_version=] [-g2] [-ecntt] [-devmode] + +curve - The name of the curve to build or "all" to build all curves +field - The name of the field to build or "all" to build all fields +-g2 - Optional - build with G2 enabled +-ecntt - Optional - build with ECNTT enabled +-devmode - Optional - build in devmode +``` + +To build ICICLE libraries for all supported curves with G2 and ECNTT enabled. + +```sh +./build.sh -curve=all -g2 -ecntt +``` + +If you wish to build for a specific curve, for example bn254, without G2 or ECNTT enabled. + +```sh +./build.sh -curve=bn254 +``` + +## Supported curves, fields and operations + +### Supported curves and operations + +| Operation\Curve | bn254 | bls12_377 | bls12_381 | bw6-761 | grumpkin | +| --- | :---: | :---: | :---: | :---: | :---: | +| MSM | ✅ | ✅ | ✅ | ✅ | ✅ | +| G2 | ✅ | ✅ | ✅ | ✅ | ❌ | +| NTT | ✅ | ✅ | ✅ | ✅ | ❌ | +| ECNTT | ✅ | ✅ | ✅ | ✅ | ❌ | +| VecOps | ✅ | ✅ | ✅ | ✅ | ✅ | +| Polynomials | ✅ | ✅ | ✅ | ✅ | ❌ | + +### Supported fields and operations + +| Operation\Field | babybear | +| --- | :---: | +| VecOps | ✅ | +| Polynomials | ✅ | +| NTT | ✅ | +| Extension Field | ✅ | + +## Running golang tests + +To run the tests for curve bn254. + +```sh +go test ./wrappers/golang/curves/bn254/tests -count=1 -v +``` + +To run all the tests in the golang bindings + +```sh +go test ./... -count=1 -v +``` + +## How do Golang bindings work? + +The libraries produced from the CUDA code compilation are used to bind Golang to ICICLE's CUDA code. + +1. These libraries (named `libingo_curve_.a` and `libingo_field_.a`) can be imported in your Go project to leverage the GPU accelerated functionalities provided by ICICLE. + +2. In your Go project, you can use `cgo` to link these libraries. Here's a basic example on how you can use `cgo` to link these libraries: + +```go +/* +#cgo LDFLAGS: -L$/path/to/shared/libs -lingo_curve_bn254 -L$/path/to/shared/libs -lingo_field_bn254 -lstdc++ -lm +#include "icicle.h" // make sure you use the correct header file(s) +*/ +import "C" + +func main() { + // Now you can call the C functions from the ICICLE libraries. + // Note that C function calls are prefixed with 'C.' in Go code. +} +``` + +Replace `/path/to/shared/libs` with the actual path where the shared libraries are located on your system. + +## Common issues + +### Cannot find shared library + +In some cases you may encounter the following error, despite exporting the correct `LD_LIBRARY_PATH`. + +```sh +/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1 +/usr/bin/ld: cannot find -lbn254: No such file or directory +/usr/bin/ld: cannot find -lbn254: No such file or directory +/usr/bin/ld: cannot find -lbn254: No such file or directory +/usr/bin/ld: cannot find -lbn254: No such file or directory +/usr/bin/ld: cannot find -lbn254: No such file or directory +collect2: error: ld returned 1 exit status +``` + +This is normally fixed by exporting the path to the shared library location in the following way: `export CGO_LDFLAGS="-L//"` + +### cuda_runtime.h: No such file or directory + +```sh +# github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381 +In file included from wrappers/golang/curves/bls12381/curve.go:5: +wrappers/golang/curves/bls12381/include/curve.h:1:10: fatal error: cuda_runtime.h: No such file or directory + 1 | #include + | ^~~~~~~~~~~~~~~~ +compilation terminated. +``` + +Our golang bindings rely on cuda headers and require that they can be found as system headers. Make sure to add the `cuda/include` of your cuda installation to your CPATH + +```sh +export CPATH=$CPATH: +``` diff --git a/wrappers/golang_v3/build.ps1 b/wrappers/golang_v3/build.ps1 new file mode 100644 index 000000000..d64e54bf6 --- /dev/null +++ b/wrappers/golang_v3/build.ps1 @@ -0,0 +1,23 @@ +$G2_DEFINED = "OFF" + +if ($args.Count -gt 1) { + $G2_DEFINED = "ON" +} + +$BUILD_DIR = (Get-Location).Path + "\..\icicle\build" +$SUPPORTED_CURVES = @("bn254", "bls12_377", "bls12_381", "bw6_761") + +if ($args[0] -eq "all") { + $BUILD_CURVES = $SUPPORTED_CURVES +} else { + $BUILD_CURVES = @($args[0]) +} + +Set-Location "../../icicle" + +New-Item -ItemType Directory -Path "build" -Force + +foreach ($CURVE in $BUILD_CURVES) { + cmake -DCURVE:STRING=$CURVE -DG2_DEFINED:STRING=$G2_DEFINED -DCMAKE_BUILD_TYPE:STRING=Release -S . -B build + cmake --build build +} diff --git a/wrappers/golang_v3/build.sh b/wrappers/golang_v3/build.sh new file mode 100755 index 000000000..e3fc6d23a --- /dev/null +++ b/wrappers/golang_v3/build.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +# G2_DEFINED=OFF +# ECNTT_DEFINED=OFF +# CUDA_COMPILER_PATH=/usr/local/cuda/bin/nvcc +# DEVMODE=OFF +# EXT_FIELD=OFF +# BUILD_CURVES=( ) +# BUILD_FIELDS=( ) +# BUILD_HASHES=( ) + +# SUPPORTED_CURVES=("bn254" "bls12_377" "bls12_381" "bw6_761", "grumpkin") +# SUPPORTED_FIELDS=("babybear") +# SUPPORTED_HASHES=("keccak") + +# if [[ $1 == "-help" ]]; then +# echo "Build script for building ICICLE cpp libraries" +# echo "" +# echo "If more than one curve or more than one field is supplied, the last one supplied will be built" +# echo "" +# echo "USAGE: ./build.sh [OPTION...]" +# echo "" +# echo "OPTIONS:" +# echo " -curve= The curve that should be built. If \"all\" is supplied," +# echo " all curves will be built with any other supplied curve options" +# echo " -g2 Builds the curve lib with G2 enabled" +# echo " -ecntt Builds the curve lib with ECNTT enabled" +# echo " -field= The field that should be built. If \"all\" is supplied," +# echo " all fields will be built with any other supplied field options" +# echo " -field-ext Builds the field lib with the extension field enabled" +# echo " -devmode Enables devmode debugging and fast build times" +# echo " -cuda_version= The version of cuda to use for compiling" +# echo "" +# exit 0 +# fi + +# for arg in "$@" +# do +# arg_lower=$(echo "$arg" | tr '[:upper:]' '[:lower:]') +# case "$arg_lower" in +# -cuda_version=*) +# cuda_version=$(echo "$arg" | cut -d'=' -f2) +# CUDA_COMPILER_PATH=/usr/local/cuda-$cuda_version/bin/nvcc +# ;; +# -ecntt) +# ECNTT_DEFINED=ON +# ;; +# -g2) +# G2_DEFINED=ON +# ;; +# -curve=*) +# curve=$(echo "$arg_lower" | cut -d'=' -f2) +# if [[ $curve == "all" ]] +# then +# BUILD_CURVES=("${SUPPORTED_CURVES[@]}") +# else +# BUILD_CURVES=( $curve ) +# fi +# ;; +# -field=*) +# field=$(echo "$arg_lower" | cut -d'=' -f2) +# if [[ $field == "all" ]] +# then +# BUILD_FIELDS=("${SUPPORTED_FIELDS[@]}") +# else +# BUILD_FIELDS=( $field ) +# fi +# ;; +# -field-ext) +# EXT_FIELD=ON +# ;; +# -hash*) +# hash=$(echo "$arg_lower" | cut -d'=' -f2) +# if [[ $hash == "all" ]] +# then +# BUILD_HASHES=("${SUPPORTED_HASHES[@]}") +# else +# BUILD_HASHES=( $hash ) +# fi +# ;; +# -devmode) +# DEVMODE=ON +# ;; +# *) +# echo "Unknown argument: $arg" +# exit 1 +# ;; +# esac +# done + + +BUILD_DIR="${ICICLE_BUILD_DIR:-$(realpath "$PWD/../../icicle_v3/build")}" +export DEFAULT_BACKEND_INSTALL_DIR="${DEFAULT_BACKEND_INSTALL_DIR:="${BUILD_DIR}/backend"}" + +# cd ../../icicle +# mkdir -p build +# rm -f "$BUILD_DIR/CMakeCache.txt" + +# for CURVE in "${BUILD_CURVES[@]}" +# do +# echo "CURVE=${CURVE}" > build_config.txt +# echo "ECNTT=${ECNTT_DEFINED}" >> build_config.txt +# echo "G2=${G2_DEFINED}" >> build_config.txt +# echo "DEVMODE=${DEVMODE}" >> build_config.txt +# cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCURVE=$CURVE -DG2=$G2_DEFINED -DECNTT=$ECNTT_DEFINED -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build +# cmake --build build -j8 && rm build_config.txt +# done + +# # Needs to remove the CMakeCache.txt file to allow building fields after curves +# # have been built since CURVE and FIELD cannot both be defined +# rm -f "$BUILD_DIR/CMakeCache.txt" + +# for FIELD in "${BUILD_FIELDS[@]}" +# do +# echo "FIELD=${FIELD}" > build_config.txt +# echo "DEVMODE=${DEVMODE}" >> build_config.txt +# cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DFIELD=$FIELD -DEXT_FIELD=$EXT_FIELD -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build +# cmake --build build -j8 && rm build_config.txt +# done + +# for HASH in "${BUILD_HASHES[@]}" +# do +# echo "HASH=${HASH_DEFINED}" > build_config.txt +# echo "DEVMODE=${DEVMODE}" >> build_config.txt +# cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DBUILD_HASH=$HASH -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build +# cmake --build build -j8 && rm build_config.txt +# done diff --git a/wrappers/golang_v3/core/internal/mock_curve.go b/wrappers/golang_v3/core/internal/mock_curve.go new file mode 100644 index 000000000..0a6fe8be4 --- /dev/null +++ b/wrappers/golang_v3/core/internal/mock_curve.go @@ -0,0 +1,76 @@ +package internal + +type MockProjective struct { + X, Y, Z MockBaseField +} + +func (p MockProjective) Size() int { + return p.X.Size() * 3 +} + +func (p MockProjective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *MockProjective) Zero() MockProjective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *MockProjective) FromLimbs(x, y, z []uint32) MockProjective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *MockProjective) FromAffine(a MockAffine) MockProjective { + z := MockBaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +type MockAffine struct { + X, Y MockBaseField +} + +func (a MockAffine) Size() int { + return a.X.Size() * 2 +} + +func (a MockAffine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *MockAffine) Zero() MockAffine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *MockAffine) FromLimbs(x, y []uint32) MockAffine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a MockAffine) ToProjective() MockProjective { + var z MockBaseField + + return MockProjective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} diff --git a/wrappers/golang_v3/core/internal/mock_field.go b/wrappers/golang_v3/core/internal/mock_field.go new file mode 100644 index 000000000..ae5ce68a7 --- /dev/null +++ b/wrappers/golang_v3/core/internal/mock_field.go @@ -0,0 +1,84 @@ +package internal + +import ( + "encoding/binary" + "fmt" +) + +const ( + MOCKBASE_LIMBS int = 4 +) + +type MockBaseField struct { + limbs [MOCKBASE_LIMBS]uint32 +} + +func (f MockBaseField) Len() int { + return int(MOCKBASE_LIMBS) +} + +func (f MockBaseField) Size() int { + return int(MOCKBASE_LIMBS * 4) +} + +func (f MockBaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f MockBaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *MockBaseField) FromUint32(v uint32) MockBaseField { + f.limbs[0] = v + return *f +} + +func (f *MockBaseField) FromLimbs(limbs []uint32) MockBaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *MockBaseField) Zero() MockBaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *MockBaseField) One() MockBaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *MockBaseField) FromBytesLittleEndian(bytes []byte) MockBaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f MockBaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/core/msm.go b/wrappers/golang_v3/core/msm.go new file mode 100644 index 000000000..76e46964a --- /dev/null +++ b/wrappers/golang_v3/core/msm.go @@ -0,0 +1,121 @@ +package core + +import ( + "fmt" + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +type MSMConfig struct { + StreamHandle runtime.Stream + basesSize int32 + + /// The number of extra bases to pre-compute for each point. See the `precompute_bases` function, `precompute_factor` passed + /// there needs to be equal to the one used here. Larger values decrease the number of computations + /// to make, on-line memory footprint, but increase the static memory footprint. Default value: 1 (i.e. don't pre-compute). + /// + PrecomputeFactor int32 + + /// `c` value, or "window bitsize" which is the main parameter of the "bucket method" + /// that we use to solve the MSM problem. As a rule of thumb, larger value means more on-line memory + /// footprint but also more parallelism and less computational complexity (up to a certain point). + /// Currently pre-computation is independent of `c`, however in the future value of `c` here and the one passed into the + /// `precompute_bases` function will need to be identical. Default value: 0 (the optimal value of `c` is chosen automatically). + C int32 + + /// Number of bits of the largest scalar. Typically equals the bitsize of scalar field, but if a different + /// (better) upper bound is known, it should be reflected in this variable. Default value: 0 (set to the bitsize of scalar field). + Bitsize int32 + + batchSize int32 + areScalarsOnDevice bool + AreScalarsMontgomeryForm bool + areBasesOnDevice bool + AreBasesMontgomeryForm bool + areResultsOnDevice bool + + /// Whether to run the MSM asynchronously. If set to `true`, the MSM function will be non-blocking + /// and you'd need to synchronize it explicitly by running `cudaStreamSynchronize` or `cudaDeviceSynchronize`. + /// If set to `false`, the MSM function will block the current CPU thread. + IsAsync bool + Ext runtime.ConfigExtension +} + +func GetDefaultMSMConfig() MSMConfig { + return MSMConfig{ + unsafe.Pointer(nil), // StreamHandle + 0, // basesSize + 1, // PrecomputeFactor + 0, // C + 0, // Bitsize + 1, // batchSize + false, // areScalarsOnDevice + false, // AreScalarsMontgomeryForm + false, // areBasesOnDevice + false, // AreBasesMontgomeryForm + false, // areResultsOnDevice + false, // IsAsync + *runtime.CreateConfigExtension(), // Ext + } +} + +func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfig, results HostOrDeviceSlice) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, int, unsafe.Pointer) { + scalarsLength, pointsLength, resultsLength := scalars.Len(), points.Len()/int(cfg.PrecomputeFactor), results.Len() + if scalarsLength%pointsLength != 0 { + errorString := fmt.Sprintf( + "Number of points %d does not divide the number of scalars %d", + pointsLength, + scalarsLength, + ) + panic(errorString) + } + if scalarsLength%resultsLength != 0 { + errorString := fmt.Sprintf( + "Number of results %d does not divide the number of scalars %d", + resultsLength, + scalarsLength, + ) + panic(errorString) + } + + cfg.areScalarsOnDevice = scalars.IsOnDevice() + cfg.areBasesOnDevice = points.IsOnDevice() + cfg.areResultsOnDevice = results.IsOnDevice() + + if scalars.IsOnDevice() { + scalars.(DeviceSlice).CheckDevice() + } + + if points.IsOnDevice() { + points.(DeviceSlice).CheckDevice() + } + + if results.IsOnDevice() { + results.(DeviceSlice).CheckDevice() + } + + size := scalars.Len() / results.Len() + return scalars.AsUnsafePointer(), points.AsUnsafePointer(), results.AsUnsafePointer(), size, unsafe.Pointer(cfg) +} + +func PrecomputePointsCheck(points HostOrDeviceSlice, cfg *MSMConfig, outputBases DeviceSlice) (unsafe.Pointer, unsafe.Pointer) { + outputBasesLength, pointsLength := outputBases.Len(), points.Len() + if outputBasesLength != pointsLength*int(cfg.PrecomputeFactor) { + errorString := fmt.Sprintf( + "Precompute factor is probably incorrect: expected %d but got %d", + outputBasesLength/pointsLength, + cfg.PrecomputeFactor, + ) + panic(errorString) + } + + if points.IsOnDevice() { + points.(DeviceSlice).CheckDevice() + } + + cfg.basesSize = int32(pointsLength) + cfg.areBasesOnDevice = points.IsOnDevice() + + return points.AsUnsafePointer(), outputBases.AsUnsafePointer() +} diff --git a/wrappers/golang_v3/core/msm_test.go b/wrappers/golang_v3/core/msm_test.go new file mode 100644 index 000000000..881d4960c --- /dev/null +++ b/wrappers/golang_v3/core/msm_test.go @@ -0,0 +1,104 @@ +package core + +import ( + "testing" + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core/internal" + "github.com/stretchr/testify/assert" +) + +func TestMSMDefaultConfig(t *testing.T) { + actual := GetDefaultMSMConfig() + + stream := unsafe.Pointer(nil) + expected := MSMConfig{ + stream, // Ctx + 0, // basesSize + 1, // PrecomputeFactor + 0, // C + 0, // Bitsize + 1, // batchSize + false, // areScalarsOnDevice + false, // AreScalarsMontgomeryForm + false, // areBasesOnDevice + false, // AreBasesMontgomeryForm + false, // areResultsOnDevice + false, // IsAsync + actual.Ext, // Ext + } + + assert.EqualValues(t, expected, actual) +} + +func TestMSMCheckHostSlices(t *testing.T) { + cfg := GetDefaultMSMConfig() + + rawScalars := make([]internal.MockBaseField, 10) + for i := range rawScalars { + var emptyField internal.MockBaseField + emptyField.One() + + rawScalars[i] = emptyField + } + scalars := HostSliceFromElements[internal.MockBaseField](rawScalars) + + affine := internal.MockAffine{} + var emptyField internal.MockBaseField + emptyField.One() + affine.FromLimbs(emptyField.GetLimbs(), emptyField.GetLimbs()) + rawAffinePoints := make([]internal.MockAffine, 10) + for i := range rawAffinePoints { + rawAffinePoints[i] = affine + } + points := HostSliceFromElements[internal.MockAffine](rawAffinePoints) + + output := make(HostSlice[internal.MockProjective], 1) + assert.NotPanics(t, func() { MsmCheck(scalars, points, &cfg, output) }) + assert.False(t, cfg.areScalarsOnDevice) + assert.False(t, cfg.areBasesOnDevice) + assert.False(t, cfg.areResultsOnDevice) + assert.Equal(t, int32(1), cfg.batchSize) + + output2 := make(HostSlice[internal.MockProjective], 3) + assert.Panics(t, func() { MsmCheck(scalars, points, &cfg, output2) }) +} + +func TestMSMCheckDeviceSlices(t *testing.T) { + cfg := GetDefaultMSMConfig() + + rawScalars := make([]internal.MockBaseField, 10) + for i := range rawScalars { + var emptyField internal.MockBaseField + emptyField.One() + + rawScalars[i] = emptyField + } + scalars := HostSliceFromElements[internal.MockBaseField](rawScalars) + var scalarsOnDevice DeviceSlice + scalars.CopyToDevice(&scalarsOnDevice, true) + + affine := internal.MockAffine{} + var emptyField internal.MockBaseField + emptyField.One() + affine.FromLimbs(emptyField.GetLimbs(), emptyField.GetLimbs()) + rawAffinePoints := make([]internal.MockAffine, 10) + for i := range rawAffinePoints { + rawAffinePoints[i] = affine + } + points := HostSliceFromElements[internal.MockAffine](rawAffinePoints) + var pointsOnDevice DeviceSlice + points.CopyToDevice(&pointsOnDevice, true) + + output := make(HostSlice[internal.MockProjective], 1) + assert.NotPanics(t, func() { MsmCheck(scalarsOnDevice, pointsOnDevice, &cfg, output) }) + assert.True(t, cfg.areScalarsOnDevice) + assert.True(t, cfg.areBasesOnDevice) + assert.False(t, cfg.areResultsOnDevice) + assert.Equal(t, int32(1), cfg.batchSize) + + output2 := make(HostSlice[internal.MockProjective], 3) + assert.Panics(t, func() { MsmCheck(scalarsOnDevice, pointsOnDevice, &cfg, output2) }) +} + +// TODO add check for batches and batchSize diff --git a/wrappers/golang_v3/core/ntt.go b/wrappers/golang_v3/core/ntt.go new file mode 100644 index 000000000..0105b9810 --- /dev/null +++ b/wrappers/golang_v3/core/ntt.go @@ -0,0 +1,108 @@ +package core + +import ( + "fmt" + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +type NTTDir int8 + +const ( + KForward NTTDir = iota + KInverse +) + +type Ordering uint32 + +const ( + KNN Ordering = iota + KNR + KRN + KRR + KNM + KMN +) + +type NttAlgorithm uint32 + +const ( + Auto NttAlgorithm = iota + Radix2 + MixedRadix +) + +type NTTConfig[T any] struct { + /// Details related to the device such as its id and stream id. See [DeviceContext](@ref device_context::DeviceContext). + StreamHandle runtime.Stream + /// Coset generator. Used to perform coset (i)NTTs. Default value: `S::one()` (corresponding to no coset being used). + CosetGen T + /// The number of NTTs to compute. Default value: 1. + BatchSize int32 + /// If true the function will compute the NTTs over the columns of the input matrix and not over the rows. + ColumnsBatch bool + /// Ordering of inputs and outputs. See [Ordering](@ref Ordering). Default value: `Ordering::kNN`. + Ordering Ordering + areInputsOnDevice bool + areOutputsOnDevice bool + /// Whether to run the NTT asynchronously. If set to `true`, the NTT function will be non-blocking and you'd need to synchronize + /// it explicitly by running `stream.synchronize()`. If set to false, the NTT function will block the current CPU thread. + IsAsync bool + Ext runtime.ConfigExtensionHandler +} + +func GetDefaultNTTConfig[T any](cosetGen T) NTTConfig[T] { + return NTTConfig[T]{ + nil, // StreamHandle + cosetGen, // CosetGen + 1, // BatchSize + false, // ColumnsBatch + KNN, // Ordering + false, // areInputsOnDevice + false, // areOutputsOnDevice + false, // IsAsync + nil, // Ext + } +} + +func NttCheck[T any](input HostOrDeviceSlice, cfg *NTTConfig[T], output HostOrDeviceSlice) (unsafe.Pointer, unsafe.Pointer, int, unsafe.Pointer) { + inputLen, outputLen := input.Len(), output.Len() + if inputLen != outputLen { + errorString := fmt.Sprintf( + "input and output capacities %d; %d are not equal", + inputLen, + outputLen, + ) + panic(errorString) + } + cfg.areInputsOnDevice = input.IsOnDevice() + cfg.areOutputsOnDevice = output.IsOnDevice() + + if input.IsOnDevice() { + input.(DeviceSlice).CheckDevice() + } + + if output.IsOnDevice() { + output.(DeviceSlice).CheckDevice() + } + + size := input.Len() / int(cfg.BatchSize) + cfgPointer := unsafe.Pointer(cfg) + + return input.AsUnsafePointer(), output.AsUnsafePointer(), size, cfgPointer +} + +type NTTInitDomainConfig struct { + StreamHandle runtime.Stream + IsAsync bool + Ext runtime.ConfigExtensionHandler +} + +func GetDefaultNTTInitDomainConfig() NTTInitDomainConfig { + return NTTInitDomainConfig{ + nil, // StreamHandle + false, // IsAsync + nil, // Ext + } +} diff --git a/wrappers/golang_v3/core/ntt_test.go b/wrappers/golang_v3/core/ntt_test.go new file mode 100644 index 000000000..dbdcc4d86 --- /dev/null +++ b/wrappers/golang_v3/core/ntt_test.go @@ -0,0 +1,92 @@ +package core + +import ( + "testing" + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core/internal" + "github.com/stretchr/testify/assert" +) + +func TestNTTDefaultConfig(t *testing.T) { + var cosetGenField internal.MockBaseField + cosetGenField.One() + var cosetGen [1]uint32 + copy(cosetGen[:], cosetGenField.GetLimbs()) + + actual := GetDefaultNTTConfig(cosetGen) + expected := NTTConfig[[1]uint32]{ + unsafe.Pointer(nil), // Ctx + cosetGen, // CosetGen + 1, // BatchSize + false, // ColumnsBatch + KNN, // Ordering + false, // areInputsOnDevice + false, // areOutputsOnDevice + false, // IsAsync + actual.Ext, // ExtensionConfig + } + + assert.Equal(t, expected, actual) +} + +func TestNTTCheckHostScalars(t *testing.T) { + var cosetGen internal.MockBaseField + cosetGen.One() + cfg := GetDefaultNTTConfig(&cosetGen) + + rawInput := make([]internal.MockBaseField, 10) + var emptyField internal.MockBaseField + emptyField.One() + + for i := range rawInput { + rawInput[i] = emptyField + } + + input := HostSliceFromElements[internal.MockBaseField](rawInput) + output := HostSliceFromElements[internal.MockBaseField](rawInput) + assert.NotPanics(t, func() { NttCheck(input, &cfg, output) }) + assert.False(t, cfg.areInputsOnDevice) + assert.False(t, cfg.areOutputsOnDevice) + + rawInputLarger := make([]internal.MockBaseField, 11) + for i := range rawInputLarger { + rawInputLarger[i] = emptyField + } + output2 := HostSliceFromElements[internal.MockBaseField](rawInputLarger) + assert.Panics(t, func() { NttCheck(input, &cfg, output2) }) +} + +func TestNTTCheckDeviceScalars(t *testing.T) { + var cosetGen internal.MockBaseField + cosetGen.One() + cfg := GetDefaultNTTConfig(cosetGen) + + numFields := 10 + rawInput := make([]internal.MockBaseField, numFields) + for i := range rawInput { + var emptyField internal.MockBaseField + emptyField.One() + + rawInput[i] = emptyField + } + + hostElements := HostSliceFromElements[internal.MockBaseField](rawInput) + + var input DeviceSlice + hostElements.CopyToDevice(&input, true) + + fieldBytesSize := hostElements.SizeOfElement() + var output DeviceSlice + output.Malloc(numFields*fieldBytesSize, fieldBytesSize) + + assert.NotPanics(t, func() { NttCheck(input, &cfg, output) }) + assert.True(t, cfg.areInputsOnDevice) + assert.True(t, cfg.areOutputsOnDevice) + + var output2 DeviceSlice + output2.Malloc((numFields+1)*fieldBytesSize, fieldBytesSize) + assert.Panics(t, func() { NttCheck(input, &cfg, output2) }) +} + +// TODO add check for batches and batchSize diff --git a/wrappers/golang_v3/core/slice.go b/wrappers/golang_v3/core/slice.go new file mode 100644 index 000000000..886660026 --- /dev/null +++ b/wrappers/golang_v3/core/slice.go @@ -0,0 +1,275 @@ +package core + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +type HostOrDeviceSlice interface { + Len() int + Cap() int + IsEmpty() bool + IsOnDevice() bool + AsUnsafePointer() unsafe.Pointer +} + +type DevicePointer = unsafe.Pointer + +type DeviceSlice struct { + inner unsafe.Pointer + // capacity is the number of bytes that have been allocated + capacity int + // length is the number of elements that have been written + length int +} + +func (d DeviceSlice) Len() int { + return d.length +} + +func (d DeviceSlice) Cap() int { + return d.capacity +} + +func (d DeviceSlice) IsEmpty() bool { + return d.length == 0 +} + +func (d DeviceSlice) AsUnsafePointer() unsafe.Pointer { + return d.inner +} + +func (d DeviceSlice) IsOnDevice() bool { + return true +} + +// func (d DeviceSlice) GetDeviceId() int { +// return runtime.GetDeviceFromPointer(d.inner) +// } + +// CheckDevice is used to ensure that the DeviceSlice about to be used resides on the currently set device +func (d DeviceSlice) CheckDevice() { + if !runtime.IsActiveDeviceMemory(d.AsUnsafePointer()) { + panic("Attempt to use DeviceSlice on a different device") + } +} + +func (d *DeviceSlice) Range(start, end int, endInclusive bool) DeviceSlice { + if end <= start { + panic("Cannot have negative or zero size slices") + } + + if end >= d.length { + panic("Cannot increase slice size from Range") + } + + var newSlice DeviceSlice + switch { + case start < 0: + panic("Negative value for start is not supported") + case start == 0: + newSlice = d.RangeTo(end, endInclusive) + case start > 0: + tempSlice := d.RangeFrom(start) + newSlice = tempSlice.RangeTo(end-start, endInclusive) + } + return newSlice +} + +func (d *DeviceSlice) RangeTo(end int, inclusive bool) DeviceSlice { + if end <= 0 { + panic("Cannot have negative or zero size slices") + } + + if end >= d.length { + panic("Cannot increase slice size from Range") + } + + var newSlice DeviceSlice + sizeOfElement := d.capacity / d.length + newSlice.length = end + if inclusive { + newSlice.length += 1 + } + newSlice.capacity = newSlice.length * sizeOfElement + newSlice.inner = d.inner + return newSlice +} + +func (d *DeviceSlice) RangeFrom(start int) DeviceSlice { + if start >= d.length { + panic("Cannot have negative or zero size slices") + } + + if start < 0 { + panic("Negative value for start is not supported") + } + + var newSlice DeviceSlice + sizeOfElement := d.capacity / d.length + + newSlice.inner = unsafe.Pointer(uintptr(d.inner) + uintptr(start)*uintptr(sizeOfElement)) + newSlice.length = d.length - start + newSlice.capacity = d.capacity - start*sizeOfElement + + return newSlice +} + +// TODO: change signature to be Malloc(element, numElements) +// calc size internally +func (d *DeviceSlice) Malloc(size, sizeOfElement int) (DeviceSlice, runtime.EIcicleError) { + dp, err := runtime.Malloc(uint(size)) + d.inner = dp + d.capacity = size + d.length = size / sizeOfElement + return *d, err +} + +func (d *DeviceSlice) MallocAsync(size, sizeOfElement int, stream runtime.Stream) (DeviceSlice, runtime.EIcicleError) { + dp, err := runtime.MallocAsync(uint(size), stream) + d.inner = dp + d.capacity = size + d.length = size / sizeOfElement + return *d, err +} + +func (d *DeviceSlice) Free() runtime.EIcicleError { + d.CheckDevice() + err := runtime.Free(d.inner) + if err == runtime.Success { + d.length, d.capacity = 0, 0 + d.inner = nil + } + return err +} + +func (d *DeviceSlice) FreeAsync(stream runtime.Stream) runtime.EIcicleError { + d.CheckDevice() + err := runtime.FreeAsync(d.inner, stream) + if err == runtime.Success { + d.length, d.capacity = 0, 0 + d.inner = nil + } + return err +} + +type HostSlice[T any] []T + +func HostSliceFromElements[T any](elements []T) HostSlice[T] { + return elements +} + +func HostSliceWithValue[T any](underlyingValue T, size int) HostSlice[T] { + slice := make(HostSlice[T], size) + for i := range slice { + slice[i] = underlyingValue + } + + return slice +} + +func (h HostSlice[T]) Len() int { + return len(h) +} + +func (h HostSlice[T]) Cap() int { + return cap(h) +} + +func (h HostSlice[T]) IsEmpty() bool { + return len(h) == 0 +} + +func (h HostSlice[T]) IsOnDevice() bool { + return false +} + +func (h HostSlice[T]) SizeOfElement() int { + return int(unsafe.Sizeof(h[0])) +} + +func (h HostSlice[T]) AsPointer() *T { + return &h[0] +} + +func (h HostSlice[T]) AsUnsafePointer() unsafe.Pointer { + return unsafe.Pointer(&h[0]) +} + +// Registers host memory as pinned, allowing the GPU to read data from the host quicker and save GPU memory space. +// Memory pinned using this function should be unpinned using [Unpin] +// func (h HostSlice[T]) Pin(flags runtime.RegisterPinnedFlags) runtime.EIcicleError { +// _, err := runtime.RegisterPinned(h.AsUnsafePointer(), h.SizeOfElement()*h.Len(), flags) +// return err +// } + +// Unregisters host memory as pinned +// func (h HostSlice[T]) Unpin() runtime.EIcicleError { +// return runtime.FreeRegisteredPinned(h.AsUnsafePointer()) +// } + +// Allocates new host memory as pinned and copies the HostSlice data to the newly allocated area +// Memory pinned using this function should be unpinned using [FreePinned] +// func (h HostSlice[T]) AllocPinned(flags runtime.AllocPinnedFlags) (HostSlice[T], runtime.EIcicleError) { +// pinnedMemPointer, err := runtime.AllocPinned(h.SizeOfElement()*h.Len(), flags) +// if err != runtime.Success { +// return nil, err +// } +// pinnedMem := unsafe.Slice((*T)(pinnedMemPointer), h.Len()) +// copy(pinnedMem, h) +// return pinnedMem, runtime.Success +// } + +// Unpins host memory that was pinned using [AllocPinned] +// func (h HostSlice[T]) FreePinned() runtime.EIcicleError { +// return runtime.FreeAllocPinned(h.AsUnsafePointer()) +// } + +func (h HostSlice[T]) CopyToDevice(dst *DeviceSlice, shouldAllocate bool) *DeviceSlice { + size := h.Len() * h.SizeOfElement() + if shouldAllocate { + dst.Malloc(size, h.SizeOfElement()) + } + dst.CheckDevice() + if size > dst.Cap() { + panic("Number of bytes to copy is too large for destination") + } + + runtime.CopyToDevice(dst.inner, h.AsUnsafePointer(), uint(size)) + dst.length = h.Len() + return dst +} + +func (h HostSlice[T]) CopyToDeviceAsync(dst *DeviceSlice, stream runtime.Stream, shouldAllocate bool) *DeviceSlice { + size := h.Len() * h.SizeOfElement() + if shouldAllocate { + dst.MallocAsync(size, h.SizeOfElement(), stream) + } + dst.CheckDevice() + if size > dst.Cap() { + panic("Number of bytes to copy is too large for destination") + } + + runtime.CopyToDeviceAsync(dst.inner, h.AsUnsafePointer(), uint(size), stream) + dst.length = h.Len() + return dst +} + +func (h HostSlice[T]) CopyFromDevice(src *DeviceSlice) { + src.CheckDevice() + if h.Len() != src.Len() { + panic("destination and source slices have different lengths") + } + bytesSize := src.Len() * h.SizeOfElement() + runtime.CopyFromDevice(h.AsUnsafePointer(), src.inner, uint(bytesSize)) +} + +func (h HostSlice[T]) CopyFromDeviceAsync(src *DeviceSlice, stream runtime.Stream) { + src.CheckDevice() + if h.Len() != src.Len() { + panic("destination and source slices have different lengths") + } + bytesSize := src.Len() * h.SizeOfElement() + runtime.CopyFromDeviceAsync(h.AsUnsafePointer(), src.inner, uint(bytesSize), stream) +} diff --git a/wrappers/golang_v3/core/slice_test.go b/wrappers/golang_v3/core/slice_test.go new file mode 100644 index 000000000..f3a696779 --- /dev/null +++ b/wrappers/golang_v3/core/slice_test.go @@ -0,0 +1,250 @@ +package core + +import ( + "math/rand" + "testing" + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core/internal" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/stretchr/testify/assert" +) + +func randomField(size int) internal.MockBaseField { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + + var field internal.MockBaseField + field.FromLimbs(limbs) + + return field +} + +func randomFields(numFields, fieldSize int) []internal.MockBaseField { + var randFields []internal.MockBaseField + + for i := 0; i < numFields; i++ { + randFields = append(randFields, randomField(fieldSize)) + } + + return randFields +} + +// This function is solely for the purpose of testing HostDeviceSlice +// It can produce invalid points and should not be used to test curve operations +func randomProjectivePoints(numPoints, fieldSize int) []internal.MockProjective { + var randProjectives []internal.MockProjective + + for i := 0; i < numPoints; i++ { + projective := internal.MockProjective{ + X: randomField(fieldSize), + Y: randomField(fieldSize), + Z: randomField(fieldSize), + } + randProjectives = append(randProjectives, projective) + } + + return randProjectives +} + +// This function is solely for the purpose of testing HostDeviceSlice +// It can produce invalid points and should not be used to test curve operations +func randomAffinePoints(numPoints, fieldSize int) []internal.MockAffine { + var randAffines []internal.MockAffine + + for i := 0; i < numPoints; i++ { + affine := internal.MockAffine{ + X: randomField(fieldSize), + Y: randomField(fieldSize), + } + randAffines = append(randAffines, affine) + } + + return randAffines +} + +const ( + numPoints = 4 + numFields = 4 + fieldSize = 4 + fieldBytesSize = fieldSize * 4 +) + +func TestHostSlice(t *testing.T) { + var emptyHostSlice HostSlice[internal.MockBaseField] + assert.Equal(t, emptyHostSlice.Len(), 0) + assert.Equal(t, emptyHostSlice.Cap(), 0) + + randFields := randomFields(numFields, fieldSize) + + hostSlice := HostSliceFromElements(randFields) + assert.Equal(t, hostSlice.Len(), 4) + assert.Equal(t, hostSlice.Cap(), 4) + + hostSliceCasted := (HostSlice[internal.MockBaseField])(randFields) + assert.Equal(t, hostSliceCasted.Len(), 4) + assert.Equal(t, hostSliceCasted.Cap(), 4) +} + +func TestHostSliceIsEmpty(t *testing.T) { + var emptyHostSlice HostSlice[*internal.MockBaseField] + assert.True(t, emptyHostSlice.IsEmpty()) + + randFields := randomFields(numFields, fieldSize) + + hostSlice := HostSliceFromElements(randFields) + assert.False(t, hostSlice.IsEmpty()) +} + +func TestHostSliceIsOnDevice(t *testing.T) { + var emptyHostSlice HostSlice[*internal.MockBaseField] + assert.False(t, emptyHostSlice.IsOnDevice()) +} + +func TestHostSliceSizeOf(t *testing.T) { + randFields := randomFields(numFields, fieldSize) + hostSlice := HostSliceFromElements(randFields) + assert.Equal(t, hostSlice.SizeOfElement(), fieldSize*4) +} + +func TestDeviceSlice(t *testing.T) { + var emptyDeviceSlice DeviceSlice + assert.Equal(t, 0, emptyDeviceSlice.Len()) + assert.Equal(t, 0, emptyDeviceSlice.Cap()) + assert.Equal(t, unsafe.Pointer(nil), emptyDeviceSlice.AsUnsafePointer()) + + emptyDeviceSlice.Malloc(numFields*fieldBytesSize, fieldBytesSize) + assert.Equal(t, numFields, emptyDeviceSlice.Len()) + assert.Equal(t, numFields*fieldBytesSize, emptyDeviceSlice.Cap()) + assert.NotEqual(t, unsafe.Pointer(nil), emptyDeviceSlice.AsUnsafePointer()) + + emptyDeviceSlice.Free() + assert.Equal(t, 0, emptyDeviceSlice.Len()) + assert.Equal(t, 0, emptyDeviceSlice.Cap()) + assert.Equal(t, unsafe.Pointer(nil), emptyDeviceSlice.AsUnsafePointer()) +} + +func TestDeviceSliceIsEmpty(t *testing.T) { + var emptyDeviceSlice DeviceSlice + assert.True(t, emptyDeviceSlice.IsEmpty()) + + const bytes = numFields * fieldBytesSize + emptyDeviceSlice.Malloc(bytes, fieldBytesSize) + + randFields := randomFields(numFields, fieldSize) + hostSlice := HostSliceFromElements(randFields) + + hostSlice.CopyToDevice(&emptyDeviceSlice, false) + assert.False(t, emptyDeviceSlice.IsEmpty()) +} + +func TestDeviceSliceIsOnDevice(t *testing.T) { + var deviceSlice DeviceSlice + assert.True(t, deviceSlice.IsOnDevice()) +} + +func TestCopyToFromHostDeviceField(t *testing.T) { + var emptyDeviceSlice DeviceSlice + + numFields := 1 << 10 + randFields := randomFields(numFields, fieldSize) + hostSlice := HostSliceFromElements(randFields) + hostSlice.CopyToDevice(&emptyDeviceSlice, true) + + randFields2 := randomFields(numFields, fieldSize) + hostSlice2 := HostSliceFromElements(randFields2) + + assert.NotEqual(t, hostSlice, hostSlice2) + hostSlice2.CopyFromDevice(&emptyDeviceSlice) + assert.Equal(t, hostSlice, hostSlice2) +} + +func TestCopyToFromHostDeviceAffinePoints(t *testing.T) { + runtime.LoadBackendFromEnv() + runtime.CreateDevice("CUDA", 0) + + var emptyDeviceSlice DeviceSlice + + numPoints := 1 << 10 + randAffines := randomAffinePoints(numPoints, fieldSize) + hostSlice := HostSliceFromElements(randAffines) + hostSlice.CopyToDevice(&emptyDeviceSlice, true) + + randAffines2 := randomAffinePoints(numPoints, fieldSize) + hostSlice2 := HostSliceFromElements(randAffines2) + + assert.NotEqual(t, hostSlice, hostSlice2) + hostSlice2.CopyFromDevice(&emptyDeviceSlice) + emptyDeviceSlice.Free() + assert.Equal(t, hostSlice, hostSlice2) +} + +func TestCopyToFromHostDeviceProjectivePoints(t *testing.T) { + var emptyDeviceSlice DeviceSlice + + numPoints := 1 << 15 + randProjectives := randomProjectivePoints(numPoints, fieldSize) + hostSlice := HostSliceFromElements(randProjectives) + hostSlice.CopyToDevice(&emptyDeviceSlice, true) + + randProjectives2 := randomProjectivePoints(numPoints, fieldSize) + hostSlice2 := HostSliceFromElements(randProjectives2) + + assert.NotEqual(t, hostSlice, hostSlice2) + hostSlice2.CopyFromDevice(&emptyDeviceSlice) + + assert.Equal(t, hostSlice, hostSlice2) +} + +func TestSliceRanges(t *testing.T) { + var deviceSlice DeviceSlice + + numPoints := 1 << 3 + randProjectives := randomProjectivePoints(numPoints, fieldSize) + hostSlice := (HostSlice[internal.MockProjective])(randProjectives) + hostSlice.CopyToDevice(&deviceSlice, true) + + // RangeFrom + var zeroProj internal.MockProjective + hostSliceRet := HostSliceWithValue[internal.MockProjective](zeroProj, numPoints-2) + + deviceSliceRangeFrom := deviceSlice.RangeFrom(2) + hostSliceRet.CopyFromDevice(&deviceSliceRangeFrom) + assert.Equal(t, hostSlice[2:], hostSliceRet) + + // RangeTo + deviceSliceRangeTo := deviceSlice.RangeTo(numPoints-3, true) + hostSliceRet.CopyFromDevice(&deviceSliceRangeTo) + assert.Equal(t, hostSlice[:6], hostSliceRet) + + // Range + hostSliceRange := HostSliceWithValue[internal.MockProjective](zeroProj, numPoints-4) + deviceSliceRange := deviceSlice.Range(2, numPoints-3, true) + hostSliceRange.CopyFromDevice(&deviceSliceRange) + assert.Equal(t, hostSlice[2:6], hostSliceRange) +} + +// func TestHostSlicePinning(t *testing.T) { +// data := []int{1, 2, 3, 4, 5, 7, 8, 9} +// dataHostSlice := HostSliceFromElements(data) +// err := dataHostSlice.Pin(cuda_runtime.CudaHostRegisterDefault) +// assert.Equal(t, cuda_runtime.CudaSuccess, err) +// err = dataHostSlice.Pin(cuda_runtime.CudaHostRegisterDefault) +// assert.Equal(t, cuda_runtime.CudaErrorHostMemoryAlreadyRegistered, err) + +// err = dataHostSlice.Unpin() +// assert.Equal(t, cuda_runtime.CudaSuccess, err) +// err = dataHostSlice.Unpin() +// assert.Equal(t, cuda_runtime.CudaErrorHostMemoryNotRegistered, err) + +// pinnedMem, err := dataHostSlice.AllocPinned(cuda_runtime.CudaHostAllocDefault) +// assert.Equal(t, cuda_runtime.CudaSuccess, err) +// assert.ElementsMatch(t, dataHostSlice, pinnedMem) + +// err = pinnedMem.FreePinned() +// assert.Equal(t, cuda_runtime.CudaSuccess, err) +// err = pinnedMem.FreePinned() +// assert.Equal(t, cuda_runtime.CudaErrorInvalidValue, err) +// } diff --git a/wrappers/golang_v3/core/utils.go b/wrappers/golang_v3/core/utils.go new file mode 100644 index 000000000..d98ec775f --- /dev/null +++ b/wrappers/golang_v3/core/utils.go @@ -0,0 +1,26 @@ +package core + +import ( + "encoding/binary" +) + +func ConvertUint32ArrToUint64Arr(arr32 []uint32) []uint64 { + arr64 := make([]uint64, len(arr32)/2) + for i := 0; i < len(arr32); i += 2 { + arr64[i/2] = (uint64(arr32[i]) << 32) | uint64(arr32[i+1]) + } + return arr64 +} + +func ConvertUint64ArrToUint32Arr(arr64 []uint64) []uint32 { + arr32 := make([]uint32, len(arr64)*2) + for i, v := range arr64 { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, v) + + arr32[i*2] = binary.LittleEndian.Uint32(b[0:4]) + arr32[i*2+1] = binary.LittleEndian.Uint32(b[4:8]) + } + + return arr32 +} diff --git a/wrappers/golang_v3/core/utils_test.go b/wrappers/golang_v3/core/utils_test.go new file mode 100644 index 000000000..5b5e9ef33 --- /dev/null +++ b/wrappers/golang_v3/core/utils_test.go @@ -0,0 +1,78 @@ +package core + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestConvertUint32ArrToUint64Arr(t *testing.T) { + testCases := []struct { + name string + input []uint32 + expected []uint64 + }{ + { + name: "Test with incremental array", + input: []uint32{1, 2, 3, 4, 5, 6, 7, 8}, + expected: []uint64{4294967298, 12884901892, 21474836486, 30064771080}, + }, + { + name: "Test with all zeros", + input: []uint32{0, 0, 0, 0, 0, 0, 0, 0}, + expected: []uint64{0, 0, 0, 0}, + }, + { + name: "Test with maximum uint32 values", + input: []uint32{4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295}, + expected: []uint64{18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615}, + }, + { + name: "Test with alternating min and max uint32 values", + input: []uint32{0, 4294967295, 0, 4294967295, 0, 4294967295, 0, 4294967295}, + expected: []uint64{4294967295, 4294967295, 4294967295, 4294967295}, + }, + { + name: "Test with alternating max and min uint32 values", + input: []uint32{4294967295, 0, 4294967295, 0, 4294967295, 0, 4294967295, 0}, + expected: []uint64{18446744069414584320, 18446744069414584320, 18446744069414584320, 18446744069414584320}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := ConvertUint32ArrToUint64Arr(tc.input) + assert.Equal(t, tc.expected, got, "Got %v, %v", got, tc.expected) + }) + } +} + +func TestConvertUint64ArrToUint32Arr(t *testing.T) { + testCases := []struct { + name string + input []uint64 + expected []uint32 + }{ + { + name: "test one", + input: []uint64{1, 2, 3, 4}, + expected: []uint32{1, 0, 2, 0, 3, 0, 4, 0}, + }, + { + name: "test two", + input: []uint64{100, 200, 300, 400}, + expected: []uint32{100, 0, 200, 0, 300, 0, 400, 0}, + }, + { + name: "test three", + input: []uint64{1000, 2000, 3000, 4000}, + expected: []uint32{1000, 0, 2000, 0, 3000, 0, 4000, 0}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := ConvertUint64ArrToUint32Arr(tc.input) + assert.Equal(t, tc.expected, got, "Got %v, %v", got, tc.expected) + }) + } +} diff --git a/wrappers/golang_v3/core/vec_ops.go b/wrappers/golang_v3/core/vec_ops.go new file mode 100644 index 000000000..8ac3afd6b --- /dev/null +++ b/wrappers/golang_v3/core/vec_ops.go @@ -0,0 +1,110 @@ +package core + +import ( + "fmt" + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +type VecOps int + +const ( + Sub VecOps = iota + Add + Mul +) + +type VecOpsConfig struct { + StreamHandle runtime.Stream + /* True if `a` is on device and false if it is not. Default value: false. */ + isAOnDevice bool + /* True if `b` is on device and false if it is not. Default value: false. */ + isBOnDevice bool + /* If true, output is preserved on device, otherwise on host. Default value: false. */ + isResultOnDevice bool + /* Whether to run the vector operations asynchronously. If set to `true`, the function will be + * non-blocking and you'll need to synchronize it explicitly by calling + * `SynchronizeStream`. If set to false, the function will block the current CPU thread. */ + IsAsync bool + Ext runtime.ConfigExtensionHandler +} + +/** + * A function that returns the default value of [VecOpsConfig](@ref VecOpsConfig). + * @return Default value of [VecOpsConfig](@ref VecOpsConfig). + */ +func DefaultVecOpsConfig() VecOpsConfig { + config := VecOpsConfig{ + nil, // StreamHandle + false, // isAOnDevice + false, // isBOnDevice + false, // isResultOnDevice + false, // IsAsync + nil, // Ext + } + + return config +} + +func VecOpCheck(a, b, out HostOrDeviceSlice, cfg *VecOpsConfig) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, int) { + aLen, bLen, outLen := a.Len(), b.Len(), out.Len() + if aLen != bLen { + errorString := fmt.Sprintf( + "a and b vector lengths %d; %d are not equal", + aLen, + bLen, + ) + panic(errorString) + } + if aLen != outLen { + errorString := fmt.Sprintf( + "a and out vector lengths %d; %d are not equal", + aLen, + outLen, + ) + panic(errorString) + } + + if a.IsOnDevice() { + a.(DeviceSlice).CheckDevice() + } + if b.IsOnDevice() { + b.(DeviceSlice).CheckDevice() + } + if out.IsOnDevice() { + out.(DeviceSlice).CheckDevice() + } + + cfg.isAOnDevice = a.IsOnDevice() + cfg.isBOnDevice = b.IsOnDevice() + cfg.isResultOnDevice = out.IsOnDevice() + + return a.AsUnsafePointer(), b.AsUnsafePointer(), out.AsUnsafePointer(), unsafe.Pointer(cfg), a.Len() +} + +func TransposeCheck(in, out HostOrDeviceSlice, onDevice bool) { + inLen, outLen := in.Len(), out.Len() + + if inLen != outLen { + errorString := fmt.Sprintf( + "in and out vector lengths %d; %d are not equal", + inLen, + outLen, + ) + panic(errorString) + } + if (onDevice != in.IsOnDevice()) || (onDevice != out.IsOnDevice()) { + errorString := fmt.Sprintf( + "onDevice is set to %t, but in.IsOnDevice():%t and out.IsOnDevice():%t", + onDevice, + in.IsOnDevice(), + out.IsOnDevice(), + ) + panic(errorString) + } + if onDevice { + in.(DeviceSlice).CheckDevice() + out.(DeviceSlice).CheckDevice() + } +} diff --git a/wrappers/golang_v3/core/vec_ops_test.go b/wrappers/golang_v3/core/vec_ops_test.go new file mode 100644 index 000000000..1abee4894 --- /dev/null +++ b/wrappers/golang_v3/core/vec_ops_test.go @@ -0,0 +1,21 @@ +package core + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestVecOpsDefaultConfig(t *testing.T) { + actual := DefaultVecOpsConfig() + expected := VecOpsConfig{ + actual.StreamHandle, // Ctx + true, // isAOnDevice + true, // isBOnDevice + true, // isResultOnDevice + true, // IsAsync + actual.Ext, // Ext + } + + assert.Equal(t, expected, actual) +} diff --git a/wrappers/golang_v3/curves/bls12377/base_field.go b/wrappers/golang_v3/curves/bls12377/base_field.go new file mode 100644 index 000000000..247482119 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/base_field.go @@ -0,0 +1,84 @@ +package bls12377 + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int = 12 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromUint32(v uint32) BaseField { + f.limbs[0] = v + return *f +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bls12377/curve.go b/wrappers/golang_v3/curves/bls12377/curve.go new file mode 100644 index 000000000..e21dd5808 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/curve.go @@ -0,0 +1,177 @@ +package bls12377 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.bls12_377_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bls12_377_to_affine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_377_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_377_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go b/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go new file mode 100644 index 000000000..0fe75abdf --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go @@ -0,0 +1,24 @@ +package ecntt + +// #cgo CFLAGS: -I./include/ +// #include "ecntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) + + cPoints := (*C.projective_t)(pointsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.projective_t)(resultsPointer) + + __ret := C.bls12_377_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bls12377/ecntt/include/ecntt.h b/wrappers/golang_v3/curves/bls12377/ecntt/include/ecntt.h new file mode 100644 index 000000000..2561e2600 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/ecntt/include/ecntt.h @@ -0,0 +1,19 @@ +#include + +#ifndef _BLS12_377_ECNTT_H +#define _BLS12_377_ECNTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NTTConfig NTTConfig; +typedef struct projective_t projective_t; + +cudaError_t bls12_377_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bls12377/g2/curve.go b/wrappers/golang_v3/curves/bls12377/g2/curve.go new file mode 100644 index 000000000..50ac2a110 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/g2/curve.go @@ -0,0 +1,177 @@ +package g2 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bls12_377_g2_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bls12_377_g2_to_affine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_377_g2_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_377_g2_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bls12377/g2/g2base_field.go b/wrappers/golang_v3/curves/bls12377/g2/g2base_field.go new file mode 100644 index 000000000..c4073af97 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/g2/g2base_field.go @@ -0,0 +1,84 @@ +package g2 + +import ( + "encoding/binary" + "fmt" +) + +const ( + G2BASE_LIMBS int = 24 +) + +type G2BaseField struct { + limbs [G2BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromUint32(v uint32) G2BaseField { + f.limbs[0] = v + return *f +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bls12377/g2/include/curve.h b/wrappers/golang_v3/curves/bls12377/g2/include/curve.h new file mode 100644 index 000000000..b136de9a8 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/g2/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _BLS12_377_G2CURVE_H +#define _BLS12_377_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct g2_projective_t g2_projective_t; +typedef struct g2_affine_t g2_affine_t; +typedef struct DeviceContext DeviceContext; + +bool bls12_377_g2_eq(g2_projective_t* point1, g2_projective_t* point2); +void bls12_377_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bls12_377_g2_generate_projective_points(g2_projective_t* points, int size); +void bls12_377_g2_generate_affine_points(g2_affine_t* points, int size); +cudaError_t bls12_377_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bls12_377_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12377/g2/include/msm.h b/wrappers/golang_v3/curves/bls12377/g2/include/msm.h new file mode 100644 index 000000000..0c1ebed7c --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/g2/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BLS12_377_G2MSM_H +#define _BLS12_377_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct g2_projective_t g2_projective_t; +typedef struct g2_affine_t g2_affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bls12_377_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); +cudaError_t bls12_377_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out); +cudaError_t bls12_377_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12377/g2/include/scalar_field.h b/wrappers/golang_v3/curves/bls12377/g2/include/scalar_field.h new file mode 100644 index 000000000..09b1bfb7f --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/g2/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BLS12_377_FIELD_H +#define _BLS12_377_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void bls12_377_generate_scalars(scalar_t* scalars, int size); +cudaError_t bls12_377_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12377/g2/msm.go b/wrappers/golang_v3/curves/bls12377/g2/msm.go new file mode 100644 index 000000000..bf47b86da --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/g2/msm.go @@ -0,0 +1,63 @@ +package g2 + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.g2_affine_t)(pointsPointer) + cResults := (*C.g2_projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.bls12_377_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: G2PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// G2PrecomputePoints should be used instead. +func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := G2GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.g2_affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bls12_377_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.g2_affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bls12_377_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bls12377/include/curve.h b/wrappers/golang_v3/curves/bls12377/include/curve.h new file mode 100644 index 000000000..87a0229b6 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _BLS12_377_CURVE_H +#define _BLS12_377_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct DeviceContext DeviceContext; + +bool bls12_377_eq(projective_t* point1, projective_t* point2); +void bls12_377_to_affine(projective_t* point, affine_t* point_out); +void bls12_377_generate_projective_points(projective_t* points, int size); +void bls12_377_generate_affine_points(affine_t* points, int size); +cudaError_t bls12_377_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bls12_377_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12377/include/scalar_field.h b/wrappers/golang_v3/curves/bls12377/include/scalar_field.h new file mode 100644 index 000000000..09b1bfb7f --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BLS12_377_FIELD_H +#define _BLS12_377_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void bls12_377_generate_scalars(scalar_t* scalars, int size); +cudaError_t bls12_377_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12377/main.go b/wrappers/golang_v3/curves/bls12377/main.go new file mode 100644 index 000000000..fa60eb5f2 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/main.go @@ -0,0 +1,4 @@ +package bls12377 + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bls12_377 -lingo_field_bls12_377 -lstdc++ -lm +import "C" diff --git a/wrappers/golang_v3/curves/bls12377/msm/include/msm.h b/wrappers/golang_v3/curves/bls12377/msm/include/msm.h new file mode 100644 index 000000000..b6ba320fb --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/msm/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BLS12_377_MSM_H +#define _BLS12_377_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bls12_377_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); +cudaError_t bls12_377_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); +cudaError_t bls12_377_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12377/msm/msm.go b/wrappers/golang_v3/curves/bls12377/msm/msm.go new file mode 100644 index 000000000..34861acc2 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/msm/msm.go @@ -0,0 +1,63 @@ +package msm + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.affine_t)(pointsPointer) + cResults := (*C.projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.bls12_377_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// PrecomputePoints should be used instead. +func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.bls12_377_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.bls12_377_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bls12377/ntt/include/ntt.h b/wrappers/golang_v3/curves/bls12377/ntt/include/ntt.h new file mode 100644 index 000000000..d933f5ba0 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/ntt/include/ntt.h @@ -0,0 +1,23 @@ +#include +#include + +#ifndef _BLS12_377_NTT_H +#define _BLS12_377_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct NTTConfig NTTConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bls12_377_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t bls12_377_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); +cudaError_t bls12_377_release_domain(DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bls12377/ntt/ntt.go b/wrappers/golang_v3/curves/bls12377/ntt/ntt.go new file mode 100644 index 000000000..4403abcca --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/ntt/ntt.go @@ -0,0 +1,56 @@ +package ntt + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" +) + +import ( + "unsafe" +) + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.bls12_377_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func GetDefaultNttConfig() core.NTTConfig[[bls12_377.SCALAR_LIMBS]uint32] { + cosetGenField := bls12_377.ScalarField{} + cosetGenField.One() + var cosetGen [bls12_377.SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func InitDomain(primitiveRoot bls12_377.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.bls12_377_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + __ret := C.bls12_377_release_domain(cCtx) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bls12377/polynomial/include/polynomial.h b/wrappers/golang_v3/curves/bls12377/polynomial/include/polynomial.h new file mode 100644 index 000000000..6aa6e3bfb --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/polynomial/include/polynomial.h @@ -0,0 +1,51 @@ +#include +#include + +#ifndef _BLS12_377_POLY_H +#define _BLS12_377_POLY_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PolynomialInst PolynomialInst; +typedef struct IntegrityPointer IntegrityPointer; + +bool bls12_377_polynomial_init_cuda_backend(); +PolynomialInst* bls12_377_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); +PolynomialInst* bls12_377_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); +PolynomialInst* bls12_377_polynomial_clone(const PolynomialInst* p); +void bls12_377_polynomial_print(PolynomialInst* p); +void bls12_377_polynomial_delete(PolynomialInst* instance); +PolynomialInst* bls12_377_polynomial_add(const PolynomialInst* a, const PolynomialInst* b); +void bls12_377_polynomial_add_inplace(PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_377_polynomial_subtract(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_377_polynomial_multiply(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_377_polynomial_multiply_by_scalar(const PolynomialInst* a, const scalar_t* scalar); +void bls12_377_polynomial_division(const PolynomialInst* a, const PolynomialInst* b, PolynomialInst** q /*OUT*/, PolynomialInst** r /*OUT*/); +PolynomialInst* bls12_377_polynomial_quotient(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_377_polynomial_remainder(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_377_polynomial_divide_by_vanishing(const PolynomialInst* p, size_t vanishing_poly_degree); +void bls12_377_polynomial_add_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void bls12_377_polynomial_sub_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void bls12_377_polynomial_evaluate_on_domain(const PolynomialInst* p, scalar_t* domain, size_t domain_size, scalar_t* evals /*OUT*/); +size_t bls12_377_polynomial_degree(PolynomialInst* p); +size_t bls12_377_polynomial_copy_coeffs_range(PolynomialInst* p, scalar_t* memory, size_t start_idx, size_t end_idx); +PolynomialInst* bls12_377_polynomial_even(PolynomialInst* p); +PolynomialInst* bls12_377_polynomial_odd(PolynomialInst* p); + +// scalar_t* bls12_377_polynomial_get_coeffs_raw_ptr(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// PolynomialInst* bls12_377_polynomial_slice(PolynomialInst* p, size_t offset, size_t stride, size_t size); +// IntegrityPointer* bls12_377_polynomial_get_coeff_view(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// IntegrityPointer* bls12_377_polynomial_get_rou_evaluations_view(PolynomialInst* p, size_t nof_evals, bool is_reversed, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// const scalar_t* bls12_377_polynomial_intergrity_ptr_get(IntegrityPointer* p); +// bool bls12_377_polynomial_intergrity_ptr_is_valid(IntegrityPointer* p); +// void bls12_377_polynomial_intergrity_ptr_destroy(IntegrityPointer* p); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/wrappers/golang_v3/curves/bls12377/polynomial/polynomial.go b/wrappers/golang_v3/curves/bls12377/polynomial/polynomial.go new file mode 100644 index 000000000..2f3998a8e --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/polynomial/polynomial.go @@ -0,0 +1,176 @@ +package polynomial + +// #cgo CFLAGS: -I./include/ +// #include "polynomial.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" +) + +type PolynomialHandle = C.struct_PolynomialInst + +type DensePolynomial struct { + handle *PolynomialHandle +} + +func InitPolyBackend() bool { + return (bool)(C.bls12_377_polynomial_init_cuda_backend()) +} + +func (up *DensePolynomial) Print() { + C.bls12_377_polynomial_print(up.handle) +} + +func (up *DensePolynomial) CreateFromCoeffecitients(coeffs core.HostOrDeviceSlice) DensePolynomial { + if coeffs.IsOnDevice() { + coeffs.(core.DeviceSlice).CheckDevice() + } + coeffsPointer := (*C.scalar_t)(coeffs.AsUnsafePointer()) + cSize := (C.size_t)(coeffs.Len()) + up.handle = C.bls12_377_polynomial_create_from_coefficients(coeffsPointer, cSize) + return *up +} + +func (up *DensePolynomial) CreateFromROUEvaluations(evals core.HostOrDeviceSlice) DensePolynomial { + evalsPointer := (*C.scalar_t)(evals.AsUnsafePointer()) + cSize := (C.size_t)(evals.Len()) + up.handle = C.bls12_377_polynomial_create_from_coefficients(evalsPointer, cSize) + return *up +} + +func (up *DensePolynomial) Clone() DensePolynomial { + return DensePolynomial{ + handle: C.bls12_377_polynomial_clone(up.handle), + } +} + +// TODO @jeremyfelder: Maybe this should be in a SetFinalizer that is set on Create functions? +func (up *DensePolynomial) Delete() { + C.bls12_377_polynomial_delete(up.handle) +} + +func (up *DensePolynomial) Add(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_377_polynomial_add(up.handle, b.handle), + } +} + +func (up *DensePolynomial) AddInplace(b *DensePolynomial) { + C.bls12_377_polynomial_add_inplace(up.handle, b.handle) +} + +func (up *DensePolynomial) Subtract(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_377_polynomial_subtract(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Multiply(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_377_polynomial_multiply(up.handle, b.handle), + } +} + +func (up *DensePolynomial) MultiplyByScalar(scalar bls12_377.ScalarField) DensePolynomial { + cScalar := (*C.scalar_t)(unsafe.Pointer(scalar.AsPointer())) + return DensePolynomial{ + handle: C.bls12_377_polynomial_multiply_by_scalar(up.handle, cScalar), + } +} + +func (up *DensePolynomial) Divide(b *DensePolynomial) (DensePolynomial, DensePolynomial) { + var q, r *PolynomialHandle + C.bls12_377_polynomial_division(up.handle, b.handle, &q, &r) + return DensePolynomial{ + handle: q, + }, DensePolynomial{ + handle: r, + } +} + +func (up *DensePolynomial) Quotient(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_377_polynomial_quotient(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Remainder(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_377_polynomial_remainder(up.handle, b.handle), + } +} + +func (up *DensePolynomial) DivideByVanishing(vanishing_degree uint64) DensePolynomial { + cVanishingDegree := (C.ulong)(vanishing_degree) + return DensePolynomial{ + handle: C.bls12_377_polynomial_divide_by_vanishing(up.handle, cVanishingDegree), + } +} + +func (up *DensePolynomial) AddMonomial(monomialCoeff bls12_377.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]bls12_377.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.bls12_377_polynomial_add_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) SubMonomial(monomialCoeff bls12_377.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]bls12_377.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.bls12_377_polynomial_sub_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) Eval(x bls12_377.ScalarField) bls12_377.ScalarField { + domains := make(core.HostSlice[bls12_377.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[bls12_377.ScalarField], 1) + up.EvalOnDomain(domains, evals) + return evals[0] +} + +func (up *DensePolynomial) EvalOnDomain(domain, evals core.HostOrDeviceSlice) core.HostOrDeviceSlice { + cDomain := (*C.scalar_t)(domain.AsUnsafePointer()) + cDomainSize := (C.size_t)(domain.Len()) + cEvals := (*C.scalar_t)(evals.AsUnsafePointer()) + C.bls12_377_polynomial_evaluate_on_domain(up.handle, cDomain, cDomainSize, cEvals) + return evals +} + +func (up *DensePolynomial) Degree() int { + return int(C.bls12_377_polynomial_degree(up.handle)) +} + +func (up *DensePolynomial) CopyCoeffsRange(start, end int, out core.HostOrDeviceSlice) (int, core.HostOrDeviceSlice) { + cStart := (C.size_t)(start) + cEnd := (C.size_t)(end) + cScalarOut := (*C.scalar_t)(out.AsUnsafePointer()) + __cNumCoeffsRead := C.bls12_377_polynomial_copy_coeffs_range(up.handle, cScalarOut, cStart, cEnd) + return int(__cNumCoeffsRead), out +} + +func (up *DensePolynomial) GetCoeff(idx int) bls12_377.ScalarField { + out := make(core.HostSlice[bls12_377.ScalarField], 1) + up.CopyCoeffsRange(idx, idx, out) + return out[0] +} + +func (up *DensePolynomial) Even() DensePolynomial { + evenPoly := C.bls12_377_polynomial_even(up.handle) + return DensePolynomial{ + handle: evenPoly, + } +} + +func (up *DensePolynomial) Odd() DensePolynomial { + oddPoly := C.bls12_377_polynomial_odd(up.handle) + return DensePolynomial{ + handle: oddPoly, + } +} diff --git a/wrappers/golang_v3/curves/bls12377/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/bls12377/poseidon/include/poseidon.h new file mode 100644 index 000000000..625f4f189 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/poseidon/include/poseidon.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BLS12_377_POSEIDON_H +#define _BLS12_377_POSEIDON_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PoseidonConfig PoseidonConfig; +typedef struct DeviceContext DeviceContext; +typedef struct PoseidonConstants PoseidonConstants; + + +cudaError_t bls12_377_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); +cudaError_t bls12_377_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); +cudaError_t bls12_377_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go b/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go new file mode 100644 index 000000000..5b452827b --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go @@ -0,0 +1,57 @@ +package poseidon + +// #cgo CFLAGS: -I./include/ +// #include "poseidon.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func GetDefaultPoseidonConfig() core.PoseidonConfig { + return core.GetDefaultPoseidonConfig() +} + +func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { + scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) + + cScalars := (*C.scalar_t)(scalarsPointer) + cResults := (*C.scalar_t)(resultsPointer) + cNumberOfStates := (C.int)(numberOfStates) + cArity := (C.int)(constants.Arity) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + cCfg := (*C.PoseidonConfig)(cfgPointer) + + __ret := C.bls12_377_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) + + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cFullRoundsHalfs := (C.int)(fullRoundsHalfs) + cPartialRounds := (C.int)(partialRounds) + cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) + + __ret := C.bls12_377_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + + __ret := C.bls12_377_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bls12377/scalar_field.go b/wrappers/golang_v3/curves/bls12377/scalar_field.go new file mode 100644 index 000000000..716207644 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/scalar_field.go @@ -0,0 +1,121 @@ +package bls12377 + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int = 8 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromUint32(v uint32) ScalarField { + f.limbs[0] = v + return *f +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalarSlice := make(core.HostSlice[ScalarField], size) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.bls12_377_generate_scalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/base_field_test.go b/wrappers/golang_v3/curves/bls12377/tests/base_field_test.go new file mode 100644 index 000000000..cb5106f26 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + BASE_LIMBS = bls12_377.BASE_LIMBS +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := bls12_377.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := bls12_377.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField bls12_377.BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField bls12_377.BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField bls12_377.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField bls12_377.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField bls12_377.BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField bls12_377.BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/curve_test.go b/wrappers/golang_v3/curves/bls12377/tests/curve_test.go new file mode 100644 index 000000000..be176bbe0 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = bls12_377.BaseField{} + + var affineZero bls12_377.Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var affine bls12_377.Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var affine bls12_377.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bls12_377.BaseField + fieldOne.One() + + var expected bls12_377.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bls12_377.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero bls12_377.Projective + projectiveZero.Zero() + var fieldZero = bls12_377.BaseField{} + var fieldOne bls12_377.BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var projective bls12_377.Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var projective bls12_377.Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bls12_377.BaseField + fieldOne.One() + + var expected bls12_377.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bls12_377.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint bls12_377.Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go b/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go new file mode 100644 index 000000000..696f6d43b --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go @@ -0,0 +1,30 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt" + "github.com/stretchr/testify/assert" +) + +func TestECNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + points := bls12_377.GenerateProjectivePoints(1 << largestTestSize) + + for _, size := range []int{4, 5, 6, 7, 8} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + pointsCopy := core.HostSliceFromElements[bls12_377.Projective](points[:testSize]) + cfg.Ordering = v + cfg.NttAlgorithm = core.Radix2 + + output := make(core.HostSlice[bls12_377.Projective], testSize) + e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + } + } +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go new file mode 100644 index 000000000..64fd2fd85 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = g2.G2BaseField{} + + var affineZero g2.G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var affine g2.G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero g2.G2Projective + projectiveZero.Zero() + var fieldZero = g2.G2BaseField{} + var fieldOne g2.G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint g2.G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_g2base_field_test.go new file mode 100644 index 000000000..dcaa8bcac --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_g2base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + G2BASE_LIMBS = bls12_377.G2BASE_LIMBS +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := bls12_377.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := bls12_377.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField bls12_377.G2BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField bls12_377.G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField bls12_377.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField bls12_377.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField bls12_377.G2BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField bls12_377.G2BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go new file mode 100644 index 000000000..86bd50f8a --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go @@ -0,0 +1,371 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bls12-377" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleBls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2" +) + +func projectiveToGnarkAffineG2(p g2.G2Projective) bls12377.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := bls12377.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := bls12377.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := bls12377.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared bls12377.E2 + zSquared.Mul(&z, &z) + + var X bls12377.E2 + X.Mul(&x, &z) + + var Y bls12377.E2 + Y.Mul(&y, &zSquared) + + g2Jac := bls12377.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine bls12377.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} + +func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBls12_377.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bls12377.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12377.G2Affine], out g2.G2Projective) bool { + var msmRes bls12377.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bls12377.G2Jac + proj := projectiveToGnarkAffineG2(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bls12377.G2Affine { + points := make([]bls12377.G2Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian()) + xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes]) + xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:]) + xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes) + xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes) + + yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian()) + yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes]) + yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:]) + yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes) + yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes) + + points[index] = bls12377.G2Affine{ + X: bls12377.E2{ + A0: xA0Elem, + A1: xA1Elem, + }, + Y: bls12377.E2{ + A0: yA0Elem, + A1: yA1Elem, + }, + } + } + + return points +} + +func TestMSMG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBls12_377.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + + } +} + +func TestMSMG2PinnedHostMemory(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleBls12_377.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[g2.G2Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + + if pinnableAndLockable { + e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +func TestMSMG2GnarkCryptoTypes(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := g2.G2GenerateAffinePoints(size) + pointsGnark := convertIcicleG2AffineToG2Affine(points) + pointsHost := (core.HostSlice[bls12377.G2Affine])(pointsGnark) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_377.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestPrecomputePointsG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_377.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBls12_377.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := g2.G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} + +func TestMSMG2MultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBls12_377.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/main_test.go b/wrappers/golang_v3/curves/bls12377/tests/main_test.go new file mode 100644 index 000000000..928e6c3fa --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/main_test.go @@ -0,0 +1,48 @@ +package tests + +import ( + "os" + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt" + poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/polynomial" + + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft" +) + +const ( + largestTestSize = 20 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := bls12_377.ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + return e +} + +func TestMain(m *testing.M) { + poly.InitPolyBackend() + + // setup domain + cfg := ntt.GetDefaultNttConfig() + e := initDomain(largestTestSize, cfg) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("initDomain failed") + } + + // execute tests + os.Exit(m.Run()) + + // release domain + e = ntt.ReleaseDomain(cfg.Ctx) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("ReleaseDomain failed") + } +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go new file mode 100644 index 000000000..1c74cc1bc --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go @@ -0,0 +1,331 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bls12-377" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleBls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/msm" +) + +func projectiveToGnarkAffine(p icicleBls12_377.Projective) bls12377.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bls12377.G1Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBls12_377.ScalarField], points core.HostSlice[icicleBls12_377.Affine], out icicleBls12_377.Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bls12377.G1Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12377.G1Affine], out icicleBls12_377.Projective) bool { + var msmRes bls12377.G1Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bls12377.G1Jac + proj := projectiveToGnarkAffine(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func convertIcicleAffineToG1Affine(iciclePoints []icicleBls12_377.Affine) []bls12377.G1Affine { + points := make([]bls12377.G1Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes]byte)(iciclePoint.X.ToBytesLittleEndian()) + fpXElem, _ := fp.LittleEndian.Element(&xBytes) + + yBytes := ([fp.Bytes]byte)(iciclePoint.Y.ToBytesLittleEndian()) + fpYElem, _ := fp.LittleEndian.Element(&yBytes) + points[index] = bls12377.G1Affine{ + X: fpXElem, + Y: fpYElem, + } + } + + return points +} + +func TestMSM(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBls12_377.GenerateScalars(size) + points := icicleBls12_377.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleBls12_377.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + + } +} + +func TestMSMPinnedHostMemory(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleBls12_377.GenerateScalars(size) + points := icicleBls12_377.GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[icicleBls12_377.Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p icicleBls12_377.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + + if pinnableAndLockable { + e = msm.Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +func TestMSMGnarkCryptoTypes(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := icicleBls12_377.GenerateAffinePoints(size) + pointsGnark := convertIcicleAffineToG1Affine(points) + pointsHost := (core.HostSlice[bls12377.G1Affine])(pointsGnark) + + var p icicleBls12_377.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = msm.Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} + +func TestMSMBatch(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_377.GenerateScalars(totalSize) + points := icicleBls12_377.GenerateAffinePoints(totalSize) + + var p icicleBls12_377.Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_377.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestPrecomputePoints(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_377.GenerateScalars(totalSize) + points := icicleBls12_377.GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p icicleBls12_377.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_377.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBls12_377.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := icicleBls12_377.GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p icicleBls12_377.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} + +func TestMSMMultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBls12_377.GenerateScalars(size) + points := icicleBls12_377.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleBls12_377.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go b/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go new file mode 100644 index 000000000..8014e56d8 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go @@ -0,0 +1,263 @@ +package tests + +import ( + "reflect" + "testing" + + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" +) + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bls12_377.ScalarField], output core.HostSlice[bls12_377.ScalarField], order core.Ordering, direction core.NTTDir) bool { + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) +} + +func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} +func TestNTTGetDefaultConfig(t *testing.T) { + actual := ntt.GetDefaultNttConfig() + expected := test_helpers.GenerateLimbOne(int(bls12_377.SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := bls12_377.ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := bls12_377.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[bls12_377.ScalarField], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} +func TestNttFrElement(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := make([]fr.Element, 4) + var x fr.Element + for i := 0; i < 4; i++ { + x.SetRandom() + scalars[i] = x + } + + for _, size := range []int{4} { + for _, v := range [1]core.Ordering{core.KNN} { + testSize := size + + scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[fr.Element], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := bls12_377.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[bls12_377.ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + largestTestSize := 12 + largestBatchSize := 100 + scalars := bls12_377.GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{2, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[bls12_377.ScalarField], totalSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +func TestReleaseDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + e := ntt.ReleaseDomain(cfg.Ctx) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := ntt.GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang_v3/curves/bls12377/tests/polynomial_test.go b/wrappers/golang_v3/curves/bls12377/tests/polynomial_test.go new file mode 100644 index 000000000..de9d2c1b9 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/polynomial_test.go @@ -0,0 +1,229 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/vecOps" + "github.com/stretchr/testify/assert" +) + +var one, two, three, four, five bls12_377.ScalarField + +func init() { + one.One() + two.FromUint32(2) + three.FromUint32(3) + four.FromUint32(4) + five.FromUint32(5) +} + +func rand() bls12_377.ScalarField { + return bls12_377.GenerateScalars(1)[0] +} + +func randomPoly(size int) (f polynomial.DensePolynomial) { + f.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_377.GenerateScalars(size))) + return f +} + +func vecOp(a, b bls12_377.ScalarField, op core.VecOps) bls12_377.ScalarField { + ahost := core.HostSliceWithValue(a, 1) + bhost := core.HostSliceWithValue(b, 1) + out := make(core.HostSlice[bls12_377.ScalarField], 1) + + cfg := core.DefaultVecOpsConfig() + vecOps.VecOp(ahost, bhost, out, cfg, op) + return out[0] +} + +func TestPolyCreateFromCoefficients(t *testing.T) { + scalars := bls12_377.GenerateScalars(33) + var uniPoly polynomial.DensePolynomial + + poly := uniPoly.CreateFromCoeffecitients(scalars) + poly.Print() +} + +func TestPolyEval(t *testing.T) { + // testing correct evaluation of f(8) for f(x)=4x^2+2x+5 + coeffs := core.HostSliceFromElements([]bls12_377.ScalarField{five, two, four}) + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(coeffs) + + var x bls12_377.ScalarField + x.FromUint32(8) + domains := make(core.HostSlice[bls12_377.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[bls12_377.ScalarField], 1) + fEvaled := f.EvalOnDomain(domains, evals) + var expected bls12_377.ScalarField + assert.Equal(t, expected.FromUint32(277), fEvaled.(core.HostSlice[bls12_377.ScalarField])[0]) +} + +func TestPolyClone(t *testing.T) { + f := randomPoly(8) + x := rand() + fx := f.Eval(x) + + g := f.Clone() + fg := f.Add(&g) + + gx := g.Eval(x) + fgx := fg.Eval(x) + + assert.Equal(t, fx, gx) + assert.Equal(t, vecOp(fx, gx, core.Add), fgx) +} + +func TestPolyAddSubMul(t *testing.T) { + testSize := 1 << 10 + f := randomPoly(testSize) + g := randomPoly(testSize) + x := rand() + + fx := f.Eval(x) + gx := g.Eval(x) + + polyAdd := f.Add(&g) + fxAddgx := vecOp(fx, gx, core.Add) + assert.Equal(t, polyAdd.Eval(x), fxAddgx) + + polySub := f.Subtract(&g) + fxSubgx := vecOp(fx, gx, core.Sub) + assert.Equal(t, polySub.Eval(x), fxSubgx) + + polyMul := f.Multiply(&g) + fxMulgx := vecOp(fx, gx, core.Mul) + assert.Equal(t, polyMul.Eval(x), fxMulgx) + + s1 := rand() + polMulS1 := f.MultiplyByScalar(s1) + assert.Equal(t, polMulS1.Eval(x), vecOp(fx, s1, core.Mul)) + + s2 := rand() + polMulS2 := f.MultiplyByScalar(s2) + assert.Equal(t, polMulS2.Eval(x), vecOp(fx, s2, core.Mul)) +} + +func TestPolyMonomials(t *testing.T) { + var zero bls12_377.ScalarField + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements([]bls12_377.ScalarField{one, zero, two})) + x := rand() + + fx := f.Eval(x) + f.AddMonomial(three, 1) + fxAdded := f.Eval(x) + assert.Equal(t, fxAdded, vecOp(fx, vecOp(three, x, core.Mul), core.Add)) + + f.SubMonomial(one, 0) + fxSub := f.Eval(x) + assert.Equal(t, fxSub, vecOp(fxAdded, one, core.Sub)) +} + +func TestPolyReadCoeffs(t *testing.T) { + var f polynomial.DensePolynomial + coeffs := core.HostSliceFromElements([]bls12_377.ScalarField{one, two, three, four}) + f.CreateFromCoeffecitients(coeffs) + coeffsCopied := make(core.HostSlice[bls12_377.ScalarField], coeffs.Len()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsCopied) + assert.ElementsMatch(t, coeffs, coeffsCopied) + + var coeffsDevice core.DeviceSlice + coeffsDevice.Malloc(coeffs.Len()*one.Size(), one.Size()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsDevice) + coeffsHost := make(core.HostSlice[bls12_377.ScalarField], coeffs.Len()) + coeffsHost.CopyFromDevice(&coeffsDevice) + + assert.ElementsMatch(t, coeffs, coeffsHost) +} + +func TestPolyOddEvenSlicing(t *testing.T) { + size := 1<<10 - 3 + f := randomPoly(size) + + even := f.Even() + odd := f.Odd() + assert.Equal(t, f.Degree(), even.Degree()+odd.Degree()+1) + + x := rand() + var evenExpected, oddExpected bls12_377.ScalarField + for i := size; i >= 0; i-- { + if i%2 == 0 { + mul := vecOp(evenExpected, x, core.Mul) + evenExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } else { + mul := vecOp(oddExpected, x, core.Mul) + oddExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } + } + + evenEvaled := even.Eval(x) + assert.Equal(t, evenExpected, evenEvaled) + + oddEvaled := odd.Eval(x) + assert.Equal(t, oddExpected, oddEvaled) +} + +func TestPolynomialDivision(t *testing.T) { + // divide f(x)/g(x), compute q(x), r(x) and check f(x)=q(x)*g(x)+r(x) + var f, g polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_377.GenerateScalars(1 << 4))) + g.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_377.GenerateScalars(1 << 2))) + + q, r := f.Divide(&g) + + qMulG := q.Multiply(&g) + fRecon := qMulG.Add(&r) + + x := bls12_377.GenerateScalars(1)[0] + fEval := f.Eval(x) + fReconEval := fRecon.Eval(x) + assert.Equal(t, fEval, fReconEval) +} + +func TestDivideByVanishing(t *testing.T) { + // poly of x^4-1 vanishes ad 4th rou + var zero bls12_377.ScalarField + minus_one := vecOp(zero, one, core.Sub) + coeffs := core.HostSliceFromElements([]bls12_377.ScalarField{minus_one, zero, zero, zero, one}) // x^4-1 + var v polynomial.DensePolynomial + v.CreateFromCoeffecitients(coeffs) + + f := randomPoly(1 << 3) + + fv := f.Multiply(&v) + fDegree := f.Degree() + fvDegree := fv.Degree() + assert.Equal(t, fDegree+4, fvDegree) + + fReconstructed := fv.DivideByVanishing(4) + assert.Equal(t, fDegree, fReconstructed.Degree()) + + x := rand() + assert.Equal(t, f.Eval(x), fReconstructed.Eval(x)) +} + +// func TestPolySlice(t *testing.T) { +// size := 4 +// coeffs := bls12_377.GenerateScalars(size) +// var f DensePolynomial +// f.CreateFromCoeffecitients(coeffs) +// fSlice := f.AsSlice() +// assert.True(t, fSlice.IsOnDevice()) +// assert.Equal(t, size, fSlice.Len()) + +// hostSlice := make(core.HostSlice[bls12_377.ScalarField], size) +// hostSlice.CopyFromDevice(fSlice) +// assert.Equal(t, coeffs, hostSlice) + +// cfg := ntt.GetDefaultNttConfig() +// res := make(core.HostSlice[bls12_377.ScalarField], size) +// ntt.Ntt(fSlice, core.KForward, cfg, res) + +// assert.Equal(t, f.Eval(one), res[0]) +// } diff --git a/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go b/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go new file mode 100644 index 000000000..b768fa291 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go @@ -0,0 +1,42 @@ +package tests + +import ( + "testing" + + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/poseidon" +) + +func TestPoseidon(t *testing.T) { + + arity := 2 + numberOfStates := 1 + + cfg := poseidon.GetDefaultPoseidonConfig() + cfg.IsAsync = true + stream, _ := cr.CreateStream() + cfg.Ctx.Stream = &stream + + var constants core.PoseidonConstants[bls12_377.ScalarField] + + poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants + + scalars := bls12_377.GenerateScalars(numberOfStates * arity) + scalars[0] = scalars[0].Zero() + scalars[1] = scalars[0].Zero() + + scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function + + output := make(core.HostSlice[bls12_377.ScalarField], numberOfStates) + output.CopyFromDeviceAsync(&deviceOutput, stream) + +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/scalar_field_test.go b/wrappers/golang_v3/curves/bls12377/tests/scalar_field_test.go new file mode 100644 index 000000000..d5063e90e --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/scalar_field_test.go @@ -0,0 +1,120 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + SCALAR_LIMBS = bls12_377.SCALAR_LIMBS +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := bls12_377.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := bls12_377.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField bls12_377.ScalarField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField bls12_377.ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField bls12_377.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField bls12_377.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField bls12_377.ScalarField + bytes, expected := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField bls12_377.ScalarField + expected, limbs := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestBls12_377GenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := bls12_377.GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := bls12_377.ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestBls12_377MongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := bls12_377.GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + bls12_377.ToMontgomery(&deviceScalars) + + scalarsMontHost := bls12_377.GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + bls12_377.FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang_v3/curves/bls12377/tests/vec_ops_test.go b/wrappers/golang_v3/curves/bls12377/tests/vec_ops_test.go new file mode 100644 index 000000000..c9e67e25f --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/tests/vec_ops_test.go @@ -0,0 +1,69 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/vecOps" + "github.com/stretchr/testify/assert" +) + +func TestBls12_377VecOps(t *testing.T) { + testSize := 1 << 14 + + a := bls12_377.GenerateScalars(testSize) + b := bls12_377.GenerateScalars(testSize) + var scalar bls12_377.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[bls12_377.ScalarField], testSize) + out2 := make(core.HostSlice[bls12_377.ScalarField], testSize) + out3 := make(core.HostSlice[bls12_377.ScalarField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.VecOp(a, b, out, cfg, core.Add) + vecOps.VecOp(out, b, out2, cfg, core.Sub) + + assert.Equal(t, a, out2) + + vecOps.VecOp(a, ones, out3, cfg, core.Mul) + + assert.Equal(t, a, out3) +} + +func TestBls12_377Transpose(t *testing.T) { + rowSize := 1 << 6 + columnSize := 1 << 8 + onDevice := false + isAsync := false + + matrix := bls12_377.GenerateScalars(rowSize * columnSize) + + out := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize) + out2 := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize) + + ctx, _ := cr.GetDefaultDeviceContext() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + + assert.Equal(t, matrix, out2) + + var dMatrix, dOut, dOut2 core.DeviceSlice + onDevice = true + + matrix.CopyToDevice(&dMatrix, true) + dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + output := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize) + output.CopyFromDevice(&dOut2) + + assert.Equal(t, matrix, output) +} diff --git a/wrappers/golang_v3/curves/bls12377/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/bls12377/vecOps/include/vec_ops.h new file mode 100644 index 000000000..54a4968e3 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/vecOps/include/vec_ops.h @@ -0,0 +1,53 @@ +#include +#include + +#ifndef _BLS12_377_VEC_OPS_H +#define _BLS12_377_VEC_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bls12_377_mul_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bls12_377_add_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bls12_377_sub_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bls12_377_transpose_matrix_cuda( + scalar_t* mat_in, + int row_size, + int column_size, + scalar_t* mat_out, + DeviceContext* ctx, + bool on_device, + bool is_async +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12377/vecOps/vec_ops.go b/wrappers/golang_v3/curves/bls12377/vecOps/vec_ops.go new file mode 100644 index 000000000..d883828f7 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12377/vecOps/vec_ops.go @@ -0,0 +1,48 @@ +package vecOps + +// #cgo CFLAGS: -I./include/ +// #include "vec_ops.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + + "unsafe" +) + +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Sub: + ret = (cr.CudaError)(C.bls12_377_sub_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Add: + ret = (cr.CudaError)(C.bls12_377_add_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Mul: + ret = (cr.CudaError)(C.bls12_377_mul_cuda(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} + +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { + core.TransposeCheck(in, out, onDevice) + + cIn := (*C.scalar_t)(in.AsUnsafePointer()) + cOut := (*C.scalar_t)(out.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cRowSize := (C.int)(rowSize) + cColumnSize := (C.int)(columnSize) + cOnDevice := (C._Bool)(onDevice) + cIsAsync := (C._Bool)(isAsync) + + err := (cr.CudaError)(C.bls12_377_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bls12381/base_field.go b/wrappers/golang_v3/curves/bls12381/base_field.go new file mode 100644 index 000000000..724c8bca9 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/base_field.go @@ -0,0 +1,84 @@ +package bls12381 + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int = 12 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromUint32(v uint32) BaseField { + f.limbs[0] = v + return *f +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bls12381/curve.go b/wrappers/golang_v3/curves/bls12381/curve.go new file mode 100644 index 000000000..d376c5c21 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/curve.go @@ -0,0 +1,177 @@ +package bls12381 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.bls12_381_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bls12_381_to_affine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_381_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_381_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go b/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go new file mode 100644 index 000000000..943ef8146 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go @@ -0,0 +1,24 @@ +package ecntt + +// #cgo CFLAGS: -I./include/ +// #include "ecntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) + + cPoints := (*C.projective_t)(pointsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.projective_t)(resultsPointer) + + __ret := C.bls12_381_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bls12381/ecntt/include/ecntt.h b/wrappers/golang_v3/curves/bls12381/ecntt/include/ecntt.h new file mode 100644 index 000000000..033af4664 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/ecntt/include/ecntt.h @@ -0,0 +1,19 @@ +#include + +#ifndef _BLS12_381_ECNTT_H +#define _BLS12_381_ECNTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NTTConfig NTTConfig; +typedef struct projective_t projective_t; + +cudaError_t bls12_381_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bls12381/g2/curve.go b/wrappers/golang_v3/curves/bls12381/g2/curve.go new file mode 100644 index 000000000..2b8caa002 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/g2/curve.go @@ -0,0 +1,177 @@ +package g2 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bls12_381_g2_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bls12_381_g2_to_affine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_381_g2_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_381_g2_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bls12381/g2/g2base_field.go b/wrappers/golang_v3/curves/bls12381/g2/g2base_field.go new file mode 100644 index 000000000..c4073af97 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/g2/g2base_field.go @@ -0,0 +1,84 @@ +package g2 + +import ( + "encoding/binary" + "fmt" +) + +const ( + G2BASE_LIMBS int = 24 +) + +type G2BaseField struct { + limbs [G2BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromUint32(v uint32) G2BaseField { + f.limbs[0] = v + return *f +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bls12381/g2/include/curve.h b/wrappers/golang_v3/curves/bls12381/g2/include/curve.h new file mode 100644 index 000000000..b7710244d --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/g2/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _BLS12_381_G2CURVE_H +#define _BLS12_381_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct g2_projective_t g2_projective_t; +typedef struct g2_affine_t g2_affine_t; +typedef struct DeviceContext DeviceContext; + +bool bls12_381_g2_eq(g2_projective_t* point1, g2_projective_t* point2); +void bls12_381_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bls12_381_g2_generate_projective_points(g2_projective_t* points, int size); +void bls12_381_g2_generate_affine_points(g2_affine_t* points, int size); +cudaError_t bls12_381_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bls12_381_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12381/g2/include/msm.h b/wrappers/golang_v3/curves/bls12381/g2/include/msm.h new file mode 100644 index 000000000..71c3ce984 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/g2/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BLS12_381_G2MSM_H +#define _BLS12_381_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct g2_projective_t g2_projective_t; +typedef struct g2_affine_t g2_affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bls12_381_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); +cudaError_t bls12_381_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out); +cudaError_t bls12_381_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12381/g2/include/scalar_field.h b/wrappers/golang_v3/curves/bls12381/g2/include/scalar_field.h new file mode 100644 index 000000000..842a6e101 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/g2/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BLS12_381_FIELD_H +#define _BLS12_381_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void bls12_381_generate_scalars(scalar_t* scalars, int size); +cudaError_t bls12_381_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12381/g2/msm.go b/wrappers/golang_v3/curves/bls12381/g2/msm.go new file mode 100644 index 000000000..05c407147 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/g2/msm.go @@ -0,0 +1,63 @@ +package g2 + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.g2_affine_t)(pointsPointer) + cResults := (*C.g2_projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.bls12_381_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: G2PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// G2PrecomputePoints should be used instead. +func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := G2GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.g2_affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bls12_381_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.g2_affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bls12_381_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bls12381/include/curve.h b/wrappers/golang_v3/curves/bls12381/include/curve.h new file mode 100644 index 000000000..1cb3bd61e --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _BLS12_381_CURVE_H +#define _BLS12_381_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct DeviceContext DeviceContext; + +bool bls12_381_eq(projective_t* point1, projective_t* point2); +void bls12_381_to_affine(projective_t* point, affine_t* point_out); +void bls12_381_generate_projective_points(projective_t* points, int size); +void bls12_381_generate_affine_points(affine_t* points, int size); +cudaError_t bls12_381_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bls12_381_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12381/include/scalar_field.h b/wrappers/golang_v3/curves/bls12381/include/scalar_field.h new file mode 100644 index 000000000..842a6e101 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BLS12_381_FIELD_H +#define _BLS12_381_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void bls12_381_generate_scalars(scalar_t* scalars, int size); +cudaError_t bls12_381_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12381/main.go b/wrappers/golang_v3/curves/bls12381/main.go new file mode 100644 index 000000000..3f3a21059 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/main.go @@ -0,0 +1,4 @@ +package bls12381 + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bls12_381 -lingo_field_bls12_381 -lstdc++ -lm +import "C" diff --git a/wrappers/golang_v3/curves/bls12381/msm/include/msm.h b/wrappers/golang_v3/curves/bls12381/msm/include/msm.h new file mode 100644 index 000000000..9312cdd85 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/msm/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BLS12_381_MSM_H +#define _BLS12_381_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bls12_381_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); +cudaError_t bls12_381_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); +cudaError_t bls12_381_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12381/msm/msm.go b/wrappers/golang_v3/curves/bls12381/msm/msm.go new file mode 100644 index 000000000..b9cbabb70 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/msm/msm.go @@ -0,0 +1,63 @@ +package msm + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.affine_t)(pointsPointer) + cResults := (*C.projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.bls12_381_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// PrecomputePoints should be used instead. +func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.bls12_381_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.bls12_381_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bls12381/ntt/include/ntt.h b/wrappers/golang_v3/curves/bls12381/ntt/include/ntt.h new file mode 100644 index 000000000..34133442c --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/ntt/include/ntt.h @@ -0,0 +1,23 @@ +#include +#include + +#ifndef _BLS12_381_NTT_H +#define _BLS12_381_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct NTTConfig NTTConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bls12_381_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t bls12_381_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); +cudaError_t bls12_381_release_domain(DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bls12381/ntt/ntt.go b/wrappers/golang_v3/curves/bls12381/ntt/ntt.go new file mode 100644 index 000000000..37be3ffe6 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/ntt/ntt.go @@ -0,0 +1,56 @@ +package ntt + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" +) + +import ( + "unsafe" +) + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.bls12_381_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func GetDefaultNttConfig() core.NTTConfig[[bls12_381.SCALAR_LIMBS]uint32] { + cosetGenField := bls12_381.ScalarField{} + cosetGenField.One() + var cosetGen [bls12_381.SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func InitDomain(primitiveRoot bls12_381.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.bls12_381_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + __ret := C.bls12_381_release_domain(cCtx) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bls12381/polynomial/include/polynomial.h b/wrappers/golang_v3/curves/bls12381/polynomial/include/polynomial.h new file mode 100644 index 000000000..2a36c90a5 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/polynomial/include/polynomial.h @@ -0,0 +1,51 @@ +#include +#include + +#ifndef _BLS12_381_POLY_H +#define _BLS12_381_POLY_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PolynomialInst PolynomialInst; +typedef struct IntegrityPointer IntegrityPointer; + +bool bls12_381_polynomial_init_cuda_backend(); +PolynomialInst* bls12_381_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); +PolynomialInst* bls12_381_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); +PolynomialInst* bls12_381_polynomial_clone(const PolynomialInst* p); +void bls12_381_polynomial_print(PolynomialInst* p); +void bls12_381_polynomial_delete(PolynomialInst* instance); +PolynomialInst* bls12_381_polynomial_add(const PolynomialInst* a, const PolynomialInst* b); +void bls12_381_polynomial_add_inplace(PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_381_polynomial_subtract(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_381_polynomial_multiply(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_381_polynomial_multiply_by_scalar(const PolynomialInst* a, const scalar_t* scalar); +void bls12_381_polynomial_division(const PolynomialInst* a, const PolynomialInst* b, PolynomialInst** q /*OUT*/, PolynomialInst** r /*OUT*/); +PolynomialInst* bls12_381_polynomial_quotient(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_381_polynomial_remainder(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bls12_381_polynomial_divide_by_vanishing(const PolynomialInst* p, size_t vanishing_poly_degree); +void bls12_381_polynomial_add_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void bls12_381_polynomial_sub_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void bls12_381_polynomial_evaluate_on_domain(const PolynomialInst* p, scalar_t* domain, size_t domain_size, scalar_t* evals /*OUT*/); +size_t bls12_381_polynomial_degree(PolynomialInst* p); +size_t bls12_381_polynomial_copy_coeffs_range(PolynomialInst* p, scalar_t* memory, size_t start_idx, size_t end_idx); +PolynomialInst* bls12_381_polynomial_even(PolynomialInst* p); +PolynomialInst* bls12_381_polynomial_odd(PolynomialInst* p); + +// scalar_t* bls12_381_polynomial_get_coeffs_raw_ptr(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// PolynomialInst* bls12_381_polynomial_slice(PolynomialInst* p, size_t offset, size_t stride, size_t size); +// IntegrityPointer* bls12_381_polynomial_get_coeff_view(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// IntegrityPointer* bls12_381_polynomial_get_rou_evaluations_view(PolynomialInst* p, size_t nof_evals, bool is_reversed, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// const scalar_t* bls12_381_polynomial_intergrity_ptr_get(IntegrityPointer* p); +// bool bls12_381_polynomial_intergrity_ptr_is_valid(IntegrityPointer* p); +// void bls12_381_polynomial_intergrity_ptr_destroy(IntegrityPointer* p); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/wrappers/golang_v3/curves/bls12381/polynomial/polynomial.go b/wrappers/golang_v3/curves/bls12381/polynomial/polynomial.go new file mode 100644 index 000000000..016c9ab18 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/polynomial/polynomial.go @@ -0,0 +1,176 @@ +package polynomial + +// #cgo CFLAGS: -I./include/ +// #include "polynomial.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" +) + +type PolynomialHandle = C.struct_PolynomialInst + +type DensePolynomial struct { + handle *PolynomialHandle +} + +func InitPolyBackend() bool { + return (bool)(C.bls12_381_polynomial_init_cuda_backend()) +} + +func (up *DensePolynomial) Print() { + C.bls12_381_polynomial_print(up.handle) +} + +func (up *DensePolynomial) CreateFromCoeffecitients(coeffs core.HostOrDeviceSlice) DensePolynomial { + if coeffs.IsOnDevice() { + coeffs.(core.DeviceSlice).CheckDevice() + } + coeffsPointer := (*C.scalar_t)(coeffs.AsUnsafePointer()) + cSize := (C.size_t)(coeffs.Len()) + up.handle = C.bls12_381_polynomial_create_from_coefficients(coeffsPointer, cSize) + return *up +} + +func (up *DensePolynomial) CreateFromROUEvaluations(evals core.HostOrDeviceSlice) DensePolynomial { + evalsPointer := (*C.scalar_t)(evals.AsUnsafePointer()) + cSize := (C.size_t)(evals.Len()) + up.handle = C.bls12_381_polynomial_create_from_coefficients(evalsPointer, cSize) + return *up +} + +func (up *DensePolynomial) Clone() DensePolynomial { + return DensePolynomial{ + handle: C.bls12_381_polynomial_clone(up.handle), + } +} + +// TODO @jeremyfelder: Maybe this should be in a SetFinalizer that is set on Create functions? +func (up *DensePolynomial) Delete() { + C.bls12_381_polynomial_delete(up.handle) +} + +func (up *DensePolynomial) Add(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_381_polynomial_add(up.handle, b.handle), + } +} + +func (up *DensePolynomial) AddInplace(b *DensePolynomial) { + C.bls12_381_polynomial_add_inplace(up.handle, b.handle) +} + +func (up *DensePolynomial) Subtract(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_381_polynomial_subtract(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Multiply(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_381_polynomial_multiply(up.handle, b.handle), + } +} + +func (up *DensePolynomial) MultiplyByScalar(scalar bls12_381.ScalarField) DensePolynomial { + cScalar := (*C.scalar_t)(unsafe.Pointer(scalar.AsPointer())) + return DensePolynomial{ + handle: C.bls12_381_polynomial_multiply_by_scalar(up.handle, cScalar), + } +} + +func (up *DensePolynomial) Divide(b *DensePolynomial) (DensePolynomial, DensePolynomial) { + var q, r *PolynomialHandle + C.bls12_381_polynomial_division(up.handle, b.handle, &q, &r) + return DensePolynomial{ + handle: q, + }, DensePolynomial{ + handle: r, + } +} + +func (up *DensePolynomial) Quotient(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_381_polynomial_quotient(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Remainder(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bls12_381_polynomial_remainder(up.handle, b.handle), + } +} + +func (up *DensePolynomial) DivideByVanishing(vanishing_degree uint64) DensePolynomial { + cVanishingDegree := (C.ulong)(vanishing_degree) + return DensePolynomial{ + handle: C.bls12_381_polynomial_divide_by_vanishing(up.handle, cVanishingDegree), + } +} + +func (up *DensePolynomial) AddMonomial(monomialCoeff bls12_381.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]bls12_381.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.bls12_381_polynomial_add_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) SubMonomial(monomialCoeff bls12_381.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]bls12_381.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.bls12_381_polynomial_sub_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) Eval(x bls12_381.ScalarField) bls12_381.ScalarField { + domains := make(core.HostSlice[bls12_381.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[bls12_381.ScalarField], 1) + up.EvalOnDomain(domains, evals) + return evals[0] +} + +func (up *DensePolynomial) EvalOnDomain(domain, evals core.HostOrDeviceSlice) core.HostOrDeviceSlice { + cDomain := (*C.scalar_t)(domain.AsUnsafePointer()) + cDomainSize := (C.size_t)(domain.Len()) + cEvals := (*C.scalar_t)(evals.AsUnsafePointer()) + C.bls12_381_polynomial_evaluate_on_domain(up.handle, cDomain, cDomainSize, cEvals) + return evals +} + +func (up *DensePolynomial) Degree() int { + return int(C.bls12_381_polynomial_degree(up.handle)) +} + +func (up *DensePolynomial) CopyCoeffsRange(start, end int, out core.HostOrDeviceSlice) (int, core.HostOrDeviceSlice) { + cStart := (C.size_t)(start) + cEnd := (C.size_t)(end) + cScalarOut := (*C.scalar_t)(out.AsUnsafePointer()) + __cNumCoeffsRead := C.bls12_381_polynomial_copy_coeffs_range(up.handle, cScalarOut, cStart, cEnd) + return int(__cNumCoeffsRead), out +} + +func (up *DensePolynomial) GetCoeff(idx int) bls12_381.ScalarField { + out := make(core.HostSlice[bls12_381.ScalarField], 1) + up.CopyCoeffsRange(idx, idx, out) + return out[0] +} + +func (up *DensePolynomial) Even() DensePolynomial { + evenPoly := C.bls12_381_polynomial_even(up.handle) + return DensePolynomial{ + handle: evenPoly, + } +} + +func (up *DensePolynomial) Odd() DensePolynomial { + oddPoly := C.bls12_381_polynomial_odd(up.handle) + return DensePolynomial{ + handle: oddPoly, + } +} diff --git a/wrappers/golang_v3/curves/bls12381/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/bls12381/poseidon/include/poseidon.h new file mode 100644 index 000000000..1372013ef --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/poseidon/include/poseidon.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BLS12_381_POSEIDON_H +#define _BLS12_381_POSEIDON_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PoseidonConfig PoseidonConfig; +typedef struct DeviceContext DeviceContext; +typedef struct PoseidonConstants PoseidonConstants; + + +cudaError_t bls12_381_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); +cudaError_t bls12_381_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); +cudaError_t bls12_381_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go b/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go new file mode 100644 index 000000000..1f99b2b51 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go @@ -0,0 +1,57 @@ +package poseidon + +// #cgo CFLAGS: -I./include/ +// #include "poseidon.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func GetDefaultPoseidonConfig() core.PoseidonConfig { + return core.GetDefaultPoseidonConfig() +} + +func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { + scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) + + cScalars := (*C.scalar_t)(scalarsPointer) + cResults := (*C.scalar_t)(resultsPointer) + cNumberOfStates := (C.int)(numberOfStates) + cArity := (C.int)(constants.Arity) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + cCfg := (*C.PoseidonConfig)(cfgPointer) + + __ret := C.bls12_381_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) + + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cFullRoundsHalfs := (C.int)(fullRoundsHalfs) + cPartialRounds := (C.int)(partialRounds) + cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) + + __ret := C.bls12_381_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + + __ret := C.bls12_381_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bls12381/scalar_field.go b/wrappers/golang_v3/curves/bls12381/scalar_field.go new file mode 100644 index 000000000..1dedd0b90 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/scalar_field.go @@ -0,0 +1,121 @@ +package bls12381 + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int = 8 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromUint32(v uint32) ScalarField { + f.limbs[0] = v + return *f +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalarSlice := make(core.HostSlice[ScalarField], size) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.bls12_381_generate_scalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/base_field_test.go b/wrappers/golang_v3/curves/bls12381/tests/base_field_test.go new file mode 100644 index 000000000..28552bcb1 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + BASE_LIMBS = bls12_381.BASE_LIMBS +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := bls12_381.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := bls12_381.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField bls12_381.BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField bls12_381.BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField bls12_381.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField bls12_381.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField bls12_381.BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField bls12_381.BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/curve_test.go b/wrappers/golang_v3/curves/bls12381/tests/curve_test.go new file mode 100644 index 000000000..ad33d17b8 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = bls12_381.BaseField{} + + var affineZero bls12_381.Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var affine bls12_381.Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var affine bls12_381.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bls12_381.BaseField + fieldOne.One() + + var expected bls12_381.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bls12_381.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero bls12_381.Projective + projectiveZero.Zero() + var fieldZero = bls12_381.BaseField{} + var fieldOne bls12_381.BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var projective bls12_381.Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var projective bls12_381.Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bls12_381.BaseField + fieldOne.One() + + var expected bls12_381.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bls12_381.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint bls12_381.Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go b/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go new file mode 100644 index 000000000..24837aabc --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go @@ -0,0 +1,30 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt" + "github.com/stretchr/testify/assert" +) + +func TestECNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + points := bls12_381.GenerateProjectivePoints(1 << largestTestSize) + + for _, size := range []int{4, 5, 6, 7, 8} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + pointsCopy := core.HostSliceFromElements[bls12_381.Projective](points[:testSize]) + cfg.Ordering = v + cfg.NttAlgorithm = core.Radix2 + + output := make(core.HostSlice[bls12_381.Projective], testSize) + e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + } + } +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go new file mode 100644 index 000000000..e804b7607 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = g2.G2BaseField{} + + var affineZero g2.G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var affine g2.G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero g2.G2Projective + projectiveZero.Zero() + var fieldZero = g2.G2BaseField{} + var fieldOne g2.G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint g2.G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_g2base_field_test.go new file mode 100644 index 000000000..2ec14da06 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_g2base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + G2BASE_LIMBS = bls12_381.G2BASE_LIMBS +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := bls12_381.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := bls12_381.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField bls12_381.G2BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField bls12_381.G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField bls12_381.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField bls12_381.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField bls12_381.G2BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField bls12_381.G2BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go new file mode 100644 index 000000000..424e064b5 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go @@ -0,0 +1,371 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleBls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/g2" +) + +func projectiveToGnarkAffineG2(p g2.G2Projective) bls12381.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := bls12381.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := bls12381.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := bls12381.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared bls12381.E2 + zSquared.Mul(&z, &z) + + var X bls12381.E2 + X.Mul(&x, &z) + + var Y bls12381.E2 + Y.Mul(&y, &zSquared) + + g2Jac := bls12381.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine bls12381.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} + +func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBls12_381.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bls12381.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12381.G2Affine], out g2.G2Projective) bool { + var msmRes bls12381.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bls12381.G2Jac + proj := projectiveToGnarkAffineG2(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bls12381.G2Affine { + points := make([]bls12381.G2Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian()) + xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes]) + xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:]) + xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes) + xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes) + + yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian()) + yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes]) + yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:]) + yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes) + yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes) + + points[index] = bls12381.G2Affine{ + X: bls12381.E2{ + A0: xA0Elem, + A1: xA1Elem, + }, + Y: bls12381.E2{ + A0: yA0Elem, + A1: yA1Elem, + }, + } + } + + return points +} + +func TestMSMG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBls12_381.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + + } +} + +func TestMSMG2PinnedHostMemory(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleBls12_381.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[g2.G2Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + + if pinnableAndLockable { + e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +func TestMSMG2GnarkCryptoTypes(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := g2.G2GenerateAffinePoints(size) + pointsGnark := convertIcicleG2AffineToG2Affine(points) + pointsHost := (core.HostSlice[bls12381.G2Affine])(pointsGnark) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_381.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestPrecomputePointsG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_381.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBls12_381.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := g2.G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} + +func TestMSMG2MultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBls12_381.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/main_test.go b/wrappers/golang_v3/curves/bls12381/tests/main_test.go new file mode 100644 index 000000000..31077b7bb --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/main_test.go @@ -0,0 +1,48 @@ +package tests + +import ( + "os" + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt" + poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/polynomial" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/fft" +) + +const ( + largestTestSize = 20 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := bls12_381.ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + return e +} + +func TestMain(m *testing.M) { + poly.InitPolyBackend() + + // setup domain + cfg := ntt.GetDefaultNttConfig() + e := initDomain(largestTestSize, cfg) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("initDomain failed") + } + + // execute tests + os.Exit(m.Run()) + + // release domain + e = ntt.ReleaseDomain(cfg.Ctx) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("ReleaseDomain failed") + } +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go new file mode 100644 index 000000000..196371a24 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go @@ -0,0 +1,331 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleBls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/msm" +) + +func projectiveToGnarkAffine(p icicleBls12_381.Projective) bls12381.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bls12381.G1Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBls12_381.ScalarField], points core.HostSlice[icicleBls12_381.Affine], out icicleBls12_381.Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bls12381.G1Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12381.G1Affine], out icicleBls12_381.Projective) bool { + var msmRes bls12381.G1Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bls12381.G1Jac + proj := projectiveToGnarkAffine(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func convertIcicleAffineToG1Affine(iciclePoints []icicleBls12_381.Affine) []bls12381.G1Affine { + points := make([]bls12381.G1Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes]byte)(iciclePoint.X.ToBytesLittleEndian()) + fpXElem, _ := fp.LittleEndian.Element(&xBytes) + + yBytes := ([fp.Bytes]byte)(iciclePoint.Y.ToBytesLittleEndian()) + fpYElem, _ := fp.LittleEndian.Element(&yBytes) + points[index] = bls12381.G1Affine{ + X: fpXElem, + Y: fpYElem, + } + } + + return points +} + +func TestMSM(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBls12_381.GenerateScalars(size) + points := icicleBls12_381.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleBls12_381.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + + } +} + +func TestMSMPinnedHostMemory(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleBls12_381.GenerateScalars(size) + points := icicleBls12_381.GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[icicleBls12_381.Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p icicleBls12_381.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + + if pinnableAndLockable { + e = msm.Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +func TestMSMGnarkCryptoTypes(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := icicleBls12_381.GenerateAffinePoints(size) + pointsGnark := convertIcicleAffineToG1Affine(points) + pointsHost := (core.HostSlice[bls12381.G1Affine])(pointsGnark) + + var p icicleBls12_381.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = msm.Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} + +func TestMSMBatch(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_381.GenerateScalars(totalSize) + points := icicleBls12_381.GenerateAffinePoints(totalSize) + + var p icicleBls12_381.Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_381.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestPrecomputePoints(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_381.GenerateScalars(totalSize) + points := icicleBls12_381.GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p icicleBls12_381.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_381.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBls12_381.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := icicleBls12_381.GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p icicleBls12_381.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} + +func TestMSMMultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBls12_381.GenerateScalars(size) + points := icicleBls12_381.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleBls12_381.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go b/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go new file mode 100644 index 000000000..bc13119e6 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go @@ -0,0 +1,263 @@ +package tests + +import ( + "reflect" + "testing" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/fft" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" +) + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bls12_381.ScalarField], output core.HostSlice[bls12_381.ScalarField], order core.Ordering, direction core.NTTDir) bool { + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) +} + +func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} +func TestNTTGetDefaultConfig(t *testing.T) { + actual := ntt.GetDefaultNttConfig() + expected := test_helpers.GenerateLimbOne(int(bls12_381.SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := bls12_381.ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := bls12_381.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[bls12_381.ScalarField], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} +func TestNttFrElement(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := make([]fr.Element, 4) + var x fr.Element + for i := 0; i < 4; i++ { + x.SetRandom() + scalars[i] = x + } + + for _, size := range []int{4} { + for _, v := range [1]core.Ordering{core.KNN} { + testSize := size + + scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[fr.Element], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := bls12_381.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[bls12_381.ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + largestTestSize := 12 + largestBatchSize := 100 + scalars := bls12_381.GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{2, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[bls12_381.ScalarField], totalSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +func TestReleaseDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + e := ntt.ReleaseDomain(cfg.Ctx) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := ntt.GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang_v3/curves/bls12381/tests/polynomial_test.go b/wrappers/golang_v3/curves/bls12381/tests/polynomial_test.go new file mode 100644 index 000000000..0c376cf85 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/polynomial_test.go @@ -0,0 +1,229 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/vecOps" + "github.com/stretchr/testify/assert" +) + +var one, two, three, four, five bls12_381.ScalarField + +func init() { + one.One() + two.FromUint32(2) + three.FromUint32(3) + four.FromUint32(4) + five.FromUint32(5) +} + +func rand() bls12_381.ScalarField { + return bls12_381.GenerateScalars(1)[0] +} + +func randomPoly(size int) (f polynomial.DensePolynomial) { + f.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_381.GenerateScalars(size))) + return f +} + +func vecOp(a, b bls12_381.ScalarField, op core.VecOps) bls12_381.ScalarField { + ahost := core.HostSliceWithValue(a, 1) + bhost := core.HostSliceWithValue(b, 1) + out := make(core.HostSlice[bls12_381.ScalarField], 1) + + cfg := core.DefaultVecOpsConfig() + vecOps.VecOp(ahost, bhost, out, cfg, op) + return out[0] +} + +func TestPolyCreateFromCoefficients(t *testing.T) { + scalars := bls12_381.GenerateScalars(33) + var uniPoly polynomial.DensePolynomial + + poly := uniPoly.CreateFromCoeffecitients(scalars) + poly.Print() +} + +func TestPolyEval(t *testing.T) { + // testing correct evaluation of f(8) for f(x)=4x^2+2x+5 + coeffs := core.HostSliceFromElements([]bls12_381.ScalarField{five, two, four}) + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(coeffs) + + var x bls12_381.ScalarField + x.FromUint32(8) + domains := make(core.HostSlice[bls12_381.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[bls12_381.ScalarField], 1) + fEvaled := f.EvalOnDomain(domains, evals) + var expected bls12_381.ScalarField + assert.Equal(t, expected.FromUint32(277), fEvaled.(core.HostSlice[bls12_381.ScalarField])[0]) +} + +func TestPolyClone(t *testing.T) { + f := randomPoly(8) + x := rand() + fx := f.Eval(x) + + g := f.Clone() + fg := f.Add(&g) + + gx := g.Eval(x) + fgx := fg.Eval(x) + + assert.Equal(t, fx, gx) + assert.Equal(t, vecOp(fx, gx, core.Add), fgx) +} + +func TestPolyAddSubMul(t *testing.T) { + testSize := 1 << 10 + f := randomPoly(testSize) + g := randomPoly(testSize) + x := rand() + + fx := f.Eval(x) + gx := g.Eval(x) + + polyAdd := f.Add(&g) + fxAddgx := vecOp(fx, gx, core.Add) + assert.Equal(t, polyAdd.Eval(x), fxAddgx) + + polySub := f.Subtract(&g) + fxSubgx := vecOp(fx, gx, core.Sub) + assert.Equal(t, polySub.Eval(x), fxSubgx) + + polyMul := f.Multiply(&g) + fxMulgx := vecOp(fx, gx, core.Mul) + assert.Equal(t, polyMul.Eval(x), fxMulgx) + + s1 := rand() + polMulS1 := f.MultiplyByScalar(s1) + assert.Equal(t, polMulS1.Eval(x), vecOp(fx, s1, core.Mul)) + + s2 := rand() + polMulS2 := f.MultiplyByScalar(s2) + assert.Equal(t, polMulS2.Eval(x), vecOp(fx, s2, core.Mul)) +} + +func TestPolyMonomials(t *testing.T) { + var zero bls12_381.ScalarField + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements([]bls12_381.ScalarField{one, zero, two})) + x := rand() + + fx := f.Eval(x) + f.AddMonomial(three, 1) + fxAdded := f.Eval(x) + assert.Equal(t, fxAdded, vecOp(fx, vecOp(three, x, core.Mul), core.Add)) + + f.SubMonomial(one, 0) + fxSub := f.Eval(x) + assert.Equal(t, fxSub, vecOp(fxAdded, one, core.Sub)) +} + +func TestPolyReadCoeffs(t *testing.T) { + var f polynomial.DensePolynomial + coeffs := core.HostSliceFromElements([]bls12_381.ScalarField{one, two, three, four}) + f.CreateFromCoeffecitients(coeffs) + coeffsCopied := make(core.HostSlice[bls12_381.ScalarField], coeffs.Len()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsCopied) + assert.ElementsMatch(t, coeffs, coeffsCopied) + + var coeffsDevice core.DeviceSlice + coeffsDevice.Malloc(coeffs.Len()*one.Size(), one.Size()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsDevice) + coeffsHost := make(core.HostSlice[bls12_381.ScalarField], coeffs.Len()) + coeffsHost.CopyFromDevice(&coeffsDevice) + + assert.ElementsMatch(t, coeffs, coeffsHost) +} + +func TestPolyOddEvenSlicing(t *testing.T) { + size := 1<<10 - 3 + f := randomPoly(size) + + even := f.Even() + odd := f.Odd() + assert.Equal(t, f.Degree(), even.Degree()+odd.Degree()+1) + + x := rand() + var evenExpected, oddExpected bls12_381.ScalarField + for i := size; i >= 0; i-- { + if i%2 == 0 { + mul := vecOp(evenExpected, x, core.Mul) + evenExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } else { + mul := vecOp(oddExpected, x, core.Mul) + oddExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } + } + + evenEvaled := even.Eval(x) + assert.Equal(t, evenExpected, evenEvaled) + + oddEvaled := odd.Eval(x) + assert.Equal(t, oddExpected, oddEvaled) +} + +func TestPolynomialDivision(t *testing.T) { + // divide f(x)/g(x), compute q(x), r(x) and check f(x)=q(x)*g(x)+r(x) + var f, g polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_381.GenerateScalars(1 << 4))) + g.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_381.GenerateScalars(1 << 2))) + + q, r := f.Divide(&g) + + qMulG := q.Multiply(&g) + fRecon := qMulG.Add(&r) + + x := bls12_381.GenerateScalars(1)[0] + fEval := f.Eval(x) + fReconEval := fRecon.Eval(x) + assert.Equal(t, fEval, fReconEval) +} + +func TestDivideByVanishing(t *testing.T) { + // poly of x^4-1 vanishes ad 4th rou + var zero bls12_381.ScalarField + minus_one := vecOp(zero, one, core.Sub) + coeffs := core.HostSliceFromElements([]bls12_381.ScalarField{minus_one, zero, zero, zero, one}) // x^4-1 + var v polynomial.DensePolynomial + v.CreateFromCoeffecitients(coeffs) + + f := randomPoly(1 << 3) + + fv := f.Multiply(&v) + fDegree := f.Degree() + fvDegree := fv.Degree() + assert.Equal(t, fDegree+4, fvDegree) + + fReconstructed := fv.DivideByVanishing(4) + assert.Equal(t, fDegree, fReconstructed.Degree()) + + x := rand() + assert.Equal(t, f.Eval(x), fReconstructed.Eval(x)) +} + +// func TestPolySlice(t *testing.T) { +// size := 4 +// coeffs := bls12_381.GenerateScalars(size) +// var f DensePolynomial +// f.CreateFromCoeffecitients(coeffs) +// fSlice := f.AsSlice() +// assert.True(t, fSlice.IsOnDevice()) +// assert.Equal(t, size, fSlice.Len()) + +// hostSlice := make(core.HostSlice[bls12_381.ScalarField], size) +// hostSlice.CopyFromDevice(fSlice) +// assert.Equal(t, coeffs, hostSlice) + +// cfg := ntt.GetDefaultNttConfig() +// res := make(core.HostSlice[bls12_381.ScalarField], size) +// ntt.Ntt(fSlice, core.KForward, cfg, res) + +// assert.Equal(t, f.Eval(one), res[0]) +// } diff --git a/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go b/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go new file mode 100644 index 000000000..915e89574 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go @@ -0,0 +1,55 @@ +package tests + +import ( + "testing" + + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/poseidon" + + "fmt" + "github.com/stretchr/testify/assert" +) + +func formatOutput(x bls12_381.ScalarField) string { + r := x.GetLimbs() + return fmt.Sprintf("%08x%08x%08x%08x%08x%08x%08x%08x", r[7], r[6], r[5], r[4], r[3], r[2], r[1], r[0]) +} + +func TestPoseidon(t *testing.T) { + + arity := 2 + numberOfStates := 1 + + cfg := poseidon.GetDefaultPoseidonConfig() + cfg.IsAsync = true + stream, _ := cr.CreateStream() + cfg.Ctx.Stream = &stream + + var constants core.PoseidonConstants[bls12_381.ScalarField] + + poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants + + scalars := bls12_381.GenerateScalars(numberOfStates * arity) + scalars[0] = scalars[0].Zero() + scalars[1] = scalars[0].Zero() + + scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function + + output := make(core.HostSlice[bls12_381.ScalarField], numberOfStates) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + expectedString := "48fe0b1331196f6cdb33a7c6e5af61b76fd388e1ef1d3d418be5147f0e4613d4" //This result is from https://github.com/triplewz/poseidon + outputString := formatOutput(output[0]) + + assert.Equal(t, outputString, expectedString, "Poseidon hash does not match expected result") + +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/scalar_field_test.go b/wrappers/golang_v3/curves/bls12381/tests/scalar_field_test.go new file mode 100644 index 000000000..4701fba70 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/scalar_field_test.go @@ -0,0 +1,120 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + SCALAR_LIMBS = bls12_381.SCALAR_LIMBS +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := bls12_381.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := bls12_381.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField bls12_381.ScalarField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField bls12_381.ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField bls12_381.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField bls12_381.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField bls12_381.ScalarField + bytes, expected := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField bls12_381.ScalarField + expected, limbs := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestBls12_381GenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := bls12_381.GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := bls12_381.ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestBls12_381MongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := bls12_381.GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + bls12_381.ToMontgomery(&deviceScalars) + + scalarsMontHost := bls12_381.GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + bls12_381.FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang_v3/curves/bls12381/tests/vec_ops_test.go b/wrappers/golang_v3/curves/bls12381/tests/vec_ops_test.go new file mode 100644 index 000000000..8a383ee48 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/tests/vec_ops_test.go @@ -0,0 +1,69 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/vecOps" + "github.com/stretchr/testify/assert" +) + +func TestBls12_381VecOps(t *testing.T) { + testSize := 1 << 14 + + a := bls12_381.GenerateScalars(testSize) + b := bls12_381.GenerateScalars(testSize) + var scalar bls12_381.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[bls12_381.ScalarField], testSize) + out2 := make(core.HostSlice[bls12_381.ScalarField], testSize) + out3 := make(core.HostSlice[bls12_381.ScalarField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.VecOp(a, b, out, cfg, core.Add) + vecOps.VecOp(out, b, out2, cfg, core.Sub) + + assert.Equal(t, a, out2) + + vecOps.VecOp(a, ones, out3, cfg, core.Mul) + + assert.Equal(t, a, out3) +} + +func TestBls12_381Transpose(t *testing.T) { + rowSize := 1 << 6 + columnSize := 1 << 8 + onDevice := false + isAsync := false + + matrix := bls12_381.GenerateScalars(rowSize * columnSize) + + out := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize) + out2 := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize) + + ctx, _ := cr.GetDefaultDeviceContext() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + + assert.Equal(t, matrix, out2) + + var dMatrix, dOut, dOut2 core.DeviceSlice + onDevice = true + + matrix.CopyToDevice(&dMatrix, true) + dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + output := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize) + output.CopyFromDevice(&dOut2) + + assert.Equal(t, matrix, output) +} diff --git a/wrappers/golang_v3/curves/bls12381/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/bls12381/vecOps/include/vec_ops.h new file mode 100644 index 000000000..65ff61787 --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/vecOps/include/vec_ops.h @@ -0,0 +1,53 @@ +#include +#include + +#ifndef _BLS12_381_VEC_OPS_H +#define _BLS12_381_VEC_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bls12_381_mul_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bls12_381_add_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bls12_381_sub_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bls12_381_transpose_matrix_cuda( + scalar_t* mat_in, + int row_size, + int column_size, + scalar_t* mat_out, + DeviceContext* ctx, + bool on_device, + bool is_async +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bls12381/vecOps/vec_ops.go b/wrappers/golang_v3/curves/bls12381/vecOps/vec_ops.go new file mode 100644 index 000000000..a17aa93af --- /dev/null +++ b/wrappers/golang_v3/curves/bls12381/vecOps/vec_ops.go @@ -0,0 +1,48 @@ +package vecOps + +// #cgo CFLAGS: -I./include/ +// #include "vec_ops.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + + "unsafe" +) + +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Sub: + ret = (cr.CudaError)(C.bls12_381_sub_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Add: + ret = (cr.CudaError)(C.bls12_381_add_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Mul: + ret = (cr.CudaError)(C.bls12_381_mul_cuda(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} + +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { + core.TransposeCheck(in, out, onDevice) + + cIn := (*C.scalar_t)(in.AsUnsafePointer()) + cOut := (*C.scalar_t)(out.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cRowSize := (C.int)(rowSize) + cColumnSize := (C.int)(columnSize) + cOnDevice := (C._Bool)(onDevice) + cIsAsync := (C._Bool)(isAsync) + + err := (cr.CudaError)(C.bls12_381_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bn254/base_field.go b/wrappers/golang_v3/curves/bn254/base_field.go new file mode 100644 index 000000000..0fbf3aeee --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/base_field.go @@ -0,0 +1,84 @@ +package bn254 + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int = 8 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromUint32(v uint32) BaseField { + f.limbs[0] = v + return *f +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bn254/curve.go b/wrappers/golang_v3/curves/bn254/curve.go new file mode 100644 index 000000000..80a844c7a --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/curve.go @@ -0,0 +1,177 @@ +package bn254 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.bn254_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bn254_to_affine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go b/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go new file mode 100644 index 000000000..feda5f2d9 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go @@ -0,0 +1,24 @@ +package ecntt + +// #cgo CFLAGS: -I./include/ +// #include "ecntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) + + cPoints := (*C.projective_t)(pointsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.projective_t)(resultsPointer) + + __ret := C.bn254_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bn254/ecntt/include/ecntt.h b/wrappers/golang_v3/curves/bn254/ecntt/include/ecntt.h new file mode 100644 index 000000000..da61fb915 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/ecntt/include/ecntt.h @@ -0,0 +1,19 @@ +#include + +#ifndef _BN254_ECNTT_H +#define _BN254_ECNTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NTTConfig NTTConfig; +typedef struct projective_t projective_t; + +cudaError_t bn254_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bn254/g2/curve.go b/wrappers/golang_v3/curves/bn254/g2/curve.go new file mode 100644 index 000000000..586d23831 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/g2/curve.go @@ -0,0 +1,177 @@ +package g2 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bn254_g2_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bn254_g2_to_affine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254_g2_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254_g2_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bn254/g2/g2base_field.go b/wrappers/golang_v3/curves/bn254/g2/g2base_field.go new file mode 100644 index 000000000..409a7d5ad --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/g2/g2base_field.go @@ -0,0 +1,84 @@ +package g2 + +import ( + "encoding/binary" + "fmt" +) + +const ( + G2BASE_LIMBS int = 16 +) + +type G2BaseField struct { + limbs [G2BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromUint32(v uint32) G2BaseField { + f.limbs[0] = v + return *f +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bn254/g2/include/curve.h b/wrappers/golang_v3/curves/bn254/g2/include/curve.h new file mode 100644 index 000000000..e8863f1ef --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/g2/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _BN254_G2CURVE_H +#define _BN254_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct g2_projective_t g2_projective_t; +typedef struct g2_affine_t g2_affine_t; +typedef struct DeviceContext DeviceContext; + +bool bn254_g2_eq(g2_projective_t* point1, g2_projective_t* point2); +void bn254_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bn254_g2_generate_projective_points(g2_projective_t* points, int size); +void bn254_g2_generate_affine_points(g2_affine_t* points, int size); +cudaError_t bn254_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bn254_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bn254/g2/include/msm.h b/wrappers/golang_v3/curves/bn254/g2/include/msm.h new file mode 100644 index 000000000..41f814526 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/g2/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BN254_G2MSM_H +#define _BN254_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct g2_projective_t g2_projective_t; +typedef struct g2_affine_t g2_affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bn254_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); +cudaError_t bn254_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out); +cudaError_t bn254_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bn254/g2/include/scalar_field.h b/wrappers/golang_v3/curves/bn254/g2/include/scalar_field.h new file mode 100644 index 000000000..f37e47db9 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/g2/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BN254_FIELD_H +#define _BN254_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void bn254_generate_scalars(scalar_t* scalars, int size); +cudaError_t bn254_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bn254/g2/msm.go b/wrappers/golang_v3/curves/bn254/g2/msm.go new file mode 100644 index 000000000..1e2c8d3e2 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/g2/msm.go @@ -0,0 +1,63 @@ +package g2 + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.g2_affine_t)(pointsPointer) + cResults := (*C.g2_projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.bn254_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: G2PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// G2PrecomputePoints should be used instead. +func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := G2GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.g2_affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bn254_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.g2_affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bn254_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bn254/include/curve.h b/wrappers/golang_v3/curves/bn254/include/curve.h new file mode 100644 index 000000000..069600aa4 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _BN254_CURVE_H +#define _BN254_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct DeviceContext DeviceContext; + +bool bn254_eq(projective_t* point1, projective_t* point2); +void bn254_to_affine(projective_t* point, affine_t* point_out); +void bn254_generate_projective_points(projective_t* points, int size); +void bn254_generate_affine_points(affine_t* points, int size); +cudaError_t bn254_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bn254_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bn254/include/scalar_field.h b/wrappers/golang_v3/curves/bn254/include/scalar_field.h new file mode 100644 index 000000000..f37e47db9 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BN254_FIELD_H +#define _BN254_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void bn254_generate_scalars(scalar_t* scalars, int size); +cudaError_t bn254_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bn254/main.go b/wrappers/golang_v3/curves/bn254/main.go new file mode 100644 index 000000000..2d88cd5be --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/main.go @@ -0,0 +1,4 @@ +package bn254 + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bn254 -lingo_field_bn254 -lstdc++ -lm +import "C" diff --git a/wrappers/golang_v3/curves/bn254/msm/include/msm.h b/wrappers/golang_v3/curves/bn254/msm/include/msm.h new file mode 100644 index 000000000..47985945a --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/msm/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BN254_MSM_H +#define _BN254_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bn254_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); +cudaError_t bn254_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); +cudaError_t bn254_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bn254/msm/msm.go b/wrappers/golang_v3/curves/bn254/msm/msm.go new file mode 100644 index 000000000..61695d82c --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/msm/msm.go @@ -0,0 +1,63 @@ +package msm + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.affine_t)(pointsPointer) + cResults := (*C.projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.bn254_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// PrecomputePoints should be used instead. +func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.bn254_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.bn254_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bn254/ntt/include/ntt.h b/wrappers/golang_v3/curves/bn254/ntt/include/ntt.h new file mode 100644 index 000000000..48b244aa1 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/ntt/include/ntt.h @@ -0,0 +1,23 @@ +#include +#include + +#ifndef _BN254_NTT_H +#define _BN254_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct NTTConfig NTTConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bn254_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t bn254_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); +cudaError_t bn254_release_domain(DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bn254/ntt/ntt.go b/wrappers/golang_v3/curves/bn254/ntt/ntt.go new file mode 100644 index 000000000..3137c8001 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/ntt/ntt.go @@ -0,0 +1,56 @@ +package ntt + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" +) + +import ( + "unsafe" +) + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.bn254_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func GetDefaultNttConfig() core.NTTConfig[[bn254.SCALAR_LIMBS]uint32] { + cosetGenField := bn254.ScalarField{} + cosetGenField.One() + var cosetGen [bn254.SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func InitDomain(primitiveRoot bn254.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.bn254_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + __ret := C.bn254_release_domain(cCtx) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bn254/polynomial/include/polynomial.h b/wrappers/golang_v3/curves/bn254/polynomial/include/polynomial.h new file mode 100644 index 000000000..14cf6eeb2 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/polynomial/include/polynomial.h @@ -0,0 +1,51 @@ +#include +#include + +#ifndef _BN254_POLY_H +#define _BN254_POLY_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PolynomialInst PolynomialInst; +typedef struct IntegrityPointer IntegrityPointer; + +bool bn254_polynomial_init_cuda_backend(); +PolynomialInst* bn254_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); +PolynomialInst* bn254_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); +PolynomialInst* bn254_polynomial_clone(const PolynomialInst* p); +void bn254_polynomial_print(PolynomialInst* p); +void bn254_polynomial_delete(PolynomialInst* instance); +PolynomialInst* bn254_polynomial_add(const PolynomialInst* a, const PolynomialInst* b); +void bn254_polynomial_add_inplace(PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bn254_polynomial_subtract(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bn254_polynomial_multiply(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bn254_polynomial_multiply_by_scalar(const PolynomialInst* a, const scalar_t* scalar); +void bn254_polynomial_division(const PolynomialInst* a, const PolynomialInst* b, PolynomialInst** q /*OUT*/, PolynomialInst** r /*OUT*/); +PolynomialInst* bn254_polynomial_quotient(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bn254_polynomial_remainder(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bn254_polynomial_divide_by_vanishing(const PolynomialInst* p, size_t vanishing_poly_degree); +void bn254_polynomial_add_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void bn254_polynomial_sub_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void bn254_polynomial_evaluate_on_domain(const PolynomialInst* p, scalar_t* domain, size_t domain_size, scalar_t* evals /*OUT*/); +size_t bn254_polynomial_degree(PolynomialInst* p); +size_t bn254_polynomial_copy_coeffs_range(PolynomialInst* p, scalar_t* memory, size_t start_idx, size_t end_idx); +PolynomialInst* bn254_polynomial_even(PolynomialInst* p); +PolynomialInst* bn254_polynomial_odd(PolynomialInst* p); + +// scalar_t* bn254_polynomial_get_coeffs_raw_ptr(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// PolynomialInst* bn254_polynomial_slice(PolynomialInst* p, size_t offset, size_t stride, size_t size); +// IntegrityPointer* bn254_polynomial_get_coeff_view(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// IntegrityPointer* bn254_polynomial_get_rou_evaluations_view(PolynomialInst* p, size_t nof_evals, bool is_reversed, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// const scalar_t* bn254_polynomial_intergrity_ptr_get(IntegrityPointer* p); +// bool bn254_polynomial_intergrity_ptr_is_valid(IntegrityPointer* p); +// void bn254_polynomial_intergrity_ptr_destroy(IntegrityPointer* p); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/wrappers/golang_v3/curves/bn254/polynomial/polynomial.go b/wrappers/golang_v3/curves/bn254/polynomial/polynomial.go new file mode 100644 index 000000000..ffee8af55 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/polynomial/polynomial.go @@ -0,0 +1,176 @@ +package polynomial + +// #cgo CFLAGS: -I./include/ +// #include "polynomial.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" +) + +type PolynomialHandle = C.struct_PolynomialInst + +type DensePolynomial struct { + handle *PolynomialHandle +} + +func InitPolyBackend() bool { + return (bool)(C.bn254_polynomial_init_cuda_backend()) +} + +func (up *DensePolynomial) Print() { + C.bn254_polynomial_print(up.handle) +} + +func (up *DensePolynomial) CreateFromCoeffecitients(coeffs core.HostOrDeviceSlice) DensePolynomial { + if coeffs.IsOnDevice() { + coeffs.(core.DeviceSlice).CheckDevice() + } + coeffsPointer := (*C.scalar_t)(coeffs.AsUnsafePointer()) + cSize := (C.size_t)(coeffs.Len()) + up.handle = C.bn254_polynomial_create_from_coefficients(coeffsPointer, cSize) + return *up +} + +func (up *DensePolynomial) CreateFromROUEvaluations(evals core.HostOrDeviceSlice) DensePolynomial { + evalsPointer := (*C.scalar_t)(evals.AsUnsafePointer()) + cSize := (C.size_t)(evals.Len()) + up.handle = C.bn254_polynomial_create_from_coefficients(evalsPointer, cSize) + return *up +} + +func (up *DensePolynomial) Clone() DensePolynomial { + return DensePolynomial{ + handle: C.bn254_polynomial_clone(up.handle), + } +} + +// TODO @jeremyfelder: Maybe this should be in a SetFinalizer that is set on Create functions? +func (up *DensePolynomial) Delete() { + C.bn254_polynomial_delete(up.handle) +} + +func (up *DensePolynomial) Add(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bn254_polynomial_add(up.handle, b.handle), + } +} + +func (up *DensePolynomial) AddInplace(b *DensePolynomial) { + C.bn254_polynomial_add_inplace(up.handle, b.handle) +} + +func (up *DensePolynomial) Subtract(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bn254_polynomial_subtract(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Multiply(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bn254_polynomial_multiply(up.handle, b.handle), + } +} + +func (up *DensePolynomial) MultiplyByScalar(scalar bn254.ScalarField) DensePolynomial { + cScalar := (*C.scalar_t)(unsafe.Pointer(scalar.AsPointer())) + return DensePolynomial{ + handle: C.bn254_polynomial_multiply_by_scalar(up.handle, cScalar), + } +} + +func (up *DensePolynomial) Divide(b *DensePolynomial) (DensePolynomial, DensePolynomial) { + var q, r *PolynomialHandle + C.bn254_polynomial_division(up.handle, b.handle, &q, &r) + return DensePolynomial{ + handle: q, + }, DensePolynomial{ + handle: r, + } +} + +func (up *DensePolynomial) Quotient(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bn254_polynomial_quotient(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Remainder(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bn254_polynomial_remainder(up.handle, b.handle), + } +} + +func (up *DensePolynomial) DivideByVanishing(vanishing_degree uint64) DensePolynomial { + cVanishingDegree := (C.ulong)(vanishing_degree) + return DensePolynomial{ + handle: C.bn254_polynomial_divide_by_vanishing(up.handle, cVanishingDegree), + } +} + +func (up *DensePolynomial) AddMonomial(monomialCoeff bn254.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]bn254.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.bn254_polynomial_add_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) SubMonomial(monomialCoeff bn254.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]bn254.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.bn254_polynomial_sub_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) Eval(x bn254.ScalarField) bn254.ScalarField { + domains := make(core.HostSlice[bn254.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[bn254.ScalarField], 1) + up.EvalOnDomain(domains, evals) + return evals[0] +} + +func (up *DensePolynomial) EvalOnDomain(domain, evals core.HostOrDeviceSlice) core.HostOrDeviceSlice { + cDomain := (*C.scalar_t)(domain.AsUnsafePointer()) + cDomainSize := (C.size_t)(domain.Len()) + cEvals := (*C.scalar_t)(evals.AsUnsafePointer()) + C.bn254_polynomial_evaluate_on_domain(up.handle, cDomain, cDomainSize, cEvals) + return evals +} + +func (up *DensePolynomial) Degree() int { + return int(C.bn254_polynomial_degree(up.handle)) +} + +func (up *DensePolynomial) CopyCoeffsRange(start, end int, out core.HostOrDeviceSlice) (int, core.HostOrDeviceSlice) { + cStart := (C.size_t)(start) + cEnd := (C.size_t)(end) + cScalarOut := (*C.scalar_t)(out.AsUnsafePointer()) + __cNumCoeffsRead := C.bn254_polynomial_copy_coeffs_range(up.handle, cScalarOut, cStart, cEnd) + return int(__cNumCoeffsRead), out +} + +func (up *DensePolynomial) GetCoeff(idx int) bn254.ScalarField { + out := make(core.HostSlice[bn254.ScalarField], 1) + up.CopyCoeffsRange(idx, idx, out) + return out[0] +} + +func (up *DensePolynomial) Even() DensePolynomial { + evenPoly := C.bn254_polynomial_even(up.handle) + return DensePolynomial{ + handle: evenPoly, + } +} + +func (up *DensePolynomial) Odd() DensePolynomial { + oddPoly := C.bn254_polynomial_odd(up.handle) + return DensePolynomial{ + handle: oddPoly, + } +} diff --git a/wrappers/golang_v3/curves/bn254/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/bn254/poseidon/include/poseidon.h new file mode 100644 index 000000000..5d63920d6 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/poseidon/include/poseidon.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BN254_POSEIDON_H +#define _BN254_POSEIDON_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PoseidonConfig PoseidonConfig; +typedef struct DeviceContext DeviceContext; +typedef struct PoseidonConstants PoseidonConstants; + + +cudaError_t bn254_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); +cudaError_t bn254_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); +cudaError_t bn254_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bn254/poseidon/poseidon.go b/wrappers/golang_v3/curves/bn254/poseidon/poseidon.go new file mode 100644 index 000000000..e5724e80f --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/poseidon/poseidon.go @@ -0,0 +1,57 @@ +package poseidon + +// #cgo CFLAGS: -I./include/ +// #include "poseidon.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func GetDefaultPoseidonConfig() core.PoseidonConfig { + return core.GetDefaultPoseidonConfig() +} + +func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { + scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) + + cScalars := (*C.scalar_t)(scalarsPointer) + cResults := (*C.scalar_t)(resultsPointer) + cNumberOfStates := (C.int)(numberOfStates) + cArity := (C.int)(constants.Arity) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + cCfg := (*C.PoseidonConfig)(cfgPointer) + + __ret := C.bn254_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) + + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cFullRoundsHalfs := (C.int)(fullRoundsHalfs) + cPartialRounds := (C.int)(partialRounds) + cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) + + __ret := C.bn254_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + + __ret := C.bn254_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bn254/scalar_field.go b/wrappers/golang_v3/curves/bn254/scalar_field.go new file mode 100644 index 000000000..cac10ce8c --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/scalar_field.go @@ -0,0 +1,121 @@ +package bn254 + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int = 8 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromUint32(v uint32) ScalarField { + f.limbs[0] = v + return *f +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalarSlice := make(core.HostSlice[ScalarField], size) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.bn254_generate_scalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang_v3/curves/bn254/tests/base_field_test.go b/wrappers/golang_v3/curves/bn254/tests/base_field_test.go new file mode 100644 index 000000000..72b5b9a1c --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + BASE_LIMBS = bn254.BASE_LIMBS +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := bn254.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := bn254.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField bn254.BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField bn254.BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField bn254.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField bn254.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField bn254.BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField bn254.BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bn254/tests/curve_test.go b/wrappers/golang_v3/curves/bn254/tests/curve_test.go new file mode 100644 index 000000000..4774340e5 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = bn254.BaseField{} + + var affineZero bn254.Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var affine bn254.Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var affine bn254.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bn254.BaseField + fieldOne.One() + + var expected bn254.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bn254.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero bn254.Projective + projectiveZero.Zero() + var fieldZero = bn254.BaseField{} + var fieldOne bn254.BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var projective bn254.Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var projective bn254.Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bn254.BaseField + fieldOne.One() + + var expected bn254.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bn254.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint bn254.Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go new file mode 100644 index 000000000..08587bba6 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go @@ -0,0 +1,30 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" + "github.com/stretchr/testify/assert" +) + +func TestECNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + points := bn254.GenerateProjectivePoints(1 << largestTestSize) + + for _, size := range []int{4, 5, 6, 7, 8} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + pointsCopy := core.HostSliceFromElements[bn254.Projective](points[:testSize]) + cfg.Ordering = v + cfg.NttAlgorithm = core.Radix2 + + output := make(core.HostSlice[bn254.Projective], testSize) + e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + } + } +} diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go new file mode 100644 index 000000000..546aa81bb --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = g2.G2BaseField{} + + var affineZero g2.G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var affine g2.G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero g2.G2Projective + projectiveZero.Zero() + var fieldZero = g2.G2BaseField{} + var fieldOne g2.G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint g2.G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go new file mode 100644 index 000000000..b822ed7ac --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + G2BASE_LIMBS = bn254.G2BASE_LIMBS +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := bn254.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := bn254.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField bn254.G2BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField bn254.G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField bn254.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField bn254.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField bn254.G2BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField bn254.G2BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go new file mode 100644 index 000000000..8c1eb3da1 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go @@ -0,0 +1,371 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" +) + +func projectiveToGnarkAffineG2(p g2.G2Projective) bn254.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := bn254.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := bn254.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := bn254.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared bn254.E2 + zSquared.Mul(&z, &z) + + var X bn254.E2 + X.Mul(&x, &z) + + var Y bn254.E2 + Y.Mul(&y, &zSquared) + + g2Jac := bn254.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine bn254.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} + +func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBn254.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bn254.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bn254.G2Affine], out g2.G2Projective) bool { + var msmRes bn254.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bn254.G2Jac + proj := projectiveToGnarkAffineG2(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bn254.G2Affine { + points := make([]bn254.G2Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian()) + xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes]) + xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:]) + xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes) + xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes) + + yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian()) + yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes]) + yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:]) + yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes) + yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes) + + points[index] = bn254.G2Affine{ + X: bn254.E2{ + A0: xA0Elem, + A1: xA1Elem, + }, + Y: bn254.E2{ + A0: yA0Elem, + A1: yA1Elem, + }, + } + } + + return points +} + +func TestMSMG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBn254.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + + } +} + +func TestMSMG2PinnedHostMemory(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleBn254.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[g2.G2Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + + if pinnableAndLockable { + e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +func TestMSMG2GnarkCryptoTypes(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := g2.G2GenerateAffinePoints(size) + pointsGnark := convertIcicleG2AffineToG2Affine(points) + pointsHost := (core.HostSlice[bn254.G2Affine])(pointsGnark) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestPrecomputePointsG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBn254.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := g2.G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} + +func TestMSMG2MultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBn254.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bn254/tests/main_test.go b/wrappers/golang_v3/curves/bn254/tests/main_test.go new file mode 100644 index 000000000..f06c8a890 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/main_test.go @@ -0,0 +1,48 @@ +package tests + +import ( + "os" + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" + poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/polynomial" + + "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" +) + +const ( + largestTestSize = 20 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := bn254.ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + return e +} + +func TestMain(m *testing.M) { + poly.InitPolyBackend() + + // setup domain + cfg := ntt.GetDefaultNttConfig() + e := initDomain(largestTestSize, cfg) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("initDomain failed") + } + + // execute tests + os.Exit(m.Run()) + + // release domain + e = ntt.ReleaseDomain(cfg.Ctx) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("ReleaseDomain failed") + } +} diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go new file mode 100644 index 000000000..eab2b0005 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -0,0 +1,331 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/msm" +) + +func projectiveToGnarkAffine(p icicleBn254.Projective) bn254.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bn254.G1Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBn254.ScalarField], points core.HostSlice[icicleBn254.Affine], out icicleBn254.Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bn254.G1Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bn254.G1Affine], out icicleBn254.Projective) bool { + var msmRes bn254.G1Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bn254.G1Jac + proj := projectiveToGnarkAffine(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func convertIcicleAffineToG1Affine(iciclePoints []icicleBn254.Affine) []bn254.G1Affine { + points := make([]bn254.G1Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes]byte)(iciclePoint.X.ToBytesLittleEndian()) + fpXElem, _ := fp.LittleEndian.Element(&xBytes) + + yBytes := ([fp.Bytes]byte)(iciclePoint.Y.ToBytesLittleEndian()) + fpYElem, _ := fp.LittleEndian.Element(&yBytes) + points[index] = bn254.G1Affine{ + X: fpXElem, + Y: fpYElem, + } + } + + return points +} + +func TestMSM(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBn254.GenerateScalars(size) + points := icicleBn254.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleBn254.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + + } +} + +func TestMSMPinnedHostMemory(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleBn254.GenerateScalars(size) + points := icicleBn254.GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[icicleBn254.Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p icicleBn254.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[icicleBn254.Projective], 1) + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + + if pinnableAndLockable { + e = msm.Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +func TestMSMGnarkCryptoTypes(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := icicleBn254.GenerateAffinePoints(size) + pointsGnark := convertIcicleAffineToG1Affine(points) + pointsHost := (core.HostSlice[bn254.G1Affine])(pointsGnark) + + var p icicleBn254.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = msm.Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} + +func TestMSMBatch(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := icicleBn254.GenerateAffinePoints(totalSize) + + var p icicleBn254.Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestPrecomputePoints(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := icicleBn254.GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p icicleBn254.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBn254.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := icicleBn254.GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p icicleBn254.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} + +func TestMSMMultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBn254.GenerateScalars(size) + points := icicleBn254.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleBn254.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go new file mode 100644 index 000000000..6e36380df --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go @@ -0,0 +1,263 @@ +package tests + +import ( + "reflect" + "testing" + + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" +) + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bn254.ScalarField], output core.HostSlice[bn254.ScalarField], order core.Ordering, direction core.NTTDir) bool { + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) +} + +func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} +func TestNTTGetDefaultConfig(t *testing.T) { + actual := ntt.GetDefaultNttConfig() + expected := test_helpers.GenerateLimbOne(int(bn254.SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := bn254.ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := bn254.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[bn254.ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[bn254.ScalarField], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} +func TestNttFrElement(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := make([]fr.Element, 4) + var x fr.Element + for i := 0; i < 4; i++ { + x.SetRandom() + scalars[i] = x + } + + for _, size := range []int{4} { + for _, v := range [1]core.Ordering{core.KNN} { + testSize := size + + scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[fr.Element], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := bn254.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[bn254.ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[bn254.ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + largestTestSize := 12 + largestBatchSize := 100 + scalars := bn254.GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{2, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[bn254.ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[bn254.ScalarField], totalSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +func TestReleaseDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + e := ntt.ReleaseDomain(cfg.Ctx) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := ntt.GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/polynomial_test.go b/wrappers/golang_v3/curves/bn254/tests/polynomial_test.go new file mode 100644 index 000000000..8eb5efed9 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/polynomial_test.go @@ -0,0 +1,229 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/vecOps" + "github.com/stretchr/testify/assert" +) + +var one, two, three, four, five bn254.ScalarField + +func init() { + one.One() + two.FromUint32(2) + three.FromUint32(3) + four.FromUint32(4) + five.FromUint32(5) +} + +func rand() bn254.ScalarField { + return bn254.GenerateScalars(1)[0] +} + +func randomPoly(size int) (f polynomial.DensePolynomial) { + f.CreateFromCoeffecitients(core.HostSliceFromElements(bn254.GenerateScalars(size))) + return f +} + +func vecOp(a, b bn254.ScalarField, op core.VecOps) bn254.ScalarField { + ahost := core.HostSliceWithValue(a, 1) + bhost := core.HostSliceWithValue(b, 1) + out := make(core.HostSlice[bn254.ScalarField], 1) + + cfg := core.DefaultVecOpsConfig() + vecOps.VecOp(ahost, bhost, out, cfg, op) + return out[0] +} + +func TestPolyCreateFromCoefficients(t *testing.T) { + scalars := bn254.GenerateScalars(33) + var uniPoly polynomial.DensePolynomial + + poly := uniPoly.CreateFromCoeffecitients(scalars) + poly.Print() +} + +func TestPolyEval(t *testing.T) { + // testing correct evaluation of f(8) for f(x)=4x^2+2x+5 + coeffs := core.HostSliceFromElements([]bn254.ScalarField{five, two, four}) + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(coeffs) + + var x bn254.ScalarField + x.FromUint32(8) + domains := make(core.HostSlice[bn254.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[bn254.ScalarField], 1) + fEvaled := f.EvalOnDomain(domains, evals) + var expected bn254.ScalarField + assert.Equal(t, expected.FromUint32(277), fEvaled.(core.HostSlice[bn254.ScalarField])[0]) +} + +func TestPolyClone(t *testing.T) { + f := randomPoly(8) + x := rand() + fx := f.Eval(x) + + g := f.Clone() + fg := f.Add(&g) + + gx := g.Eval(x) + fgx := fg.Eval(x) + + assert.Equal(t, fx, gx) + assert.Equal(t, vecOp(fx, gx, core.Add), fgx) +} + +func TestPolyAddSubMul(t *testing.T) { + testSize := 1 << 10 + f := randomPoly(testSize) + g := randomPoly(testSize) + x := rand() + + fx := f.Eval(x) + gx := g.Eval(x) + + polyAdd := f.Add(&g) + fxAddgx := vecOp(fx, gx, core.Add) + assert.Equal(t, polyAdd.Eval(x), fxAddgx) + + polySub := f.Subtract(&g) + fxSubgx := vecOp(fx, gx, core.Sub) + assert.Equal(t, polySub.Eval(x), fxSubgx) + + polyMul := f.Multiply(&g) + fxMulgx := vecOp(fx, gx, core.Mul) + assert.Equal(t, polyMul.Eval(x), fxMulgx) + + s1 := rand() + polMulS1 := f.MultiplyByScalar(s1) + assert.Equal(t, polMulS1.Eval(x), vecOp(fx, s1, core.Mul)) + + s2 := rand() + polMulS2 := f.MultiplyByScalar(s2) + assert.Equal(t, polMulS2.Eval(x), vecOp(fx, s2, core.Mul)) +} + +func TestPolyMonomials(t *testing.T) { + var zero bn254.ScalarField + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements([]bn254.ScalarField{one, zero, two})) + x := rand() + + fx := f.Eval(x) + f.AddMonomial(three, 1) + fxAdded := f.Eval(x) + assert.Equal(t, fxAdded, vecOp(fx, vecOp(three, x, core.Mul), core.Add)) + + f.SubMonomial(one, 0) + fxSub := f.Eval(x) + assert.Equal(t, fxSub, vecOp(fxAdded, one, core.Sub)) +} + +func TestPolyReadCoeffs(t *testing.T) { + var f polynomial.DensePolynomial + coeffs := core.HostSliceFromElements([]bn254.ScalarField{one, two, three, four}) + f.CreateFromCoeffecitients(coeffs) + coeffsCopied := make(core.HostSlice[bn254.ScalarField], coeffs.Len()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsCopied) + assert.ElementsMatch(t, coeffs, coeffsCopied) + + var coeffsDevice core.DeviceSlice + coeffsDevice.Malloc(coeffs.Len()*one.Size(), one.Size()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsDevice) + coeffsHost := make(core.HostSlice[bn254.ScalarField], coeffs.Len()) + coeffsHost.CopyFromDevice(&coeffsDevice) + + assert.ElementsMatch(t, coeffs, coeffsHost) +} + +func TestPolyOddEvenSlicing(t *testing.T) { + size := 1<<10 - 3 + f := randomPoly(size) + + even := f.Even() + odd := f.Odd() + assert.Equal(t, f.Degree(), even.Degree()+odd.Degree()+1) + + x := rand() + var evenExpected, oddExpected bn254.ScalarField + for i := size; i >= 0; i-- { + if i%2 == 0 { + mul := vecOp(evenExpected, x, core.Mul) + evenExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } else { + mul := vecOp(oddExpected, x, core.Mul) + oddExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } + } + + evenEvaled := even.Eval(x) + assert.Equal(t, evenExpected, evenEvaled) + + oddEvaled := odd.Eval(x) + assert.Equal(t, oddExpected, oddEvaled) +} + +func TestPolynomialDivision(t *testing.T) { + // divide f(x)/g(x), compute q(x), r(x) and check f(x)=q(x)*g(x)+r(x) + var f, g polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements(bn254.GenerateScalars(1 << 4))) + g.CreateFromCoeffecitients(core.HostSliceFromElements(bn254.GenerateScalars(1 << 2))) + + q, r := f.Divide(&g) + + qMulG := q.Multiply(&g) + fRecon := qMulG.Add(&r) + + x := bn254.GenerateScalars(1)[0] + fEval := f.Eval(x) + fReconEval := fRecon.Eval(x) + assert.Equal(t, fEval, fReconEval) +} + +func TestDivideByVanishing(t *testing.T) { + // poly of x^4-1 vanishes ad 4th rou + var zero bn254.ScalarField + minus_one := vecOp(zero, one, core.Sub) + coeffs := core.HostSliceFromElements([]bn254.ScalarField{minus_one, zero, zero, zero, one}) // x^4-1 + var v polynomial.DensePolynomial + v.CreateFromCoeffecitients(coeffs) + + f := randomPoly(1 << 3) + + fv := f.Multiply(&v) + fDegree := f.Degree() + fvDegree := fv.Degree() + assert.Equal(t, fDegree+4, fvDegree) + + fReconstructed := fv.DivideByVanishing(4) + assert.Equal(t, fDegree, fReconstructed.Degree()) + + x := rand() + assert.Equal(t, f.Eval(x), fReconstructed.Eval(x)) +} + +// func TestPolySlice(t *testing.T) { +// size := 4 +// coeffs := bn254.GenerateScalars(size) +// var f DensePolynomial +// f.CreateFromCoeffecitients(coeffs) +// fSlice := f.AsSlice() +// assert.True(t, fSlice.IsOnDevice()) +// assert.Equal(t, size, fSlice.Len()) + +// hostSlice := make(core.HostSlice[bn254.ScalarField], size) +// hostSlice.CopyFromDevice(fSlice) +// assert.Equal(t, coeffs, hostSlice) + +// cfg := ntt.GetDefaultNttConfig() +// res := make(core.HostSlice[bn254.ScalarField], size) +// ntt.Ntt(fSlice, core.KForward, cfg, res) + +// assert.Equal(t, f.Eval(one), res[0]) +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go b/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go new file mode 100644 index 000000000..0564841f0 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go @@ -0,0 +1,42 @@ +package tests + +import ( + "testing" + + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/poseidon" +) + +func TestPoseidon(t *testing.T) { + + arity := 2 + numberOfStates := 1 + + cfg := poseidon.GetDefaultPoseidonConfig() + cfg.IsAsync = true + stream, _ := cr.CreateStream() + cfg.Ctx.Stream = &stream + + var constants core.PoseidonConstants[bn254.ScalarField] + + poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants + + scalars := bn254.GenerateScalars(numberOfStates * arity) + scalars[0] = scalars[0].Zero() + scalars[1] = scalars[0].Zero() + + scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function + + output := make(core.HostSlice[bn254.ScalarField], numberOfStates) + output.CopyFromDeviceAsync(&deviceOutput, stream) + +} diff --git a/wrappers/golang_v3/curves/bn254/tests/scalar_field_test.go b/wrappers/golang_v3/curves/bn254/tests/scalar_field_test.go new file mode 100644 index 000000000..ed119cda9 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/scalar_field_test.go @@ -0,0 +1,120 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + SCALAR_LIMBS = bn254.SCALAR_LIMBS +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := bn254.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := bn254.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField bn254.ScalarField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField bn254.ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField bn254.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField bn254.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField bn254.ScalarField + bytes, expected := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField bn254.ScalarField + expected, limbs := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestBn254GenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := bn254.GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := bn254.ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestBn254MongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := bn254.GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + bn254.ToMontgomery(&deviceScalars) + + scalarsMontHost := bn254.GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + bn254.FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang_v3/curves/bn254/tests/vec_ops_test.go b/wrappers/golang_v3/curves/bn254/tests/vec_ops_test.go new file mode 100644 index 000000000..20ed5e4c4 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/tests/vec_ops_test.go @@ -0,0 +1,69 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/vecOps" + "github.com/stretchr/testify/assert" +) + +func TestBn254VecOps(t *testing.T) { + testSize := 1 << 14 + + a := bn254.GenerateScalars(testSize) + b := bn254.GenerateScalars(testSize) + var scalar bn254.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[bn254.ScalarField], testSize) + out2 := make(core.HostSlice[bn254.ScalarField], testSize) + out3 := make(core.HostSlice[bn254.ScalarField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.VecOp(a, b, out, cfg, core.Add) + vecOps.VecOp(out, b, out2, cfg, core.Sub) + + assert.Equal(t, a, out2) + + vecOps.VecOp(a, ones, out3, cfg, core.Mul) + + assert.Equal(t, a, out3) +} + +func TestBn254Transpose(t *testing.T) { + rowSize := 1 << 6 + columnSize := 1 << 8 + onDevice := false + isAsync := false + + matrix := bn254.GenerateScalars(rowSize * columnSize) + + out := make(core.HostSlice[bn254.ScalarField], rowSize*columnSize) + out2 := make(core.HostSlice[bn254.ScalarField], rowSize*columnSize) + + ctx, _ := cr.GetDefaultDeviceContext() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + + assert.Equal(t, matrix, out2) + + var dMatrix, dOut, dOut2 core.DeviceSlice + onDevice = true + + matrix.CopyToDevice(&dMatrix, true) + dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + output := make(core.HostSlice[bn254.ScalarField], rowSize*columnSize) + output.CopyFromDevice(&dOut2) + + assert.Equal(t, matrix, output) +} diff --git a/wrappers/golang_v3/curves/bn254/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/bn254/vecOps/include/vec_ops.h new file mode 100644 index 000000000..5735fce5b --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/vecOps/include/vec_ops.h @@ -0,0 +1,53 @@ +#include +#include + +#ifndef _BN254_VEC_OPS_H +#define _BN254_VEC_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bn254_mul_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bn254_add_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bn254_sub_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bn254_transpose_matrix_cuda( + scalar_t* mat_in, + int row_size, + int column_size, + scalar_t* mat_out, + DeviceContext* ctx, + bool on_device, + bool is_async +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bn254/vecOps/vec_ops.go b/wrappers/golang_v3/curves/bn254/vecOps/vec_ops.go new file mode 100644 index 000000000..428f54968 --- /dev/null +++ b/wrappers/golang_v3/curves/bn254/vecOps/vec_ops.go @@ -0,0 +1,48 @@ +package vecOps + +// #cgo CFLAGS: -I./include/ +// #include "vec_ops.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + + "unsafe" +) + +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Sub: + ret = (cr.CudaError)(C.bn254_sub_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Add: + ret = (cr.CudaError)(C.bn254_add_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Mul: + ret = (cr.CudaError)(C.bn254_mul_cuda(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} + +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { + core.TransposeCheck(in, out, onDevice) + + cIn := (*C.scalar_t)(in.AsUnsafePointer()) + cOut := (*C.scalar_t)(out.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cRowSize := (C.int)(rowSize) + cColumnSize := (C.int)(columnSize) + cOnDevice := (C._Bool)(onDevice) + cIsAsync := (C._Bool)(isAsync) + + err := (cr.CudaError)(C.bn254_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bw6761/base_field.go b/wrappers/golang_v3/curves/bw6761/base_field.go new file mode 100644 index 000000000..b401e49d7 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/base_field.go @@ -0,0 +1,84 @@ +package bw6761 + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int = 24 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromUint32(v uint32) BaseField { + f.limbs[0] = v + return *f +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bw6761/curve.go b/wrappers/golang_v3/curves/bw6761/curve.go new file mode 100644 index 000000000..907971405 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/curve.go @@ -0,0 +1,177 @@ +package bw6761 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.bw6_761_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bw6_761_to_affine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bw6_761_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bw6_761_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go b/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go new file mode 100644 index 000000000..4bf2db434 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go @@ -0,0 +1,24 @@ +package ecntt + +// #cgo CFLAGS: -I./include/ +// #include "ecntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) + + cPoints := (*C.projective_t)(pointsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.projective_t)(resultsPointer) + + __ret := C.bw6_761_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bw6761/ecntt/include/ecntt.h b/wrappers/golang_v3/curves/bw6761/ecntt/include/ecntt.h new file mode 100644 index 000000000..9c0cf0eff --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/ecntt/include/ecntt.h @@ -0,0 +1,19 @@ +#include + +#ifndef _BW6_761_ECNTT_H +#define _BW6_761_ECNTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NTTConfig NTTConfig; +typedef struct projective_t projective_t; + +cudaError_t bw6_761_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bw6761/g2/curve.go b/wrappers/golang_v3/curves/bw6761/g2/curve.go new file mode 100644 index 000000000..4167674ef --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/g2/curve.go @@ -0,0 +1,177 @@ +package g2 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bw6_761_g2_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bw6_761_g2_to_affine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bw6_761_g2_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bw6_761_g2_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bw6761/g2/g2base_field.go b/wrappers/golang_v3/curves/bw6761/g2/g2base_field.go new file mode 100644 index 000000000..c4073af97 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/g2/g2base_field.go @@ -0,0 +1,84 @@ +package g2 + +import ( + "encoding/binary" + "fmt" +) + +const ( + G2BASE_LIMBS int = 24 +) + +type G2BaseField struct { + limbs [G2BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromUint32(v uint32) G2BaseField { + f.limbs[0] = v + return *f +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bw6761/g2/include/curve.h b/wrappers/golang_v3/curves/bw6761/g2/include/curve.h new file mode 100644 index 000000000..b57b55cfc --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/g2/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _BW6_761_G2CURVE_H +#define _BW6_761_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct g2_projective_t g2_projective_t; +typedef struct g2_affine_t g2_affine_t; +typedef struct DeviceContext DeviceContext; + +bool bw6_761_g2_eq(g2_projective_t* point1, g2_projective_t* point2); +void bw6_761_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); +void bw6_761_g2_generate_projective_points(g2_projective_t* points, int size); +void bw6_761_g2_generate_affine_points(g2_affine_t* points, int size); +cudaError_t bw6_761_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bw6_761_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bw6761/g2/include/msm.h b/wrappers/golang_v3/curves/bw6761/g2/include/msm.h new file mode 100644 index 000000000..3c0ff4cad --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/g2/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BW6_761_G2MSM_H +#define _BW6_761_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct g2_projective_t g2_projective_t; +typedef struct g2_affine_t g2_affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bw6_761_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); +cudaError_t bw6_761_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out); +cudaError_t bw6_761_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bw6761/g2/include/scalar_field.h b/wrappers/golang_v3/curves/bw6761/g2/include/scalar_field.h new file mode 100644 index 000000000..4a4800789 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/g2/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BW6_761_FIELD_H +#define _BW6_761_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void bw6_761_generate_scalars(scalar_t* scalars, int size); +cudaError_t bw6_761_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bw6761/g2/msm.go b/wrappers/golang_v3/curves/bw6761/g2/msm.go new file mode 100644 index 000000000..8a7a57cb0 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/g2/msm.go @@ -0,0 +1,63 @@ +package g2 + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.g2_affine_t)(pointsPointer) + cResults := (*C.g2_projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.bw6_761_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: G2PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// G2PrecomputePoints should be used instead. +func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := G2GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.g2_affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bw6_761_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.g2_affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bw6_761_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bw6761/include/curve.h b/wrappers/golang_v3/curves/bw6761/include/curve.h new file mode 100644 index 000000000..cc6e401cb --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _BW6_761_CURVE_H +#define _BW6_761_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct DeviceContext DeviceContext; + +bool bw6_761_eq(projective_t* point1, projective_t* point2); +void bw6_761_to_affine(projective_t* point, affine_t* point_out); +void bw6_761_generate_projective_points(projective_t* points, int size); +void bw6_761_generate_affine_points(affine_t* points, int size); +cudaError_t bw6_761_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bw6_761_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bw6761/include/scalar_field.h b/wrappers/golang_v3/curves/bw6761/include/scalar_field.h new file mode 100644 index 000000000..4a4800789 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BW6_761_FIELD_H +#define _BW6_761_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void bw6_761_generate_scalars(scalar_t* scalars, int size); +cudaError_t bw6_761_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bw6761/main.go b/wrappers/golang_v3/curves/bw6761/main.go new file mode 100644 index 000000000..9e7f9462c --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/main.go @@ -0,0 +1,4 @@ +package bw6761 + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bw6_761 -lingo_field_bw6_761 -lstdc++ -lm +import "C" diff --git a/wrappers/golang_v3/curves/bw6761/msm/include/msm.h b/wrappers/golang_v3/curves/bw6761/msm/include/msm.h new file mode 100644 index 000000000..883917079 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/msm/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BW6_761_MSM_H +#define _BW6_761_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bw6_761_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); +cudaError_t bw6_761_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); +cudaError_t bw6_761_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bw6761/msm/msm.go b/wrappers/golang_v3/curves/bw6761/msm/msm.go new file mode 100644 index 000000000..5fd9e0c76 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/msm/msm.go @@ -0,0 +1,63 @@ +package msm + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.affine_t)(pointsPointer) + cResults := (*C.projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.bw6_761_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// PrecomputePoints should be used instead. +func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.bw6_761_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.bw6_761_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bw6761/ntt/include/ntt.h b/wrappers/golang_v3/curves/bw6761/ntt/include/ntt.h new file mode 100644 index 000000000..aea1223e4 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/ntt/include/ntt.h @@ -0,0 +1,23 @@ +#include +#include + +#ifndef _BW6_761_NTT_H +#define _BW6_761_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct NTTConfig NTTConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bw6_761_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t bw6_761_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); +cudaError_t bw6_761_release_domain(DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bw6761/ntt/ntt.go b/wrappers/golang_v3/curves/bw6761/ntt/ntt.go new file mode 100644 index 000000000..297049e19 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/ntt/ntt.go @@ -0,0 +1,56 @@ +package ntt + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" +) + +import ( + "unsafe" +) + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.bw6_761_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func GetDefaultNttConfig() core.NTTConfig[[bw6_761.SCALAR_LIMBS]uint32] { + cosetGenField := bw6_761.ScalarField{} + cosetGenField.One() + var cosetGen [bw6_761.SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func InitDomain(primitiveRoot bw6_761.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.bw6_761_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + __ret := C.bw6_761_release_domain(cCtx) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bw6761/polynomial/include/polynomial.h b/wrappers/golang_v3/curves/bw6761/polynomial/include/polynomial.h new file mode 100644 index 000000000..2568e51fc --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/polynomial/include/polynomial.h @@ -0,0 +1,51 @@ +#include +#include + +#ifndef _BW6_761_POLY_H +#define _BW6_761_POLY_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PolynomialInst PolynomialInst; +typedef struct IntegrityPointer IntegrityPointer; + +bool bw6_761_polynomial_init_cuda_backend(); +PolynomialInst* bw6_761_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); +PolynomialInst* bw6_761_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); +PolynomialInst* bw6_761_polynomial_clone(const PolynomialInst* p); +void bw6_761_polynomial_print(PolynomialInst* p); +void bw6_761_polynomial_delete(PolynomialInst* instance); +PolynomialInst* bw6_761_polynomial_add(const PolynomialInst* a, const PolynomialInst* b); +void bw6_761_polynomial_add_inplace(PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bw6_761_polynomial_subtract(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bw6_761_polynomial_multiply(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bw6_761_polynomial_multiply_by_scalar(const PolynomialInst* a, const scalar_t* scalar); +void bw6_761_polynomial_division(const PolynomialInst* a, const PolynomialInst* b, PolynomialInst** q /*OUT*/, PolynomialInst** r /*OUT*/); +PolynomialInst* bw6_761_polynomial_quotient(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bw6_761_polynomial_remainder(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* bw6_761_polynomial_divide_by_vanishing(const PolynomialInst* p, size_t vanishing_poly_degree); +void bw6_761_polynomial_add_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void bw6_761_polynomial_sub_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void bw6_761_polynomial_evaluate_on_domain(const PolynomialInst* p, scalar_t* domain, size_t domain_size, scalar_t* evals /*OUT*/); +size_t bw6_761_polynomial_degree(PolynomialInst* p); +size_t bw6_761_polynomial_copy_coeffs_range(PolynomialInst* p, scalar_t* memory, size_t start_idx, size_t end_idx); +PolynomialInst* bw6_761_polynomial_even(PolynomialInst* p); +PolynomialInst* bw6_761_polynomial_odd(PolynomialInst* p); + +// scalar_t* bw6_761_polynomial_get_coeffs_raw_ptr(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// PolynomialInst* bw6_761_polynomial_slice(PolynomialInst* p, size_t offset, size_t stride, size_t size); +// IntegrityPointer* bw6_761_polynomial_get_coeff_view(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// IntegrityPointer* bw6_761_polynomial_get_rou_evaluations_view(PolynomialInst* p, size_t nof_evals, bool is_reversed, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// const scalar_t* bw6_761_polynomial_intergrity_ptr_get(IntegrityPointer* p); +// bool bw6_761_polynomial_intergrity_ptr_is_valid(IntegrityPointer* p); +// void bw6_761_polynomial_intergrity_ptr_destroy(IntegrityPointer* p); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/wrappers/golang_v3/curves/bw6761/polynomial/polynomial.go b/wrappers/golang_v3/curves/bw6761/polynomial/polynomial.go new file mode 100644 index 000000000..49626f731 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/polynomial/polynomial.go @@ -0,0 +1,176 @@ +package polynomial + +// #cgo CFLAGS: -I./include/ +// #include "polynomial.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" +) + +type PolynomialHandle = C.struct_PolynomialInst + +type DensePolynomial struct { + handle *PolynomialHandle +} + +func InitPolyBackend() bool { + return (bool)(C.bw6_761_polynomial_init_cuda_backend()) +} + +func (up *DensePolynomial) Print() { + C.bw6_761_polynomial_print(up.handle) +} + +func (up *DensePolynomial) CreateFromCoeffecitients(coeffs core.HostOrDeviceSlice) DensePolynomial { + if coeffs.IsOnDevice() { + coeffs.(core.DeviceSlice).CheckDevice() + } + coeffsPointer := (*C.scalar_t)(coeffs.AsUnsafePointer()) + cSize := (C.size_t)(coeffs.Len()) + up.handle = C.bw6_761_polynomial_create_from_coefficients(coeffsPointer, cSize) + return *up +} + +func (up *DensePolynomial) CreateFromROUEvaluations(evals core.HostOrDeviceSlice) DensePolynomial { + evalsPointer := (*C.scalar_t)(evals.AsUnsafePointer()) + cSize := (C.size_t)(evals.Len()) + up.handle = C.bw6_761_polynomial_create_from_coefficients(evalsPointer, cSize) + return *up +} + +func (up *DensePolynomial) Clone() DensePolynomial { + return DensePolynomial{ + handle: C.bw6_761_polynomial_clone(up.handle), + } +} + +// TODO @jeremyfelder: Maybe this should be in a SetFinalizer that is set on Create functions? +func (up *DensePolynomial) Delete() { + C.bw6_761_polynomial_delete(up.handle) +} + +func (up *DensePolynomial) Add(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bw6_761_polynomial_add(up.handle, b.handle), + } +} + +func (up *DensePolynomial) AddInplace(b *DensePolynomial) { + C.bw6_761_polynomial_add_inplace(up.handle, b.handle) +} + +func (up *DensePolynomial) Subtract(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bw6_761_polynomial_subtract(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Multiply(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bw6_761_polynomial_multiply(up.handle, b.handle), + } +} + +func (up *DensePolynomial) MultiplyByScalar(scalar bw6_761.ScalarField) DensePolynomial { + cScalar := (*C.scalar_t)(unsafe.Pointer(scalar.AsPointer())) + return DensePolynomial{ + handle: C.bw6_761_polynomial_multiply_by_scalar(up.handle, cScalar), + } +} + +func (up *DensePolynomial) Divide(b *DensePolynomial) (DensePolynomial, DensePolynomial) { + var q, r *PolynomialHandle + C.bw6_761_polynomial_division(up.handle, b.handle, &q, &r) + return DensePolynomial{ + handle: q, + }, DensePolynomial{ + handle: r, + } +} + +func (up *DensePolynomial) Quotient(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bw6_761_polynomial_quotient(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Remainder(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.bw6_761_polynomial_remainder(up.handle, b.handle), + } +} + +func (up *DensePolynomial) DivideByVanishing(vanishing_degree uint64) DensePolynomial { + cVanishingDegree := (C.ulong)(vanishing_degree) + return DensePolynomial{ + handle: C.bw6_761_polynomial_divide_by_vanishing(up.handle, cVanishingDegree), + } +} + +func (up *DensePolynomial) AddMonomial(monomialCoeff bw6_761.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]bw6_761.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.bw6_761_polynomial_add_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) SubMonomial(monomialCoeff bw6_761.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]bw6_761.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.bw6_761_polynomial_sub_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) Eval(x bw6_761.ScalarField) bw6_761.ScalarField { + domains := make(core.HostSlice[bw6_761.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[bw6_761.ScalarField], 1) + up.EvalOnDomain(domains, evals) + return evals[0] +} + +func (up *DensePolynomial) EvalOnDomain(domain, evals core.HostOrDeviceSlice) core.HostOrDeviceSlice { + cDomain := (*C.scalar_t)(domain.AsUnsafePointer()) + cDomainSize := (C.size_t)(domain.Len()) + cEvals := (*C.scalar_t)(evals.AsUnsafePointer()) + C.bw6_761_polynomial_evaluate_on_domain(up.handle, cDomain, cDomainSize, cEvals) + return evals +} + +func (up *DensePolynomial) Degree() int { + return int(C.bw6_761_polynomial_degree(up.handle)) +} + +func (up *DensePolynomial) CopyCoeffsRange(start, end int, out core.HostOrDeviceSlice) (int, core.HostOrDeviceSlice) { + cStart := (C.size_t)(start) + cEnd := (C.size_t)(end) + cScalarOut := (*C.scalar_t)(out.AsUnsafePointer()) + __cNumCoeffsRead := C.bw6_761_polynomial_copy_coeffs_range(up.handle, cScalarOut, cStart, cEnd) + return int(__cNumCoeffsRead), out +} + +func (up *DensePolynomial) GetCoeff(idx int) bw6_761.ScalarField { + out := make(core.HostSlice[bw6_761.ScalarField], 1) + up.CopyCoeffsRange(idx, idx, out) + return out[0] +} + +func (up *DensePolynomial) Even() DensePolynomial { + evenPoly := C.bw6_761_polynomial_even(up.handle) + return DensePolynomial{ + handle: evenPoly, + } +} + +func (up *DensePolynomial) Odd() DensePolynomial { + oddPoly := C.bw6_761_polynomial_odd(up.handle) + return DensePolynomial{ + handle: oddPoly, + } +} diff --git a/wrappers/golang_v3/curves/bw6761/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/bw6761/poseidon/include/poseidon.h new file mode 100644 index 000000000..1731d1058 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/poseidon/include/poseidon.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _BW6_761_POSEIDON_H +#define _BW6_761_POSEIDON_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PoseidonConfig PoseidonConfig; +typedef struct DeviceContext DeviceContext; +typedef struct PoseidonConstants PoseidonConstants; + + +cudaError_t bw6_761_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); +cudaError_t bw6_761_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); +cudaError_t bw6_761_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go b/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go new file mode 100644 index 000000000..3ffe21ea2 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go @@ -0,0 +1,57 @@ +package poseidon + +// #cgo CFLAGS: -I./include/ +// #include "poseidon.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func GetDefaultPoseidonConfig() core.PoseidonConfig { + return core.GetDefaultPoseidonConfig() +} + +func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { + scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) + + cScalars := (*C.scalar_t)(scalarsPointer) + cResults := (*C.scalar_t)(resultsPointer) + cNumberOfStates := (C.int)(numberOfStates) + cArity := (C.int)(constants.Arity) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + cCfg := (*C.PoseidonConfig)(cfgPointer) + + __ret := C.bw6_761_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) + + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cFullRoundsHalfs := (C.int)(fullRoundsHalfs) + cPartialRounds := (C.int)(partialRounds) + cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) + + __ret := C.bw6_761_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + + __ret := C.bw6_761_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/bw6761/scalar_field.go b/wrappers/golang_v3/curves/bw6761/scalar_field.go new file mode 100644 index 000000000..d02566f31 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/scalar_field.go @@ -0,0 +1,121 @@ +package bw6761 + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int = 12 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromUint32(v uint32) ScalarField { + f.limbs[0] = v + return *f +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalarSlice := make(core.HostSlice[ScalarField], size) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.bw6_761_generate_scalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/base_field_test.go b/wrappers/golang_v3/curves/bw6761/tests/base_field_test.go new file mode 100644 index 000000000..1c340ce3e --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + BASE_LIMBS = bw6_761.BASE_LIMBS +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := bw6_761.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := bw6_761.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField bw6_761.BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField bw6_761.BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField bw6_761.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField bw6_761.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField bw6_761.BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField bw6_761.BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/curve_test.go b/wrappers/golang_v3/curves/bw6761/tests/curve_test.go new file mode 100644 index 000000000..0f90cf2d7 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = bw6_761.BaseField{} + + var affineZero bw6_761.Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var affine bw6_761.Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var affine bw6_761.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bw6_761.BaseField + fieldOne.One() + + var expected bw6_761.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bw6_761.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero bw6_761.Projective + projectiveZero.Zero() + var fieldZero = bw6_761.BaseField{} + var fieldOne bw6_761.BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var projective bw6_761.Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var projective bw6_761.Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bw6_761.BaseField + fieldOne.One() + + var expected bw6_761.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bw6_761.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint bw6_761.Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go b/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go new file mode 100644 index 000000000..0a90035c9 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go @@ -0,0 +1,30 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt" + "github.com/stretchr/testify/assert" +) + +func TestECNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + points := bw6_761.GenerateProjectivePoints(1 << largestTestSize) + + for _, size := range []int{4, 5, 6, 7, 8} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + pointsCopy := core.HostSliceFromElements[bw6_761.Projective](points[:testSize]) + cfg.Ordering = v + cfg.NttAlgorithm = core.Radix2 + + output := make(core.HostSlice[bw6_761.Projective], testSize) + e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + } + } +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go new file mode 100644 index 000000000..e64a3ca45 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = g2.G2BaseField{} + + var affineZero g2.G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var affine g2.G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero g2.G2Projective + projectiveZero.Zero() + var fieldZero = g2.G2BaseField{} + var fieldOne g2.G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint g2.G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_g2base_field_test.go new file mode 100644 index 000000000..6f4429ff5 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_g2base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + G2BASE_LIMBS = bw6_761.G2BASE_LIMBS +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := bw6_761.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := bw6_761.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField bw6_761.G2BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField bw6_761.G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField bw6_761.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField bw6_761.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField bw6_761.G2BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField bw6_761.G2BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go new file mode 100644 index 000000000..8a886d767 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go @@ -0,0 +1,331 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bw6-761" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleBw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/g2" +) + +func projectiveToGnarkAffineG2(p g2.G2Projective) bw6761.G2Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bw6761.G2Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBw6_761.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bw6761.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bw6761.G2Affine], out g2.G2Projective) bool { + var msmRes bw6761.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bw6761.G2Jac + proj := projectiveToGnarkAffineG2(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func convertIcicleAffineToG2Affine(iciclePoints []g2.G2Affine) []bw6761.G2Affine { + points := make([]bw6761.G2Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes]byte)(iciclePoint.X.ToBytesLittleEndian()) + fpXElem, _ := fp.LittleEndian.Element(&xBytes) + + yBytes := ([fp.Bytes]byte)(iciclePoint.Y.ToBytesLittleEndian()) + fpYElem, _ := fp.LittleEndian.Element(&yBytes) + points[index] = bw6761.G2Affine{ + X: fpXElem, + Y: fpYElem, + } + } + + return points +} + +func TestMSMG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBw6_761.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + + } +} + +func TestMSMG2PinnedHostMemory(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleBw6_761.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[g2.G2Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + + if pinnableAndLockable { + e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +func TestMSMG2GnarkCryptoTypes(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := g2.G2GenerateAffinePoints(size) + pointsGnark := convertIcicleAffineToG2Affine(points) + pointsHost := (core.HostSlice[bw6761.G2Affine])(pointsGnark) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBw6_761.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestPrecomputePointsG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBw6_761.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBw6_761.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := g2.G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} + +func TestMSMG2MultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBw6_761.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/main_test.go b/wrappers/golang_v3/curves/bw6761/tests/main_test.go new file mode 100644 index 000000000..48d0499fc --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/main_test.go @@ -0,0 +1,48 @@ +package tests + +import ( + "os" + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt" + poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/polynomial" + + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/fft" +) + +const ( + largestTestSize = 20 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := bw6_761.ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + return e +} + +func TestMain(m *testing.M) { + poly.InitPolyBackend() + + // setup domain + cfg := ntt.GetDefaultNttConfig() + e := initDomain(largestTestSize, cfg) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("initDomain failed") + } + + // execute tests + os.Exit(m.Run()) + + // release domain + e = ntt.ReleaseDomain(cfg.Ctx) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("ReleaseDomain failed") + } +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go new file mode 100644 index 000000000..4169eb250 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go @@ -0,0 +1,331 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bw6-761" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleBw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/msm" +) + +func projectiveToGnarkAffine(p icicleBw6_761.Projective) bw6761.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bw6761.G1Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBw6_761.ScalarField], points core.HostSlice[icicleBw6_761.Affine], out icicleBw6_761.Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bw6761.G1Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bw6761.G1Affine], out icicleBw6_761.Projective) bool { + var msmRes bw6761.G1Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bw6761.G1Jac + proj := projectiveToGnarkAffine(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func convertIcicleAffineToG1Affine(iciclePoints []icicleBw6_761.Affine) []bw6761.G1Affine { + points := make([]bw6761.G1Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes]byte)(iciclePoint.X.ToBytesLittleEndian()) + fpXElem, _ := fp.LittleEndian.Element(&xBytes) + + yBytes := ([fp.Bytes]byte)(iciclePoint.Y.ToBytesLittleEndian()) + fpYElem, _ := fp.LittleEndian.Element(&yBytes) + points[index] = bw6761.G1Affine{ + X: fpXElem, + Y: fpYElem, + } + } + + return points +} + +func TestMSM(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBw6_761.GenerateScalars(size) + points := icicleBw6_761.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleBw6_761.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + + } +} + +func TestMSMPinnedHostMemory(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleBw6_761.GenerateScalars(size) + points := icicleBw6_761.GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[icicleBw6_761.Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p icicleBw6_761.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + + if pinnableAndLockable { + e = msm.Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +func TestMSMGnarkCryptoTypes(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := icicleBw6_761.GenerateAffinePoints(size) + pointsGnark := convertIcicleAffineToG1Affine(points) + pointsHost := (core.HostSlice[bw6761.G1Affine])(pointsGnark) + + var p icicleBw6_761.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = msm.Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} + +func TestMSMBatch(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBw6_761.GenerateScalars(totalSize) + points := icicleBw6_761.GenerateAffinePoints(totalSize) + + var p icicleBw6_761.Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBw6_761.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestPrecomputePoints(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleBw6_761.GenerateScalars(totalSize) + points := icicleBw6_761.GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p icicleBw6_761.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[icicleBw6_761.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleBw6_761.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := icicleBw6_761.GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p icicleBw6_761.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} + +func TestMSMMultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBw6_761.GenerateScalars(size) + points := icicleBw6_761.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleBw6_761.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go b/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go new file mode 100644 index 000000000..3552a2a8b --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go @@ -0,0 +1,263 @@ +package tests + +import ( + "reflect" + "testing" + + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/fft" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" +) + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bw6_761.ScalarField], output core.HostSlice[bw6_761.ScalarField], order core.Ordering, direction core.NTTDir) bool { + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) +} + +func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} +func TestNTTGetDefaultConfig(t *testing.T) { + actual := ntt.GetDefaultNttConfig() + expected := test_helpers.GenerateLimbOne(int(bw6_761.SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := bw6_761.ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := bw6_761.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[bw6_761.ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[bw6_761.ScalarField], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} +func TestNttFrElement(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := make([]fr.Element, 4) + var x fr.Element + for i := 0; i < 4; i++ { + x.SetRandom() + scalars[i] = x + } + + for _, size := range []int{4} { + for _, v := range [1]core.Ordering{core.KNN} { + testSize := size + + scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[fr.Element], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := bw6_761.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[bw6_761.ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[bw6_761.ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + largestTestSize := 12 + largestBatchSize := 100 + scalars := bw6_761.GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{2, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[bw6_761.ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[bw6_761.ScalarField], totalSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +func TestReleaseDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + e := ntt.ReleaseDomain(cfg.Ctx) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := ntt.GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang_v3/curves/bw6761/tests/polynomial_test.go b/wrappers/golang_v3/curves/bw6761/tests/polynomial_test.go new file mode 100644 index 000000000..5bb3f1712 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/polynomial_test.go @@ -0,0 +1,229 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/vecOps" + "github.com/stretchr/testify/assert" +) + +var one, two, three, four, five bw6_761.ScalarField + +func init() { + one.One() + two.FromUint32(2) + three.FromUint32(3) + four.FromUint32(4) + five.FromUint32(5) +} + +func rand() bw6_761.ScalarField { + return bw6_761.GenerateScalars(1)[0] +} + +func randomPoly(size int) (f polynomial.DensePolynomial) { + f.CreateFromCoeffecitients(core.HostSliceFromElements(bw6_761.GenerateScalars(size))) + return f +} + +func vecOp(a, b bw6_761.ScalarField, op core.VecOps) bw6_761.ScalarField { + ahost := core.HostSliceWithValue(a, 1) + bhost := core.HostSliceWithValue(b, 1) + out := make(core.HostSlice[bw6_761.ScalarField], 1) + + cfg := core.DefaultVecOpsConfig() + vecOps.VecOp(ahost, bhost, out, cfg, op) + return out[0] +} + +func TestPolyCreateFromCoefficients(t *testing.T) { + scalars := bw6_761.GenerateScalars(33) + var uniPoly polynomial.DensePolynomial + + poly := uniPoly.CreateFromCoeffecitients(scalars) + poly.Print() +} + +func TestPolyEval(t *testing.T) { + // testing correct evaluation of f(8) for f(x)=4x^2+2x+5 + coeffs := core.HostSliceFromElements([]bw6_761.ScalarField{five, two, four}) + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(coeffs) + + var x bw6_761.ScalarField + x.FromUint32(8) + domains := make(core.HostSlice[bw6_761.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[bw6_761.ScalarField], 1) + fEvaled := f.EvalOnDomain(domains, evals) + var expected bw6_761.ScalarField + assert.Equal(t, expected.FromUint32(277), fEvaled.(core.HostSlice[bw6_761.ScalarField])[0]) +} + +func TestPolyClone(t *testing.T) { + f := randomPoly(8) + x := rand() + fx := f.Eval(x) + + g := f.Clone() + fg := f.Add(&g) + + gx := g.Eval(x) + fgx := fg.Eval(x) + + assert.Equal(t, fx, gx) + assert.Equal(t, vecOp(fx, gx, core.Add), fgx) +} + +func TestPolyAddSubMul(t *testing.T) { + testSize := 1 << 10 + f := randomPoly(testSize) + g := randomPoly(testSize) + x := rand() + + fx := f.Eval(x) + gx := g.Eval(x) + + polyAdd := f.Add(&g) + fxAddgx := vecOp(fx, gx, core.Add) + assert.Equal(t, polyAdd.Eval(x), fxAddgx) + + polySub := f.Subtract(&g) + fxSubgx := vecOp(fx, gx, core.Sub) + assert.Equal(t, polySub.Eval(x), fxSubgx) + + polyMul := f.Multiply(&g) + fxMulgx := vecOp(fx, gx, core.Mul) + assert.Equal(t, polyMul.Eval(x), fxMulgx) + + s1 := rand() + polMulS1 := f.MultiplyByScalar(s1) + assert.Equal(t, polMulS1.Eval(x), vecOp(fx, s1, core.Mul)) + + s2 := rand() + polMulS2 := f.MultiplyByScalar(s2) + assert.Equal(t, polMulS2.Eval(x), vecOp(fx, s2, core.Mul)) +} + +func TestPolyMonomials(t *testing.T) { + var zero bw6_761.ScalarField + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements([]bw6_761.ScalarField{one, zero, two})) + x := rand() + + fx := f.Eval(x) + f.AddMonomial(three, 1) + fxAdded := f.Eval(x) + assert.Equal(t, fxAdded, vecOp(fx, vecOp(three, x, core.Mul), core.Add)) + + f.SubMonomial(one, 0) + fxSub := f.Eval(x) + assert.Equal(t, fxSub, vecOp(fxAdded, one, core.Sub)) +} + +func TestPolyReadCoeffs(t *testing.T) { + var f polynomial.DensePolynomial + coeffs := core.HostSliceFromElements([]bw6_761.ScalarField{one, two, three, four}) + f.CreateFromCoeffecitients(coeffs) + coeffsCopied := make(core.HostSlice[bw6_761.ScalarField], coeffs.Len()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsCopied) + assert.ElementsMatch(t, coeffs, coeffsCopied) + + var coeffsDevice core.DeviceSlice + coeffsDevice.Malloc(coeffs.Len()*one.Size(), one.Size()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsDevice) + coeffsHost := make(core.HostSlice[bw6_761.ScalarField], coeffs.Len()) + coeffsHost.CopyFromDevice(&coeffsDevice) + + assert.ElementsMatch(t, coeffs, coeffsHost) +} + +func TestPolyOddEvenSlicing(t *testing.T) { + size := 1<<10 - 3 + f := randomPoly(size) + + even := f.Even() + odd := f.Odd() + assert.Equal(t, f.Degree(), even.Degree()+odd.Degree()+1) + + x := rand() + var evenExpected, oddExpected bw6_761.ScalarField + for i := size; i >= 0; i-- { + if i%2 == 0 { + mul := vecOp(evenExpected, x, core.Mul) + evenExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } else { + mul := vecOp(oddExpected, x, core.Mul) + oddExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } + } + + evenEvaled := even.Eval(x) + assert.Equal(t, evenExpected, evenEvaled) + + oddEvaled := odd.Eval(x) + assert.Equal(t, oddExpected, oddEvaled) +} + +func TestPolynomialDivision(t *testing.T) { + // divide f(x)/g(x), compute q(x), r(x) and check f(x)=q(x)*g(x)+r(x) + var f, g polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements(bw6_761.GenerateScalars(1 << 4))) + g.CreateFromCoeffecitients(core.HostSliceFromElements(bw6_761.GenerateScalars(1 << 2))) + + q, r := f.Divide(&g) + + qMulG := q.Multiply(&g) + fRecon := qMulG.Add(&r) + + x := bw6_761.GenerateScalars(1)[0] + fEval := f.Eval(x) + fReconEval := fRecon.Eval(x) + assert.Equal(t, fEval, fReconEval) +} + +func TestDivideByVanishing(t *testing.T) { + // poly of x^4-1 vanishes ad 4th rou + var zero bw6_761.ScalarField + minus_one := vecOp(zero, one, core.Sub) + coeffs := core.HostSliceFromElements([]bw6_761.ScalarField{minus_one, zero, zero, zero, one}) // x^4-1 + var v polynomial.DensePolynomial + v.CreateFromCoeffecitients(coeffs) + + f := randomPoly(1 << 3) + + fv := f.Multiply(&v) + fDegree := f.Degree() + fvDegree := fv.Degree() + assert.Equal(t, fDegree+4, fvDegree) + + fReconstructed := fv.DivideByVanishing(4) + assert.Equal(t, fDegree, fReconstructed.Degree()) + + x := rand() + assert.Equal(t, f.Eval(x), fReconstructed.Eval(x)) +} + +// func TestPolySlice(t *testing.T) { +// size := 4 +// coeffs := bw6_761.GenerateScalars(size) +// var f DensePolynomial +// f.CreateFromCoeffecitients(coeffs) +// fSlice := f.AsSlice() +// assert.True(t, fSlice.IsOnDevice()) +// assert.Equal(t, size, fSlice.Len()) + +// hostSlice := make(core.HostSlice[bw6_761.ScalarField], size) +// hostSlice.CopyFromDevice(fSlice) +// assert.Equal(t, coeffs, hostSlice) + +// cfg := ntt.GetDefaultNttConfig() +// res := make(core.HostSlice[bw6_761.ScalarField], size) +// ntt.Ntt(fSlice, core.KForward, cfg, res) + +// assert.Equal(t, f.Eval(one), res[0]) +// } diff --git a/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go b/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go new file mode 100644 index 000000000..b1ab540ca --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go @@ -0,0 +1,42 @@ +package tests + +import ( + "testing" + + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/poseidon" +) + +func TestPoseidon(t *testing.T) { + + arity := 2 + numberOfStates := 1 + + cfg := poseidon.GetDefaultPoseidonConfig() + cfg.IsAsync = true + stream, _ := cr.CreateStream() + cfg.Ctx.Stream = &stream + + var constants core.PoseidonConstants[bw6_761.ScalarField] + + poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants + + scalars := bw6_761.GenerateScalars(numberOfStates * arity) + scalars[0] = scalars[0].Zero() + scalars[1] = scalars[0].Zero() + + scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function + + output := make(core.HostSlice[bw6_761.ScalarField], numberOfStates) + output.CopyFromDeviceAsync(&deviceOutput, stream) + +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/scalar_field_test.go b/wrappers/golang_v3/curves/bw6761/tests/scalar_field_test.go new file mode 100644 index 000000000..0a8a835e7 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/scalar_field_test.go @@ -0,0 +1,120 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + SCALAR_LIMBS = bw6_761.SCALAR_LIMBS +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := bw6_761.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := bw6_761.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField bw6_761.ScalarField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField bw6_761.ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField bw6_761.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField bw6_761.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField bw6_761.ScalarField + bytes, expected := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField bw6_761.ScalarField + expected, limbs := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestBw6_761GenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := bw6_761.GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := bw6_761.ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestBw6_761MongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := bw6_761.GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + bw6_761.ToMontgomery(&deviceScalars) + + scalarsMontHost := bw6_761.GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + bw6_761.FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang_v3/curves/bw6761/tests/vec_ops_test.go b/wrappers/golang_v3/curves/bw6761/tests/vec_ops_test.go new file mode 100644 index 000000000..bd6802809 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/tests/vec_ops_test.go @@ -0,0 +1,69 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/vecOps" + "github.com/stretchr/testify/assert" +) + +func TestBw6_761VecOps(t *testing.T) { + testSize := 1 << 14 + + a := bw6_761.GenerateScalars(testSize) + b := bw6_761.GenerateScalars(testSize) + var scalar bw6_761.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[bw6_761.ScalarField], testSize) + out2 := make(core.HostSlice[bw6_761.ScalarField], testSize) + out3 := make(core.HostSlice[bw6_761.ScalarField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.VecOp(a, b, out, cfg, core.Add) + vecOps.VecOp(out, b, out2, cfg, core.Sub) + + assert.Equal(t, a, out2) + + vecOps.VecOp(a, ones, out3, cfg, core.Mul) + + assert.Equal(t, a, out3) +} + +func TestBw6_761Transpose(t *testing.T) { + rowSize := 1 << 6 + columnSize := 1 << 8 + onDevice := false + isAsync := false + + matrix := bw6_761.GenerateScalars(rowSize * columnSize) + + out := make(core.HostSlice[bw6_761.ScalarField], rowSize*columnSize) + out2 := make(core.HostSlice[bw6_761.ScalarField], rowSize*columnSize) + + ctx, _ := cr.GetDefaultDeviceContext() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + + assert.Equal(t, matrix, out2) + + var dMatrix, dOut, dOut2 core.DeviceSlice + onDevice = true + + matrix.CopyToDevice(&dMatrix, true) + dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + output := make(core.HostSlice[bw6_761.ScalarField], rowSize*columnSize) + output.CopyFromDevice(&dOut2) + + assert.Equal(t, matrix, output) +} diff --git a/wrappers/golang_v3/curves/bw6761/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/bw6761/vecOps/include/vec_ops.h new file mode 100644 index 000000000..86bda7e30 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/vecOps/include/vec_ops.h @@ -0,0 +1,53 @@ +#include +#include + +#ifndef _BW6_761_VEC_OPS_H +#define _BW6_761_VEC_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t bw6_761_mul_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bw6_761_add_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bw6_761_sub_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t bw6_761_transpose_matrix_cuda( + scalar_t* mat_in, + int row_size, + int column_size, + scalar_t* mat_out, + DeviceContext* ctx, + bool on_device, + bool is_async +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/bw6761/vecOps/vec_ops.go b/wrappers/golang_v3/curves/bw6761/vecOps/vec_ops.go new file mode 100644 index 000000000..ad40566d8 --- /dev/null +++ b/wrappers/golang_v3/curves/bw6761/vecOps/vec_ops.go @@ -0,0 +1,48 @@ +package vecOps + +// #cgo CFLAGS: -I./include/ +// #include "vec_ops.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + + "unsafe" +) + +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Sub: + ret = (cr.CudaError)(C.bw6_761_sub_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Add: + ret = (cr.CudaError)(C.bw6_761_add_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Mul: + ret = (cr.CudaError)(C.bw6_761_mul_cuda(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} + +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { + core.TransposeCheck(in, out, onDevice) + + cIn := (*C.scalar_t)(in.AsUnsafePointer()) + cOut := (*C.scalar_t)(out.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cRowSize := (C.int)(rowSize) + cColumnSize := (C.int)(columnSize) + cOnDevice := (C._Bool)(onDevice) + cIsAsync := (C._Bool)(isAsync) + + err := (cr.CudaError)(C.bw6_761_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/grumpkin/base_field.go b/wrappers/golang_v3/curves/grumpkin/base_field.go new file mode 100644 index 000000000..cacd27674 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/base_field.go @@ -0,0 +1,84 @@ +package grumpkin + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int = 8 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromUint32(v uint32) BaseField { + f.limbs[0] = v + return *f +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/grumpkin/curve.go b/wrappers/golang_v3/curves/grumpkin/curve.go new file mode 100644 index 000000000..653cbc8ed --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/curve.go @@ -0,0 +1,177 @@ +package grumpkin + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.grumpkin_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.grumpkin_to_affine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.grumpkin_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.grumpkin_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.grumpkin_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.grumpkin_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/grumpkin/include/curve.h b/wrappers/golang_v3/curves/grumpkin/include/curve.h new file mode 100644 index 000000000..8466982ed --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/include/curve.h @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _GRUMPKIN_CURVE_H +#define _GRUMPKIN_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct DeviceContext DeviceContext; + +bool grumpkin_eq(projective_t* point1, projective_t* point2); +void grumpkin_to_affine(projective_t* point, affine_t* point_out); +void grumpkin_generate_projective_points(projective_t* points, int size); +void grumpkin_generate_affine_points(affine_t* points, int size); +cudaError_t grumpkin_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t grumpkin_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/grumpkin/include/scalar_field.h b/wrappers/golang_v3/curves/grumpkin/include/scalar_field.h new file mode 100644 index 000000000..90517bfd9 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _GRUMPKIN_FIELD_H +#define _GRUMPKIN_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void grumpkin_generate_scalars(scalar_t* scalars, int size); +cudaError_t grumpkin_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/grumpkin/main.go b/wrappers/golang_v3/curves/grumpkin/main.go new file mode 100644 index 000000000..3404e2279 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/main.go @@ -0,0 +1,4 @@ +package grumpkin + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_grumpkin -lingo_field_grumpkin -lstdc++ -lm +import "C" diff --git a/wrappers/golang_v3/curves/grumpkin/msm/include/msm.h b/wrappers/golang_v3/curves/grumpkin/msm/include/msm.h new file mode 100644 index 000000000..9314720be --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/msm/include/msm.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _GRUMPKIN_MSM_H +#define _GRUMPKIN_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct projective_t projective_t; +typedef struct affine_t affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t grumpkin_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); +cudaError_t grumpkin_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); +cudaError_t grumpkin_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/grumpkin/msm/msm.go b/wrappers/golang_v3/curves/grumpkin/msm/msm.go new file mode 100644 index 000000000..b0c4fa86b --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/msm/msm.go @@ -0,0 +1,63 @@ +package msm + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.affine_t)(pointsPointer) + cResults := (*C.projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.grumpkin_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// PrecomputePoints should be used instead. +func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.grumpkin_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.affine_t)(outputBasesPointer) + + __ret := C.grumpkin_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/grumpkin/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/grumpkin/poseidon/include/poseidon.h new file mode 100644 index 000000000..ed27d7dba --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/poseidon/include/poseidon.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _GRUMPKIN_POSEIDON_H +#define _GRUMPKIN_POSEIDON_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PoseidonConfig PoseidonConfig; +typedef struct DeviceContext DeviceContext; +typedef struct PoseidonConstants PoseidonConstants; + + +cudaError_t grumpkin_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); +cudaError_t grumpkin_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); +cudaError_t grumpkin_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go b/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go new file mode 100644 index 000000000..037207530 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go @@ -0,0 +1,57 @@ +package poseidon + +// #cgo CFLAGS: -I./include/ +// #include "poseidon.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func GetDefaultPoseidonConfig() core.PoseidonConfig { + return core.GetDefaultPoseidonConfig() +} + +func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { + scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) + + cScalars := (*C.scalar_t)(scalarsPointer) + cResults := (*C.scalar_t)(resultsPointer) + cNumberOfStates := (C.int)(numberOfStates) + cArity := (C.int)(constants.Arity) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + cCfg := (*C.PoseidonConfig)(cfgPointer) + + __ret := C.grumpkin_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) + + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cFullRoundsHalfs := (C.int)(fullRoundsHalfs) + cPartialRounds := (C.int)(partialRounds) + cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) + + __ret := C.grumpkin_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + + __ret := C.grumpkin_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/curves/grumpkin/scalar_field.go b/wrappers/golang_v3/curves/grumpkin/scalar_field.go new file mode 100644 index 000000000..cc46f3b9c --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/scalar_field.go @@ -0,0 +1,121 @@ +package grumpkin + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int = 8 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromUint32(v uint32) ScalarField { + f.limbs[0] = v + return *f +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalarSlice := make(core.HostSlice[ScalarField], size) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.grumpkin_generate_scalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.grumpkin_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang_v3/curves/grumpkin/tests/base_field_test.go b/wrappers/golang_v3/curves/grumpkin/tests/base_field_test.go new file mode 100644 index 000000000..d1f93f654 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/tests/base_field_test.go @@ -0,0 +1,88 @@ +package tests + +import ( + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + BASE_LIMBS = grumpkin.BASE_LIMBS +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := grumpkin.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := grumpkin.BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField grumpkin.BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField grumpkin.BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField grumpkin.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField grumpkin.BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField grumpkin.BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField grumpkin.BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go b/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go new file mode 100644 index 000000000..29c6c90d0 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go @@ -0,0 +1,103 @@ +package tests + +import ( + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = grumpkin.BaseField{} + + var affineZero grumpkin.Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var affine grumpkin.Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var affine grumpkin.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne grumpkin.BaseField + fieldOne.One() + + var expected grumpkin.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine grumpkin.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero grumpkin.Projective + projectiveZero.Zero() + var fieldZero = grumpkin.BaseField{} + var fieldOne grumpkin.BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var projective grumpkin.Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var projective grumpkin.Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne grumpkin.BaseField + fieldOne.One() + + var expected grumpkin.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine grumpkin.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint grumpkin.Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/grumpkin/tests/main_test.go b/wrappers/golang_v3/curves/grumpkin/tests/main_test.go new file mode 100644 index 000000000..071357d76 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/tests/main_test.go @@ -0,0 +1,17 @@ +package tests + +import ( + "os" + "testing" +) + +const ( + largestTestSize = 20 +) + +func TestMain(m *testing.M) { + + // execute tests + os.Exit(m.Run()) + +} diff --git a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go new file mode 100644 index 000000000..2efd2e92f --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go @@ -0,0 +1,213 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicleGrumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin/msm" +) + +func TestMSM(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleGrumpkin.GenerateScalars(size) + points := icicleGrumpkin.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleGrumpkin.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + + } +} + +func TestMSMPinnedHostMemory(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicleGrumpkin.GenerateScalars(size) + points := icicleGrumpkin.GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[icicleGrumpkin.Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p icicleGrumpkin.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + + if pinnableAndLockable { + e = msm.Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} + +func TestMSMBatch(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleGrumpkin.GenerateScalars(totalSize) + points := icicleGrumpkin.GenerateAffinePoints(totalSize) + + var p icicleGrumpkin.Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleGrumpkin.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + } + } +} + +func TestPrecomputePoints(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicleGrumpkin.GenerateScalars(totalSize) + points := icicleGrumpkin.GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p icicleGrumpkin.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[icicleGrumpkin.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicleGrumpkin.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := icicleGrumpkin.GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p icicleGrumpkin.Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + } +} + +func TestMSMMultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleGrumpkin.GenerateScalars(size) + points := icicleGrumpkin.GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p icicleGrumpkin.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go b/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go new file mode 100644 index 000000000..92f9e5efe --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go @@ -0,0 +1,42 @@ +package tests + +import ( + "testing" + + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin/poseidon" +) + +func TestPoseidon(t *testing.T) { + + arity := 2 + numberOfStates := 1 + + cfg := poseidon.GetDefaultPoseidonConfig() + cfg.IsAsync = true + stream, _ := cr.CreateStream() + cfg.Ctx.Stream = &stream + + var constants core.PoseidonConstants[grumpkin.ScalarField] + + poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants + + scalars := grumpkin.GenerateScalars(numberOfStates * arity) + scalars[0] = scalars[0].Zero() + scalars[1] = scalars[0].Zero() + + scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function + + output := make(core.HostSlice[grumpkin.ScalarField], numberOfStates) + output.CopyFromDeviceAsync(&deviceOutput, stream) + +} diff --git a/wrappers/golang_v3/curves/grumpkin/tests/scalar_field_test.go b/wrappers/golang_v3/curves/grumpkin/tests/scalar_field_test.go new file mode 100644 index 000000000..43e328307 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/tests/scalar_field_test.go @@ -0,0 +1,120 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + SCALAR_LIMBS = grumpkin.SCALAR_LIMBS +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := grumpkin.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := grumpkin.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField grumpkin.ScalarField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField grumpkin.ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField grumpkin.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField grumpkin.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField grumpkin.ScalarField + bytes, expected := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField grumpkin.ScalarField + expected, limbs := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestGrumpkinGenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := grumpkin.GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := grumpkin.ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestGrumpkinMongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := grumpkin.GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + grumpkin.ToMontgomery(&deviceScalars) + + scalarsMontHost := grumpkin.GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + grumpkin.FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang_v3/curves/grumpkin/tests/vec_ops_test.go b/wrappers/golang_v3/curves/grumpkin/tests/vec_ops_test.go new file mode 100644 index 000000000..9413b0597 --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/tests/vec_ops_test.go @@ -0,0 +1,69 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin/vecOps" + "github.com/stretchr/testify/assert" +) + +func TestGrumpkinVecOps(t *testing.T) { + testSize := 1 << 14 + + a := grumpkin.GenerateScalars(testSize) + b := grumpkin.GenerateScalars(testSize) + var scalar grumpkin.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[grumpkin.ScalarField], testSize) + out2 := make(core.HostSlice[grumpkin.ScalarField], testSize) + out3 := make(core.HostSlice[grumpkin.ScalarField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.VecOp(a, b, out, cfg, core.Add) + vecOps.VecOp(out, b, out2, cfg, core.Sub) + + assert.Equal(t, a, out2) + + vecOps.VecOp(a, ones, out3, cfg, core.Mul) + + assert.Equal(t, a, out3) +} + +func TestGrumpkinTranspose(t *testing.T) { + rowSize := 1 << 6 + columnSize := 1 << 8 + onDevice := false + isAsync := false + + matrix := grumpkin.GenerateScalars(rowSize * columnSize) + + out := make(core.HostSlice[grumpkin.ScalarField], rowSize*columnSize) + out2 := make(core.HostSlice[grumpkin.ScalarField], rowSize*columnSize) + + ctx, _ := cr.GetDefaultDeviceContext() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + + assert.Equal(t, matrix, out2) + + var dMatrix, dOut, dOut2 core.DeviceSlice + onDevice = true + + matrix.CopyToDevice(&dMatrix, true) + dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + output := make(core.HostSlice[grumpkin.ScalarField], rowSize*columnSize) + output.CopyFromDevice(&dOut2) + + assert.Equal(t, matrix, output) +} diff --git a/wrappers/golang_v3/curves/grumpkin/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/grumpkin/vecOps/include/vec_ops.h new file mode 100644 index 000000000..c348dafac --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/vecOps/include/vec_ops.h @@ -0,0 +1,53 @@ +#include +#include + +#ifndef _GRUMPKIN_VEC_OPS_H +#define _GRUMPKIN_VEC_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t grumpkin_mul_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t grumpkin_add_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t grumpkin_sub_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t grumpkin_transpose_matrix_cuda( + scalar_t* mat_in, + int row_size, + int column_size, + scalar_t* mat_out, + DeviceContext* ctx, + bool on_device, + bool is_async +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/curves/grumpkin/vecOps/vec_ops.go b/wrappers/golang_v3/curves/grumpkin/vecOps/vec_ops.go new file mode 100644 index 000000000..316fe5c0d --- /dev/null +++ b/wrappers/golang_v3/curves/grumpkin/vecOps/vec_ops.go @@ -0,0 +1,48 @@ +package vecOps + +// #cgo CFLAGS: -I./include/ +// #include "vec_ops.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + + "unsafe" +) + +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Sub: + ret = (cr.CudaError)(C.grumpkin_sub_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Add: + ret = (cr.CudaError)(C.grumpkin_add_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Mul: + ret = (cr.CudaError)(C.grumpkin_mul_cuda(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} + +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { + core.TransposeCheck(in, out, onDevice) + + cIn := (*C.scalar_t)(in.AsUnsafePointer()) + cOut := (*C.scalar_t)(out.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cRowSize := (C.int)(rowSize) + cColumnSize := (C.int)(columnSize) + cOnDevice := (C._Bool)(onDevice) + cIsAsync := (C._Bool)(isAsync) + + err := (cr.CudaError)(C.grumpkin_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/fields/babybear/extension/extension_field.go b/wrappers/golang_v3/fields/babybear/extension/extension_field.go new file mode 100644 index 000000000..ce8768ea6 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/extension/extension_field.go @@ -0,0 +1,119 @@ +package extension + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +const ( + EXTENSION_LIMBS int = 4 +) + +type ExtensionField struct { + limbs [EXTENSION_LIMBS]uint32 +} + +func (f ExtensionField) Len() int { + return int(EXTENSION_LIMBS) +} + +func (f ExtensionField) Size() int { + return int(EXTENSION_LIMBS * 4) +} + +func (f ExtensionField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ExtensionField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ExtensionField) FromUint32(v uint32) ExtensionField { + f.limbs[0] = v + return *f +} + +func (f *ExtensionField) FromLimbs(limbs []uint32) ExtensionField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ExtensionField) Zero() ExtensionField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ExtensionField) One() ExtensionField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ExtensionField) FromBytesLittleEndian(bytes []byte) ExtensionField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ExtensionField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ExtensionField] { + scalarSlice := make(core.HostSlice[ExtensionField], size) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.babybear_extension_generate_scalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*scalars, *scalars, *scalars, &defaultCfg) + cErr := C.babybear_extension_scalar_convert_montgomery((*C.scalar_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.scalar_t)(cValues)) + err := runtime.EIcicleError(cErr) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang_v3/fields/babybear/extension/include/scalar_field.h b/wrappers/golang_v3/fields/babybear/extension/include/scalar_field.h new file mode 100644 index 000000000..958b2c6c5 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/extension/include/scalar_field.h @@ -0,0 +1,22 @@ +#include +#include + +#ifndef _BABYBEAR_EXTENSION_FIELD_H +#define _BABYBEAR_EXTENSION_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; + +void babybear_extension_generate_scalars(scalar_t* scalars, int size); +int babybear_extension_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/fields/babybear/extension/ntt/include/ntt.h b/wrappers/golang_v3/fields/babybear/extension/ntt/include/ntt.h new file mode 100644 index 000000000..d484687e9 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/extension/ntt/include/ntt.h @@ -0,0 +1,22 @@ +#include +#include + +#ifndef _BABYBEAR_EXTENSION_NTT_H +#define _BABYBEAR_EXTENSION_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct NTTConfig NTTConfig; + + +int babybear_extension_ntt(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/fields/babybear/extension/ntt/ntt.go b/wrappers/golang_v3/fields/babybear/extension/ntt/ntt.go new file mode 100644 index 000000000..574a81951 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/extension/ntt/ntt.go @@ -0,0 +1,24 @@ +package ntt + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.babybear_extension_ntt(cScalars, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err +} diff --git a/wrappers/golang_v3/fields/babybear/extension/vecOps/include/vec_ops.h b/wrappers/golang_v3/fields/babybear/extension/vecOps/include/vec_ops.h new file mode 100644 index 000000000..a7860086d --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/extension/vecOps/include/vec_ops.h @@ -0,0 +1,51 @@ +#include +#include + +#ifndef _babybear_extension_VEC_OPS_H +#define _babybear_extension_VEC_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; +typedef struct DeviceContext DeviceContext; + +int babybear_extension_vector_mul( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +int babybear_extension_vector_add( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +int babybear_extension_vector_sub( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +int babybear_extension_matrix_transpose( + scalar_t* mat_in, + int row_size, + int column_size, + VecOpsConfig* config, + scalar_t* mat_out +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/fields/babybear/extension/vecOps/vec_ops.go b/wrappers/golang_v3/fields/babybear/extension/vecOps/vec_ops.go new file mode 100644 index 000000000..afde0e157 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/extension/vecOps/vec_ops.go @@ -0,0 +1,44 @@ +package vecOps + +// #cgo CFLAGS: -I./include/ +// #include "vec_ops.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Sub: + ret = (runtime.EIcicleError)(C.babybear_extension_vector_sub(cA, cB, cSize, cConfig, cOut)) + case core.Add: + ret = (runtime.EIcicleError)(C.babybear_extension_vector_add(cA, cB, cSize, cConfig, cOut)) + case core.Mul: + ret = (runtime.EIcicleError)(C.babybear_extension_vector_mul(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} + +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, config core.VecOpsConfig) runtime.EIcicleError { + inPointer, _, outPointer, cfgPointer, _ := core.VecOpCheck(in, in, out, &config) + + cIn := (*C.scalar_t)(inPointer) + cRowSize := (C.int)(rowSize) + cColumnSize := (C.int)(columnSize) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cOut := (*C.scalar_t)(outPointer) + + err := (C.babybear_extension_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) + return runtime.EIcicleError(err) +} diff --git a/wrappers/golang_v3/fields/babybear/include/scalar_field.h b/wrappers/golang_v3/fields/babybear/include/scalar_field.h new file mode 100644 index 000000000..c22cd571f --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/include/scalar_field.h @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _BABYBEAR_FIELD_H +#define _BABYBEAR_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; + +void babybear_generate_scalars(scalar_t* scalars, int size); +int babybear_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/fields/babybear/main.go b/wrappers/golang_v3/fields/babybear/main.go new file mode 100644 index 000000000..117f7b8a3 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/main.go @@ -0,0 +1,4 @@ +package babybear + +// #cgo LDFLAGS: -L${SRCDIR}/../../../icicle_v3/build -licicle_field_babybear -lstdc++ -Wl,-rpath=${SRCDIR}/../../../icicle_v3/build +import "C" diff --git a/wrappers/golang_v3/fields/babybear/ntt/include/ntt.h b/wrappers/golang_v3/fields/babybear/ntt/include/ntt.h new file mode 100644 index 000000000..4dad1dab3 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/ntt/include/ntt.h @@ -0,0 +1,24 @@ +#include +#include + +#ifndef _BABYBEAR_NTT_H +#define _BABYBEAR_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct NTTConfig NTTConfig; +typedef struct NTTInitDomainConfig NTTInitDomainConfig; + +int babybear_ntt(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +int babybear_ntt_init_domain(scalar_t* primitive_root, NTTInitDomainConfig* ctx); +int babybear_ntt_release_domain(); +int* babybear_get_root_of_unity(size_t size); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/fields/babybear/ntt/ntt.go b/wrappers/golang_v3/fields/babybear/ntt/ntt.go new file mode 100644 index 000000000..2d4b1edb9 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/ntt/ntt.go @@ -0,0 +1,59 @@ +package ntt + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.babybear_ntt(cScalars, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err +} + +func GetDefaultNttConfig() core.NTTConfig[[babybear.SCALAR_LIMBS]uint32] { + cosetGenField := babybear.ScalarField{} + cosetGenField.One() + var cosetGen [babybear.SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func GetRootOfUnity(size uint64) babybear.ScalarField { + cRes := C.babybear_get_root_of_unity((C.size_t)(size)) + var res babybear.ScalarField + res.FromLimbs(*(*[]uint32)(unsafe.Pointer(cRes))) + return res +} + +func InitDomain(primitiveRoot babybear.ScalarField, cfg core.NTTInitDomainConfig) runtime.EIcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCfg := (*C.NTTInitDomainConfig)(unsafe.Pointer(&cfg)) + __ret := C.babybear_ntt_init_domain(cPrimitiveRoot, cCfg) + err := runtime.EIcicleError(__ret) + return err +} + +func ReleaseDomain() runtime.EIcicleError { + __ret := C.babybear_ntt_release_domain() + err := runtime.EIcicleError(__ret) + return err +} diff --git a/wrappers/golang_v3/fields/babybear/polynomial/include/polynomial.h b/wrappers/golang_v3/fields/babybear/polynomial/include/polynomial.h new file mode 100644 index 000000000..dd5107cc7 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/polynomial/include/polynomial.h @@ -0,0 +1,50 @@ +#include +#include + +#ifndef _BABYBEAR_POLY_H +#define _BABYBEAR_POLY_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PolynomialInst PolynomialInst; +typedef struct IntegrityPointer IntegrityPointer; + +PolynomialInst* babybear_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); +PolynomialInst* babybear_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); +PolynomialInst* babybear_polynomial_clone(const PolynomialInst* p); +void babybear_polynomial_print(PolynomialInst* p); +void babybear_polynomial_delete(PolynomialInst* instance); +PolynomialInst* babybear_polynomial_add(const PolynomialInst* a, const PolynomialInst* b); +void babybear_polynomial_add_inplace(PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* babybear_polynomial_subtract(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* babybear_polynomial_multiply(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* babybear_polynomial_multiply_by_scalar(const PolynomialInst* a, const scalar_t* scalar); +void babybear_polynomial_division(const PolynomialInst* a, const PolynomialInst* b, PolynomialInst** q /*OUT*/, PolynomialInst** r /*OUT*/); +PolynomialInst* babybear_polynomial_quotient(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* babybear_polynomial_remainder(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* babybear_polynomial_divide_by_vanishing(const PolynomialInst* p, size_t vanishing_poly_degree); +void babybear_polynomial_add_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void babybear_polynomial_sub_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void babybear_polynomial_evaluate_on_domain(const PolynomialInst* p, scalar_t* domain, size_t domain_size, scalar_t* evals /*OUT*/); +size_t babybear_polynomial_degree(PolynomialInst* p); +size_t babybear_polynomial_copy_coeffs_range(PolynomialInst* p, scalar_t* memory, size_t start_idx, size_t end_idx); +PolynomialInst* babybear_polynomial_even(PolynomialInst* p); +PolynomialInst* babybear_polynomial_odd(PolynomialInst* p); + +// scalar_t* babybear_polynomial_get_coeffs_raw_ptr(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// PolynomialInst* babybear_polynomial_slice(PolynomialInst* p, size_t offset, size_t stride, size_t size); +// IntegrityPointer* babybear_polynomial_get_coeff_view(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// IntegrityPointer* babybear_polynomial_get_rou_evaluations_view(PolynomialInst* p, size_t nof_evals, bool is_reversed, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// const scalar_t* babybear_polynomial_intergrity_ptr_get(IntegrityPointer* p); +// bool babybear_polynomial_intergrity_ptr_is_valid(IntegrityPointer* p); +// void babybear_polynomial_intergrity_ptr_destroy(IntegrityPointer* p); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/wrappers/golang_v3/fields/babybear/polynomial/polynomial.go b/wrappers/golang_v3/fields/babybear/polynomial/polynomial.go new file mode 100644 index 000000000..c83161151 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/polynomial/polynomial.go @@ -0,0 +1,172 @@ +package polynomial + +// #cgo CFLAGS: -I./include/ +// #include "polynomial.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" +) + +type PolynomialHandle = C.struct_PolynomialInst + +type DensePolynomial struct { + handle *PolynomialHandle +} + +func (up *DensePolynomial) Print() { + C.babybear_polynomial_print(up.handle) +} + +func (up *DensePolynomial) CreateFromCoeffecitients(coeffs core.HostOrDeviceSlice) DensePolynomial { + if coeffs.IsOnDevice() { + coeffs.(core.DeviceSlice).CheckDevice() + } + coeffsPointer := (*C.scalar_t)(coeffs.AsUnsafePointer()) + cSize := (C.size_t)(coeffs.Len()) + up.handle = C.babybear_polynomial_create_from_coefficients(coeffsPointer, cSize) + return *up +} + +func (up *DensePolynomial) CreateFromROUEvaluations(evals core.HostOrDeviceSlice) DensePolynomial { + evalsPointer := (*C.scalar_t)(evals.AsUnsafePointer()) + cSize := (C.size_t)(evals.Len()) + up.handle = C.babybear_polynomial_create_from_coefficients(evalsPointer, cSize) + return *up +} + +func (up *DensePolynomial) Clone() DensePolynomial { + return DensePolynomial{ + handle: C.babybear_polynomial_clone(up.handle), + } +} + +// TODO @jeremyfelder: Maybe this should be in a SetFinalizer that is set on Create functions? +func (up *DensePolynomial) Delete() { + C.babybear_polynomial_delete(up.handle) +} + +func (up *DensePolynomial) Add(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.babybear_polynomial_add(up.handle, b.handle), + } +} + +func (up *DensePolynomial) AddInplace(b *DensePolynomial) { + C.babybear_polynomial_add_inplace(up.handle, b.handle) +} + +func (up *DensePolynomial) Subtract(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.babybear_polynomial_subtract(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Multiply(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.babybear_polynomial_multiply(up.handle, b.handle), + } +} + +func (up *DensePolynomial) MultiplyByScalar(scalar babybear.ScalarField) DensePolynomial { + cScalar := (*C.scalar_t)(unsafe.Pointer(scalar.AsPointer())) + return DensePolynomial{ + handle: C.babybear_polynomial_multiply_by_scalar(up.handle, cScalar), + } +} + +func (up *DensePolynomial) Divide(b *DensePolynomial) (DensePolynomial, DensePolynomial) { + var q, r *PolynomialHandle + C.babybear_polynomial_division(up.handle, b.handle, &q, &r) + return DensePolynomial{ + handle: q, + }, DensePolynomial{ + handle: r, + } +} + +func (up *DensePolynomial) Quotient(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.babybear_polynomial_quotient(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Remainder(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.babybear_polynomial_remainder(up.handle, b.handle), + } +} + +func (up *DensePolynomial) DivideByVanishing(vanishing_degree uint64) DensePolynomial { + cVanishingDegree := (C.ulong)(vanishing_degree) + return DensePolynomial{ + handle: C.babybear_polynomial_divide_by_vanishing(up.handle, cVanishingDegree), + } +} + +func (up *DensePolynomial) AddMonomial(monomialCoeff babybear.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]babybear.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.babybear_polynomial_add_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) SubMonomial(monomialCoeff babybear.ScalarField, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]babybear.ScalarField{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.babybear_polynomial_sub_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) Eval(x babybear.ScalarField) babybear.ScalarField { + domains := make(core.HostSlice[babybear.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[babybear.ScalarField], 1) + up.EvalOnDomain(domains, evals) + return evals[0] +} + +func (up *DensePolynomial) EvalOnDomain(domain, evals core.HostOrDeviceSlice) core.HostOrDeviceSlice { + cDomain := (*C.scalar_t)(domain.AsUnsafePointer()) + cDomainSize := (C.size_t)(domain.Len()) + cEvals := (*C.scalar_t)(evals.AsUnsafePointer()) + C.babybear_polynomial_evaluate_on_domain(up.handle, cDomain, cDomainSize, cEvals) + return evals +} + +func (up *DensePolynomial) Degree() int { + return int(C.babybear_polynomial_degree(up.handle)) +} + +func (up *DensePolynomial) CopyCoeffsRange(start, end int, out core.HostOrDeviceSlice) (int, core.HostOrDeviceSlice) { + cStart := (C.size_t)(start) + cEnd := (C.size_t)(end) + cScalarOut := (*C.scalar_t)(out.AsUnsafePointer()) + __cNumCoeffsRead := C.babybear_polynomial_copy_coeffs_range(up.handle, cScalarOut, cStart, cEnd) + return int(__cNumCoeffsRead), out +} + +func (up *DensePolynomial) GetCoeff(idx int) babybear.ScalarField { + out := make(core.HostSlice[babybear.ScalarField], 1) + up.CopyCoeffsRange(idx, idx, out) + return out[0] +} + +func (up *DensePolynomial) Even() DensePolynomial { + evenPoly := C.babybear_polynomial_even(up.handle) + return DensePolynomial{ + handle: evenPoly, + } +} + +func (up *DensePolynomial) Odd() DensePolynomial { + oddPoly := C.babybear_polynomial_odd(up.handle) + return DensePolynomial{ + handle: oddPoly, + } +} diff --git a/wrappers/golang_v3/fields/babybear/scalar_field.go b/wrappers/golang_v3/fields/babybear/scalar_field.go new file mode 100644 index 000000000..4395f97fc --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/scalar_field.go @@ -0,0 +1,119 @@ +package babybear + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +const ( + SCALAR_LIMBS int = 1 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromUint32(v uint32) ScalarField { + f.limbs[0] = v + return *f +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalarSlice := make(core.HostSlice[ScalarField], size) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.babybear_generate_scalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*scalars, *scalars, *scalars, &defaultCfg) + cErr := C.babybear_scalar_convert_montgomery((*C.scalar_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.scalar_t)(cValues)) + err := runtime.EIcicleError(cErr) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang_v3/fields/babybear/tests/main_test.go b/wrappers/golang_v3/fields/babybear/tests/main_test.go new file mode 100644 index 000000000..992e3747b --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/tests/main_test.go @@ -0,0 +1,46 @@ +package tests + +import ( + "os" + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/ntt" + + // poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +const ( + largestTestSize = 20 +) + +func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { + rouIcicle := babybear.ScalarField{} + rouIcicle.FromUint32(1461624142) + e := ntt.InitDomain(rouIcicle, cfg) + return e +} + +func TestMain(m *testing.M) { + runtime.LoadBackendFromEnv() + device := runtime.CreateDevice("CUDA", 0) + runtime.SetDevice(&device) + + // setup domain + cfg := core.GetDefaultNTTInitDomainConfig() + e := initDomain(largestTestSize, cfg) + if e != runtime.Success { + panic("initDomain failed") + } + + // execute tests + os.Exit(m.Run()) + + // release domain + e = ntt.ReleaseDomain() + if e != runtime.Success { + panic("ReleaseDomain failed") + } +} diff --git a/wrappers/golang_v3/fields/babybear/tests/ntt_no_domain_test.go b/wrappers/golang_v3/fields/babybear/tests/ntt_no_domain_test.go new file mode 100644 index 000000000..0c16bbc28 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/tests/ntt_no_domain_test.go @@ -0,0 +1,82 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear_extension "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/extension" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +func TestNttNoDomain(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := babybear_extension.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[babybear_extension.ExtensionField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[babybear_extension.ExtensionField], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + } + } +} + +func TestNttDeviceAsyncNoDomain(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := babybear_extension.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[babybear_extension.ExtensionField](scalars[:testSize]) + + stream, _ := runtime.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.StreamHandle = stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[babybear_extension.ExtensionField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + runtime.SynchronizeStream(stream) + } + } + } +} + +func TestNttBatchNoDomain(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + largestTestSize := 12 + largestBatchSize := 100 + scalars := babybear_extension.GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{2, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[babybear_extension.ExtensionField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[babybear_extension.ExtensionField], totalSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + } + } +} diff --git a/wrappers/golang_v3/fields/babybear/tests/ntt_test.go b/wrappers/golang_v3/fields/babybear/tests/ntt_test.go new file mode 100644 index 000000000..a825bebc8 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/tests/ntt_test.go @@ -0,0 +1,170 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" +) + +func TestNTTGetDefaultConfig(t *testing.T) { + actual := ntt.GetDefaultNttConfig() + expected := test_helpers.GenerateLimbOne(int(babybear.SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := babybear.ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := core.GetDefaultNTTInitDomainConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := babybear.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[babybear.ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[babybear.ScalarField], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := babybear.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[babybear.ScalarField](scalars[:testSize]) + + stream, _ := runtime.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.StreamHandle = stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[babybear.ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + runtime.SynchronizeStream(stream) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + largestTestSize := 12 + largestBatchSize := 100 + scalars := babybear.GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{2, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[babybear.ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[babybear.ScalarField], totalSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + } + } +} + +func TestReleaseDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + e := ntt.ReleaseDomain() + assert.Equal(t, runtime.Success, e, "ReleasDomain failed") +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := ntt.GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang_v3/fields/babybear/tests/polynomial_test.go b/wrappers/golang_v3/fields/babybear/tests/polynomial_test.go new file mode 100644 index 000000000..09f60433b --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/tests/polynomial_test.go @@ -0,0 +1,230 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" + + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/vecOps" + "github.com/stretchr/testify/assert" +) + +var one, two, three, four, five babybear.ScalarField + +func init() { + one.One() + two.FromUint32(2) + three.FromUint32(3) + four.FromUint32(4) + five.FromUint32(5) +} + +func rand() babybear.ScalarField { + return babybear.GenerateScalars(1)[0] +} + +func randomPoly(size int) (f polynomial.DensePolynomial) { + f.CreateFromCoeffecitients(core.HostSliceFromElements(babybear.GenerateScalars(size))) + return f +} + +func vecOp(a, b babybear.ScalarField, op core.VecOps) babybear.ScalarField { + ahost := core.HostSliceWithValue(a, 1) + bhost := core.HostSliceWithValue(b, 1) + out := make(core.HostSlice[babybear.ScalarField], 1) + + cfg := core.DefaultVecOpsConfig() + vecOps.VecOp(ahost, bhost, out, cfg, op) + return out[0] +} + +func TestPolyCreateFromCoefficients(t *testing.T) { + scalars := babybear.GenerateScalars(33) + var uniPoly polynomial.DensePolynomial + + poly := uniPoly.CreateFromCoeffecitients(scalars) + poly.Print() +} + +func TestPolyEval(t *testing.T) { + // testing correct evaluation of f(8) for f(x)=4x^2+2x+5 + coeffs := core.HostSliceFromElements([]babybear.ScalarField{five, two, four}) + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(coeffs) + + var x babybear.ScalarField + x.FromUint32(8) + domains := make(core.HostSlice[babybear.ScalarField], 1) + domains[0] = x + evals := make(core.HostSlice[babybear.ScalarField], 1) + fEvaled := f.EvalOnDomain(domains, evals) + var expected babybear.ScalarField + assert.Equal(t, expected.FromUint32(277), fEvaled.(core.HostSlice[babybear.ScalarField])[0]) +} + +func TestPolyClone(t *testing.T) { + f := randomPoly(8) + x := rand() + fx := f.Eval(x) + + g := f.Clone() + fg := f.Add(&g) + + gx := g.Eval(x) + fgx := fg.Eval(x) + + assert.Equal(t, fx, gx) + assert.Equal(t, vecOp(fx, gx, core.Add), fgx) +} + +func TestPolyAddSubMul(t *testing.T) { + testSize := 1 << 10 + f := randomPoly(testSize) + g := randomPoly(testSize) + x := rand() + + fx := f.Eval(x) + gx := g.Eval(x) + + polyAdd := f.Add(&g) + fxAddgx := vecOp(fx, gx, core.Add) + assert.Equal(t, polyAdd.Eval(x), fxAddgx) + + polySub := f.Subtract(&g) + fxSubgx := vecOp(fx, gx, core.Sub) + assert.Equal(t, polySub.Eval(x), fxSubgx) + + polyMul := f.Multiply(&g) + fxMulgx := vecOp(fx, gx, core.Mul) + assert.Equal(t, polyMul.Eval(x), fxMulgx) + + s1 := rand() + polMulS1 := f.MultiplyByScalar(s1) + assert.Equal(t, polMulS1.Eval(x), vecOp(fx, s1, core.Mul)) + + s2 := rand() + polMulS2 := f.MultiplyByScalar(s2) + assert.Equal(t, polMulS2.Eval(x), vecOp(fx, s2, core.Mul)) +} + +func TestPolyMonomials(t *testing.T) { + var zero babybear.ScalarField + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements([]babybear.ScalarField{one, zero, two})) + x := rand() + + fx := f.Eval(x) + f.AddMonomial(three, 1) + fxAdded := f.Eval(x) + assert.Equal(t, fxAdded, vecOp(fx, vecOp(three, x, core.Mul), core.Add)) + + f.SubMonomial(one, 0) + fxSub := f.Eval(x) + assert.Equal(t, fxSub, vecOp(fxAdded, one, core.Sub)) +} + +func TestPolyReadCoeffs(t *testing.T) { + var f polynomial.DensePolynomial + coeffs := core.HostSliceFromElements([]babybear.ScalarField{one, two, three, four}) + f.CreateFromCoeffecitients(coeffs) + coeffsCopied := make(core.HostSlice[babybear.ScalarField], coeffs.Len()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsCopied) + assert.ElementsMatch(t, coeffs, coeffsCopied) + + var coeffsDevice core.DeviceSlice + coeffsDevice.Malloc(coeffs.Len()*one.Size(), one.Size()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsDevice) + coeffsHost := make(core.HostSlice[babybear.ScalarField], coeffs.Len()) + coeffsHost.CopyFromDevice(&coeffsDevice) + + assert.ElementsMatch(t, coeffs, coeffsHost) +} + +func TestPolyOddEvenSlicing(t *testing.T) { + size := 1<<10 - 3 + f := randomPoly(size) + + even := f.Even() + odd := f.Odd() + assert.Equal(t, f.Degree(), even.Degree()+odd.Degree()+1) + + x := rand() + var evenExpected, oddExpected babybear.ScalarField + for i := size; i >= 0; i-- { + if i%2 == 0 { + mul := vecOp(evenExpected, x, core.Mul) + evenExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } else { + mul := vecOp(oddExpected, x, core.Mul) + oddExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } + } + + evenEvaled := even.Eval(x) + assert.Equal(t, evenExpected, evenEvaled) + + oddEvaled := odd.Eval(x) + assert.Equal(t, oddExpected, oddEvaled) +} + +func TestPolynomialDivision(t *testing.T) { + // divide f(x)/g(x), compute q(x), r(x) and check f(x)=q(x)*g(x)+r(x) + var f, g polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements(babybear.GenerateScalars(1 << 4))) + g.CreateFromCoeffecitients(core.HostSliceFromElements(babybear.GenerateScalars(1 << 2))) + + q, r := f.Divide(&g) + + qMulG := q.Multiply(&g) + fRecon := qMulG.Add(&r) + + x := babybear.GenerateScalars(1)[0] + fEval := f.Eval(x) + fReconEval := fRecon.Eval(x) + assert.Equal(t, fEval, fReconEval) +} + +func TestDivideByVanishing(t *testing.T) { + // poly of x^4-1 vanishes ad 4th rou + var zero babybear.ScalarField + minus_one := vecOp(zero, one, core.Sub) + coeffs := core.HostSliceFromElements([]babybear.ScalarField{minus_one, zero, zero, zero, one}) // x^4-1 + var v polynomial.DensePolynomial + v.CreateFromCoeffecitients(coeffs) + + f := randomPoly(1 << 3) + + fv := f.Multiply(&v) + fDegree := f.Degree() + fvDegree := fv.Degree() + assert.Equal(t, fDegree+4, fvDegree) + + fReconstructed := fv.DivideByVanishing(4) + assert.Equal(t, fDegree, fReconstructed.Degree()) + + x := rand() + assert.Equal(t, f.Eval(x), fReconstructed.Eval(x)) +} + +// func TestPolySlice(t *testing.T) { +// size := 4 +// coeffs := babybear.GenerateScalars(size) +// var f polynomial.DensePolynomial +// f.CreateFromCoeffecitients(coeffs) +// fSlice := f.AsSlice() +// assert.True(t, fSlice.IsOnDevice()) +// assert.Equal(t, size, fSlice.Len()) + +// hostSlice := make(core.HostSlice[babybear.ScalarField], size) +// hostSlice.CopyFromDevice(fSlice) +// assert.Equal(t, coeffs, hostSlice) + +// cfg := ntt.GetDefaultNttConfig() +// res := make(core.HostSlice[babybear.ScalarField], size) +// ntt.Ntt(fSlice, core.KForward, cfg, res) + +// assert.Equal(t, f.Eval(one), res[0]) +// } diff --git a/wrappers/golang_v3/fields/babybear/tests/scalar_field_test.go b/wrappers/golang_v3/fields/babybear/tests/scalar_field_test.go new file mode 100644 index 000000000..41b9f4c6b --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/tests/scalar_field_test.go @@ -0,0 +1,121 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" +) + +const ( + SCALAR_LIMBS = babybear.SCALAR_LIMBS +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := babybear.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := babybear.ScalarField{} + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField babybear.ScalarField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField babybear.ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField babybear.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField babybear.ScalarField + randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField babybear.ScalarField + bytes, expected := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField babybear.ScalarField + expected, limbs := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestBabybearGenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := babybear.GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := babybear.ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestBabybearMongtomeryConversion(t *testing.T) { + size := 1 << 20 + scalars := babybear.GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + babybear.ToMontgomery(&deviceScalars) + + scalarsMontHost := make(core.HostSlice[babybear.ScalarField], size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + babybear.FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang_v3/fields/babybear/tests/vec_ops_test.go b/wrappers/golang_v3/fields/babybear/tests/vec_ops_test.go new file mode 100644 index 000000000..29b4b501e --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/tests/vec_ops_test.go @@ -0,0 +1,66 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/vecOps" + "github.com/stretchr/testify/assert" +) + +func TestBabybearVecOps(t *testing.T) { + testSize := 1 << 14 + + a := babybear.GenerateScalars(testSize) + b := babybear.GenerateScalars(testSize) + var scalar babybear.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[babybear.ScalarField], testSize) + out2 := make(core.HostSlice[babybear.ScalarField], testSize) + out3 := make(core.HostSlice[babybear.ScalarField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.VecOp(a, b, out, cfg, core.Add) + vecOps.VecOp(out, b, out2, cfg, core.Sub) + + assert.Equal(t, a, out2) + + vecOps.VecOp(a, ones, out3, cfg, core.Mul) + + assert.Equal(t, a, out3) +} + +func TestBabybearTranspose(t *testing.T) { + rowSize := 1 << 6 + columnSize := 1 << 8 + + matrix := babybear.GenerateScalars(rowSize * columnSize) + + out := make(core.HostSlice[babybear.ScalarField], rowSize*columnSize) + out2 := make(core.HostSlice[babybear.ScalarField], rowSize*columnSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) + + assert.NotEqual(t, matrix, out) + assert.Equal(t, matrix, out2) + + var dMatrix, dOut, dOut2 core.DeviceSlice + + matrix.CopyToDevice(&dMatrix, true) + dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, cfg) + output := make(core.HostSlice[babybear.ScalarField], rowSize*columnSize) + output.CopyFromDevice(&dOut2) + + assert.Equal(t, matrix, output) +} diff --git a/wrappers/golang_v3/fields/babybear/vecOps/include/vec_ops.h b/wrappers/golang_v3/fields/babybear/vecOps/include/vec_ops.h new file mode 100644 index 000000000..3438ca5b6 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/vecOps/include/vec_ops.h @@ -0,0 +1,51 @@ +#include +#include + +#ifndef _BABYBEAR_VEC_OPS_H +#define _BABYBEAR_VEC_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; +typedef struct DeviceContext DeviceContext; + +int babybear_vector_mul( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +int babybear_vector_add( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +int babybear_vector_sub( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +int babybear_matrix_transpose( + scalar_t* mat_in, + int row_size, + int column_size, + VecOpsConfig* config, + scalar_t* mat_out +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/fields/babybear/vecOps/vec_ops.go b/wrappers/golang_v3/fields/babybear/vecOps/vec_ops.go new file mode 100644 index 000000000..06da50dd1 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/vecOps/vec_ops.go @@ -0,0 +1,44 @@ +package vecOps + +// #cgo CFLAGS: -I./include/ +// #include "vec_ops.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Sub: + ret = (runtime.EIcicleError)(C.babybear_vector_sub(cA, cB, cSize, cConfig, cOut)) + case core.Add: + ret = (runtime.EIcicleError)(C.babybear_vector_add(cA, cB, cSize, cConfig, cOut)) + case core.Mul: + ret = (runtime.EIcicleError)(C.babybear_vector_mul(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} + +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, config core.VecOpsConfig) runtime.EIcicleError { + inPointer, _, outPointer, cfgPointer, _ := core.VecOpCheck(in, in, out, &config) + + cIn := (*C.scalar_t)(inPointer) + cRowSize := (C.int)(rowSize) + cColumnSize := (C.int)(columnSize) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cOut := (*C.scalar_t)(outPointer) + + err := (C.babybear_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) + return runtime.EIcicleError(err) +} diff --git a/wrappers/golang_v3/hash/keccak/hasher.go b/wrappers/golang_v3/hash/keccak/hasher.go new file mode 100644 index 000000000..304342a8f --- /dev/null +++ b/wrappers/golang_v3/hash/keccak/hasher.go @@ -0,0 +1,88 @@ +package keccak + +// #cgo CFLAGS: -I./include/ +// #include "keccak.h" +import "C" + +import ( + "fmt" + "unsafe" + + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +type HashSize int + +const ( + Hash256 HashSize = 256 + Hash512 HashSize = 512 +) + +type KeccakConfig struct { + Ctx cr.DeviceContext + areInputsOnDevice bool + areOutputsOnDevice bool + IsAsync bool +} + +func GetDefaultKeccakConfig() KeccakConfig { + ctx, _ := cr.GetDefaultDeviceContext() + return KeccakConfig{ + ctx, + false, + false, + false, + } +} + +func keccakCheck(input core.HostOrDeviceSlice, output core.HostOrDeviceSlice, cfg *KeccakConfig, hashSize HashSize, numberOfBlocks int32) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) { + cfg.areInputsOnDevice = input.IsOnDevice() + cfg.areOutputsOnDevice = output.IsOnDevice() + + if input.IsOnDevice() { + input.(core.DeviceSlice).CheckDevice() + } + + if output.IsOnDevice() { + output.(core.DeviceSlice).CheckDevice() + } + + if output.Cap() < int(hashSize)/8*int(numberOfBlocks) { + errorString := fmt.Sprintf( + "Output capacity %d isn't enough for hashSize %d and numberOfBlocks %d", + output.Cap(), + hashSize, + numberOfBlocks, + ) + panic(errorString) + } + + return input.AsUnsafePointer(), output.AsUnsafePointer(), unsafe.Pointer(cfg) +} + +func keccak(input core.HostOrDeviceSlice, inputBlockSize, numberOfBlocks int32, output core.HostOrDeviceSlice, config *KeccakConfig, hashSize HashSize) (ret core.IcicleError) { + inputPointer, outputPointer, cfgPointer := keccakCheck(input, output, config, hashSize, numberOfBlocks) + cInput := (*C.uint8_t)(inputPointer) + cOutput := (*C.uint8_t)(outputPointer) + cInputBlockSize := (C.int)(inputBlockSize) + cNumberOfBlocks := (C.int)(numberOfBlocks) + cConfig := (*C.KeccakConfig)(cfgPointer) + + switch hashSize { + case Hash256: + ret = core.FromCudaError((cr.CudaError)(C.keccak256_cuda(cInput, cInputBlockSize, cNumberOfBlocks, cOutput, cConfig))) + case Hash512: + ret = core.FromCudaError((cr.CudaError)(C.keccak512_cuda(cInput, cInputBlockSize, cNumberOfBlocks, cOutput, cConfig))) + } + + return ret +} + +func Keccak256(input core.HostOrDeviceSlice, inputBlockSize, numberOfBlocks int32, output core.HostOrDeviceSlice, config *KeccakConfig) core.IcicleError { + return keccak(input, inputBlockSize, numberOfBlocks, output, config, Hash256) +} + +func Keccak512(input core.HostOrDeviceSlice, inputBlockSize, numberOfBlocks int32, output core.HostOrDeviceSlice, config *KeccakConfig) core.IcicleError { + return keccak(input, inputBlockSize, numberOfBlocks, output, config, Hash512) +} diff --git a/wrappers/golang_v3/hash/keccak/include/keccak.h b/wrappers/golang_v3/hash/keccak/include/keccak.h new file mode 100644 index 000000000..e2202e768 --- /dev/null +++ b/wrappers/golang_v3/hash/keccak/include/keccak.h @@ -0,0 +1,20 @@ +#include +#include + +#ifndef _KECCAK_HASH_H +#define _KECCAK_HASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct KeccakConfig KeccakConfig; + +cudaError_t keccak256_cuda(uint8_t* input, int input_block_size, int number_of_blocks, uint8_t* output, KeccakConfig* config); +cudaError_t keccak512_cuda(uint8_t* input, int input_block_size, int number_of_blocks, uint8_t* output, KeccakConfig* config); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/hash/keccak/main.go b/wrappers/golang_v3/hash/keccak/main.go new file mode 100644 index 000000000..2f342c8e3 --- /dev/null +++ b/wrappers/golang_v3/hash/keccak/main.go @@ -0,0 +1,4 @@ +package keccak + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_hash -lstdc++ -lm +import "C" diff --git a/wrappers/golang_v3/hash/keccak/tests/hasher_test.go b/wrappers/golang_v3/hash/keccak/tests/hasher_test.go new file mode 100644 index 000000000..040715bed --- /dev/null +++ b/wrappers/golang_v3/hash/keccak/tests/hasher_test.go @@ -0,0 +1,66 @@ +package tests + +import ( + "encoding/hex" + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/hash/keccak" + + "github.com/stretchr/testify/assert" +) + +func createHostSliceFromHexString(hexString string) core.HostSlice[uint8] { + byteArray, err := hex.DecodeString(hexString) + if err != nil { + panic("Not a hex string") + } + return core.HostSliceFromElements([]uint8(byteArray)) +} + +func TestSimpleHash256(t *testing.T) { + input := createHostSliceFromHexString("1725b6679911bfe75ad7e248fbeec4a01034feace99aca43cd95d338a37db8d04b4aa5d83c8f8f5bdb8f7f98cec9a658f7f8061a6de07dcfd61db169cc7e666e1971adb4c7e97c43361c9a9eed8bb7b5c33cfe576a383a7440803996fd28148b") + outHost := make(core.HostSlice[uint8], 32) + + cfg := keccak.GetDefaultKeccakConfig() + e := keccak.Keccak256(input, int32(input.Len()), 1, outHost, &cfg) + assert.Equal(t, e.CudaErrorCode, cr.CudaSuccess, "Hashing failed") + t.Log(outHost) + assert.Equal(t, outHost, createHostSliceFromHexString("10fd4a3df6046e32f282cad3ac78e1566304339e7a6696826af023a55ab42048")) +} + +func TestBatchHash256(t *testing.T) { + input := createHostSliceFromHexString("1725b6679911bfe75ad7e248fbeec4a01034feace99aca43cd95d338a37db8d04b4aa5d83c8f8f5bdb8f7f98cec9a658f7f8061a6de07dcfd61db169cc7e666e1971adb4c7e97c43361c9a9eed8bb7b5c33cfe576a383a7440803996fd28148b") + outHost := make(core.HostSlice[uint8], 32*2) + + cfg := keccak.GetDefaultKeccakConfig() + e := keccak.Keccak256(input, int32(input.Len()/2), 2, outHost, &cfg) + assert.Equal(t, e.CudaErrorCode, cr.CudaSuccess, "Hashing failed") + t.Log(outHost) + assert.Equal(t, outHost[:32], createHostSliceFromHexString("7983fbc4cb4539cc90731205c44f74ca74e0a49ad1032a7a1429b1e443e66f45")) + assert.Equal(t, outHost[32:64], createHostSliceFromHexString("2952c2491c75338d28943231a492e9ab684a6820e4af1d74c8c1976759f7bf4b")) +} + +func TestSimpleHash512(t *testing.T) { + input := createHostSliceFromHexString("1725b6679911bfe75ad7e248fbeec4a01034feace99aca43cd95d338a37db8d04b4aa5d83c8f8f5bdb8f7f98cec9a658f7f8061a6de07dcfd61db169cc7e666e1971adb4c7e97c43361c9a9eed8bb7b5c33cfe576a383a7440803996fd28148b") + outHost := make(core.HostSlice[uint8], 64) + + cfg := keccak.GetDefaultKeccakConfig() + e := keccak.Keccak512(input, int32(input.Len()), 1, outHost, &cfg) + assert.Equal(t, e.CudaErrorCode, cr.CudaSuccess, "Hashing failed") + t.Log(outHost) + assert.Equal(t, outHost, createHostSliceFromHexString("1da4e0264dc755bc0b3a3318d2496e11c72322104693b68dbddfa66aa6e8b95526e95a7684a55ea831202f475f3d6a322ed86360d7e0e80f4a129f15d59dd403")) +} + +func TestBatchHash512(t *testing.T) { + input := createHostSliceFromHexString("1725b6679911bfe75ad7e248fbeec4a01034feace99aca43cd95d338a37db8d04b4aa5d83c8f8f5bdb8f7f98cec9a658f7f8061a6de07dcfd61db169cc7e666e1971adb4c7e97c43361c9a9eed8bb7b5c33cfe576a383a7440803996fd28148b") + outHost := make(core.HostSlice[uint8], 64*2) + + cfg := keccak.GetDefaultKeccakConfig() + e := keccak.Keccak512(input, int32(input.Len()/2), 2, outHost, &cfg) + assert.Equal(t, e.CudaErrorCode, cr.CudaSuccess, "Hashing failed") + t.Log(outHost) + assert.Equal(t, outHost[:64], createHostSliceFromHexString("709974f0dc1df1461fcbc2275e968fcb510c947d38837d577d661b6b40249c6b348e33092e4795faad7d2829403bd70fe860207f40a84a23e03c4610ca7927a9")) + assert.Equal(t, outHost[64:128], createHostSliceFromHexString("b8e46caa6cf7fbe6858deb28d4d9e58b768333b1260f5386656c0ae0d0850262bf6aa00293ef0979c37903fb5d2b784a02a4a227725a2b091df182abda03231d")) +} diff --git a/wrappers/golang_v3/internal/generator/config/babybear.go b/wrappers/golang_v3/internal/generator/config/babybear.go new file mode 100644 index 000000000..15b58b5c0 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/config/babybear.go @@ -0,0 +1,17 @@ +package config + +func init() { + var babybear = FieldData{ + PackageName: "babybear", + Field: "babybear", + LimbsNum: 1, + SupportsExtension: true, + ExtensionLimbsNum: 4, + SupportsNTT: true, + SupportsPoseidon: false, + SupportsPoly: true, + ROU: 1461624142, + } + + addField(babybear) +} diff --git a/wrappers/golang_v3/internal/generator/config/bls12377.go b/wrappers/golang_v3/internal/generator/config/bls12377.go new file mode 100644 index 000000000..ea44fd62d --- /dev/null +++ b/wrappers/golang_v3/internal/generator/config/bls12377.go @@ -0,0 +1,19 @@ +package config + +func init() { + var bls12377 = CurveData{ + PackageName: "bls12377", + Curve: "bls12_377", + GnarkImport: "bls12-377", + SupportsPoly: true, + SupportsPoseidon: true, + SupportsNTT: true, + SupportsECNTT: true, + SupportsG2: true, + ScalarFieldNumLimbs: 8, + BaseFieldNumLimbs: 12, + G2FieldNumLimbs: 24, + } + + addCurve(bls12377) +} diff --git a/wrappers/golang_v3/internal/generator/config/bls12381.go b/wrappers/golang_v3/internal/generator/config/bls12381.go new file mode 100644 index 000000000..3f3e1a4ef --- /dev/null +++ b/wrappers/golang_v3/internal/generator/config/bls12381.go @@ -0,0 +1,19 @@ +package config + +func init() { + var bls12381 = CurveData{ + PackageName: "bls12381", + Curve: "bls12_381", + GnarkImport: "bls12-381", + SupportsPoly: true, + SupportsPoseidon: true, + SupportsNTT: true, + SupportsECNTT: true, + SupportsG2: true, + ScalarFieldNumLimbs: 8, + BaseFieldNumLimbs: 12, + G2FieldNumLimbs: 24, + } + + addCurve(bls12381) +} diff --git a/wrappers/golang_v3/internal/generator/config/bn254.go b/wrappers/golang_v3/internal/generator/config/bn254.go new file mode 100644 index 000000000..cdc83afcb --- /dev/null +++ b/wrappers/golang_v3/internal/generator/config/bn254.go @@ -0,0 +1,19 @@ +package config + +func init() { + var bn254 = CurveData{ + PackageName: "bn254", + Curve: "bn254", + GnarkImport: "bn254", + SupportsPoly: true, + SupportsPoseidon: true, + SupportsNTT: true, + SupportsECNTT: true, + SupportsG2: true, + ScalarFieldNumLimbs: 8, + BaseFieldNumLimbs: 8, + G2FieldNumLimbs: 16, + } + + addCurve(bn254) +} diff --git a/wrappers/golang_v3/internal/generator/config/bw6761.go b/wrappers/golang_v3/internal/generator/config/bw6761.go new file mode 100644 index 000000000..90920c87f --- /dev/null +++ b/wrappers/golang_v3/internal/generator/config/bw6761.go @@ -0,0 +1,19 @@ +package config + +func init() { + var bw6761 = CurveData{ + PackageName: "bw6761", + Curve: "bw6_761", + GnarkImport: "bw6-761", + SupportsPoly: true, + SupportsPoseidon: true, + SupportsNTT: true, + SupportsECNTT: true, + SupportsG2: true, + ScalarFieldNumLimbs: 12, + BaseFieldNumLimbs: 24, + G2FieldNumLimbs: 24, + } + + addCurve(bw6761) +} diff --git a/wrappers/golang_v3/internal/generator/config/config.go b/wrappers/golang_v3/internal/generator/config/config.go new file mode 100644 index 000000000..bb1f422e0 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/config/config.go @@ -0,0 +1,50 @@ +package config + +type FieldData struct { + PackageName string + Field string + LimbsNum int + GnarkImport string + SupportsExtension bool + ExtensionLimbsNum int + SupportsNTT bool + SupportsPoseidon bool + SupportsPoly bool + ROU int +} + +type HashData struct { + PackageName string + Hash string +} + +// Maybe just put limbs in CurveData and no need for individual Field objects +type CurveData struct { + PackageName string + Curve string + GnarkImport string + SupportsPoly bool + SupportsPoseidon bool + SupportsNTT bool + SupportsECNTT bool + SupportsG2 bool + ScalarFieldNumLimbs int + BaseFieldNumLimbs int + G2FieldNumLimbs int +} + +var Curves []CurveData +var Fields []FieldData +var Hashes []HashData + +func addCurve(curve CurveData) { + Curves = append(Curves, curve) +} + +func addField(field FieldData) { + Fields = append(Fields, field) +} + +func addHash(hash HashData) { + Hashes = append(Hashes, hash) +} diff --git a/wrappers/golang_v3/internal/generator/config/grumpkin.go b/wrappers/golang_v3/internal/generator/config/grumpkin.go new file mode 100644 index 000000000..84279b98d --- /dev/null +++ b/wrappers/golang_v3/internal/generator/config/grumpkin.go @@ -0,0 +1,19 @@ +package config + +func init() { + var grumpkin = CurveData{ + PackageName: "grumpkin", + Curve: "grumpkin", + GnarkImport: "", + SupportsPoly: false, + SupportsPoseidon: true, + SupportsNTT: false, + SupportsECNTT: false, + SupportsG2: false, + ScalarFieldNumLimbs: 8, + BaseFieldNumLimbs: 8, + G2FieldNumLimbs: 0, + } + + addCurve(grumpkin) +} diff --git a/wrappers/golang_v3/internal/generator/curves/generate.go b/wrappers/golang_v3/internal/generator/curves/generate.go new file mode 100644 index 000000000..1a4982c86 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/curves/generate.go @@ -0,0 +1,42 @@ +package curves + +import ( + "path" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var curveTemplates = map[string]string{ + "src": "curves/templates/curve.go.tmpl", + "test": "curves/templates/curve_test.go.tmpl", + "header": "curves/templates/curve.h.tmpl", +} + +func Generate(baseDir, packageName, curve, curvePrefix string) { + data := struct { + PackageName string + Curve string + CurvePrefix string + BaseImportPath string + }{ + packageName, + curve, + curvePrefix, + baseDir, + } + + filePrefix := "" + if packageName == "g2" { + filePrefix = "g2_" + } + + testDir := "tests" + parentDir := path.Base(baseDir) + if parentDir == "g2" || parentDir == "extension" { + testDir = "../tests" + } + + generator.GenerateFile(curveTemplates["src"], baseDir, "", "", data) + generator.GenerateFile(curveTemplates["header"], path.Join(baseDir, "include"), "", "", data) + generator.GenerateFile(curveTemplates["test"], path.Join(baseDir, testDir), filePrefix, "", data) +} diff --git a/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl new file mode 100644 index 000000000..e6bd59d55 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl @@ -0,0 +1,178 @@ +package {{.PackageName}} +{{if ne .CurvePrefix "Mock"}} +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) +{{end}} +type {{.CurvePrefix}}Projective struct { + X, Y, Z {{.CurvePrefix}}BaseField +} + +func (p {{.CurvePrefix}}Projective) Size() int { + return p.X.Size() * 3 +} + +func (p {{.CurvePrefix}}Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *{{.CurvePrefix}}Projective) Zero() {{.CurvePrefix}}Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *{{.CurvePrefix}}Projective) FromLimbs(x, y, z []uint32) {{.CurvePrefix}}Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *{{.CurvePrefix}}Projective) FromAffine(a {{.CurvePrefix}}Affine) {{.CurvePrefix}}Projective { + z := {{.CurvePrefix}}BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} +{{if ne .CurvePrefix "Mock"}} +func (p {{.CurvePrefix}}Projective) ProjectiveEq(p2 *{{.CurvePrefix}}Projective) bool { + cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p2)) + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *{{.CurvePrefix}}Projective) ProjectiveToAffine() {{.CurvePrefix}}Affine { + var a {{.CurvePrefix}}Affine + + cA := (*C.{{toCName .CurvePrefix}}affine_t)(unsafe.Pointer(&a)) + cP := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&p)) + C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_to_affine(cP, cA) + return a +} + +func {{.CurvePrefix}}GenerateProjectivePoints(size int) core.HostSlice[{{.CurvePrefix}}Projective] { + points := make([]{{.CurvePrefix}}Projective, size) + for i := range points { + points[i] = {{.CurvePrefix}}Projective{} + } + + pointsSlice := core.HostSliceFromElements[{{.CurvePrefix}}Projective](points) + pPoints := (*C.{{toCName .CurvePrefix}}projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_projective_points(pPoints, cSize) + + return pointsSlice +} +{{end}} +type {{.CurvePrefix}}Affine struct { + X, Y {{.CurvePrefix}}BaseField +} + +func (a {{.CurvePrefix}}Affine) Size() int { + return a.X.Size() * 2 +} + +func (a {{.CurvePrefix}}Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *{{.CurvePrefix}}Affine) Zero() {{.CurvePrefix}}Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *{{.CurvePrefix}}Affine) FromLimbs(x, y []uint32) {{.CurvePrefix}}Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a {{.CurvePrefix}}Affine) ToProjective() {{.CurvePrefix}}Projective { + var z {{.CurvePrefix}}BaseField + + return {{.CurvePrefix}}Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} +{{if ne .CurvePrefix "Mock"}} +func {{.CurvePrefix}}AffineFromProjective(p *{{.CurvePrefix}}Projective) {{.CurvePrefix}}Affine { + return p.ProjectiveToAffine() +} + +func {{.CurvePrefix}}GenerateAffinePoints(size int) core.HostSlice[{{.CurvePrefix}}Affine] { + points := make([]{{.CurvePrefix}}Affine, size) + for i := range points { + points[i] = {{.CurvePrefix}}Affine{} + } + + pointsSlice := core.HostSliceFromElements[{{.CurvePrefix}}Affine](points) + cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convert{{.CurvePrefix}}AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.{{toCName .CurvePrefix}}affine_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func {{.CurvePrefix}}AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convert{{.CurvePrefix}}AffinePointsMontgomery(points, true) +} + +func {{.CurvePrefix}}AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convert{{.CurvePrefix}}AffinePointsMontgomery(points, false) +} + +func convert{{.CurvePrefix}}ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.{{toCName .CurvePrefix}}projective_t)(points.AsUnsafePointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func {{.CurvePrefix}}ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convert{{.CurvePrefix}}ProjectivePointsMontgomery(points, true) +} + +func {{.CurvePrefix}}ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + points.CheckDevice() + return convert{{.CurvePrefix}}ProjectivePointsMontgomery(points, false) +} +{{end}} \ No newline at end of file diff --git a/wrappers/golang_v3/internal/generator/curves/templates/curve.h.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/curve.h.tmpl new file mode 100644 index 000000000..22179e6f6 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/curves/templates/curve.h.tmpl @@ -0,0 +1,26 @@ +#include +#include + +#ifndef _{{toUpper .Curve}}_{{.CurvePrefix}}CURVE_H +#define _{{toUpper .Curve}}_{{.CurvePrefix}}CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct {{toCName .CurvePrefix}}projective_t {{toCName .CurvePrefix}}projective_t; +typedef struct {{toCName .CurvePrefix}}affine_t {{toCName .CurvePrefix}}affine_t; +typedef struct DeviceContext DeviceContext; + +bool {{.Curve}}{{toCNameBackwards .CurvePrefix}}_eq({{toCName .CurvePrefix}}projective_t* point1, {{toCName .CurvePrefix}}projective_t* point2); +void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_to_affine({{toCName .CurvePrefix}}projective_t* point, {{toCName .CurvePrefix}}affine_t* point_out); +void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_projective_points({{toCName .CurvePrefix}}projective_t* points, int size); +void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_affine_points({{toCName .CurvePrefix}}affine_t* points, int size); +cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_affine_convert_montgomery({{toCName .CurvePrefix}}affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_projective_convert_montgomery({{toCName .CurvePrefix}}projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/internal/generator/curves/templates/curve_test.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/curve_test.go.tmpl new file mode 100644 index 000000000..8a5cf3825 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/curves/templates/curve_test.go.tmpl @@ -0,0 +1,103 @@ +package tests + +import ( + {{if ne .CurvePrefix "G2"}}{{.Curve}}{{end}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func Test{{.CurvePrefix}}AffineZero(t *testing.T) { + var fieldZero = {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}BaseField{} + + var affineZero {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + var affine {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func Test{{.CurvePrefix}}AffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + + var affine {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func Test{{.CurvePrefix}}AffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + var fieldOne {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}BaseField + fieldOne.One() + + var expected {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func Test{{.CurvePrefix}}ProjectiveZero(t *testing.T) { + var projectiveZero {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Projective + projectiveZero.Zero() + var fieldZero = {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}BaseField{} + var fieldOne {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + var projective {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func Test{{.CurvePrefix}}ProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + + var projective {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func Test{{.CurvePrefix}}ProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int({{.CurvePrefix}}BASE_LIMBS)) + var fieldOne {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}BaseField + fieldOne.One() + + var expected {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint {{if eq .CurvePrefix "G2"}}g2{{else}}{{.Curve}}{{end}}.{{.CurvePrefix}}Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl new file mode 100644 index 000000000..3a85167d0 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl @@ -0,0 +1,4 @@ +package {{.PackageName}} + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../{{.UpDirs}}icicle/build/lib -lingo_curve_{{.Field}} -lingo_field_{{.Field}} -lstdc++ -lm +import "C" diff --git a/wrappers/golang_v3/internal/generator/ecntt/generate.go b/wrappers/golang_v3/internal/generator/ecntt/generate.go new file mode 100644 index 000000000..a557babee --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ecntt/generate.go @@ -0,0 +1,29 @@ +package ntt + +import ( + "path" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var ecnttTemplates = map[string]string{ + "src": "ecntt/templates/ecntt.go.tmpl", + "test": "ecntt/templates/ecntt_test.go.tmpl", + "header": "ecntt/templates/ecntt.h.tmpl", +} + +func Generate(baseDir, curve, gnarkImport string) { + data := struct { + Curve string + BaseImportPath string + GnarkImport string + }{ + curve, + baseDir, + gnarkImport, + } + + generator.GenerateFile(ecnttTemplates["src"], path.Join(baseDir, "ecntt"), "", "", data) + generator.GenerateFile(ecnttTemplates["header"], path.Join(baseDir, "ecntt", "include"), "", "", data) + generator.GenerateFile(ecnttTemplates["test"], path.Join(baseDir, "tests"), "", "", data) +} diff --git a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl new file mode 100644 index 000000000..2e4e98d5e --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl @@ -0,0 +1,24 @@ +package ecntt + +// #cgo CFLAGS: -I./include/ +// #include "ecntt.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) + + cPoints := (*C.projective_t)(pointsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.projective_t)(resultsPointer) + + __ret := C.{{.Curve}}_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.h.tmpl b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.h.tmpl new file mode 100644 index 000000000..3180f5340 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.h.tmpl @@ -0,0 +1,19 @@ +#include + +#ifndef _{{toUpper .Curve}}_ECNTT_H +#define _{{toUpper .Curve}}_ECNTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NTTConfig NTTConfig; +typedef struct projective_t projective_t; + +cudaError_t {{.Curve}}_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl new file mode 100644 index 000000000..ac9f96271 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl @@ -0,0 +1,30 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + {{.Curve}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt" + "github.com/stretchr/testify/assert" +) + +func TestECNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + points := {{.Curve}}.GenerateProjectivePoints(1 << largestTestSize) + + for _, size := range []int{4, 5, 6, 7, 8} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + pointsCopy := core.HostSliceFromElements[{{.Curve}}.Projective](points[:testSize]) + cfg.Ordering = v + cfg.NttAlgorithm = core.Radix2 + + output := make(core.HostSlice[{{.Curve}}.Projective], testSize) + e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + } + } +} diff --git a/wrappers/golang_v3/internal/generator/fields/generate.go b/wrappers/golang_v3/internal/generator/fields/generate.go new file mode 100644 index 000000000..6c52c6d5e --- /dev/null +++ b/wrappers/golang_v3/internal/generator/fields/generate.go @@ -0,0 +1,47 @@ +package fields + +import ( + "path" + "strings" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var fieldTemplates = map[string]string{ + "src": "fields/templates/field.go.tmpl", + "test": "fields/templates/field_test.go.tmpl", + "header": "fields/templates/scalar_field.h.tmpl", +} + +func Generate(baseDir, packageName, field, fieldPrefix string, isScalar bool, numLimbs int) { + data := struct { + PackageName string + Field string + FieldPrefix string + BaseImportPath string + IsScalar bool + NUM_LIMBS int + }{ + packageName, + field, + fieldPrefix, + baseDir, + isScalar, + numLimbs, + } + + filePrefix := "" + if packageName == "g2" { + filePrefix = "g2_" + } + + testDir := "tests" + parentDir := path.Base(baseDir) + if parentDir == "g2" || parentDir == "extension" { + testDir = "../tests" + } + + generator.GenerateFile(fieldTemplates["src"], baseDir, strings.ToLower(fieldPrefix)+"_", "", data) + generator.GenerateFile(fieldTemplates["header"], path.Join(baseDir, "include"), "", "", data) + generator.GenerateFile(fieldTemplates["test"], path.Join(baseDir, testDir), filePrefix+strings.ToLower(fieldPrefix)+"_", "", data) +} diff --git a/wrappers/golang_v3/internal/generator/fields/templates/field.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/field.go.tmpl new file mode 100644 index 000000000..47bc7e92f --- /dev/null +++ b/wrappers/golang_v3/internal/generator/fields/templates/field.go.tmpl @@ -0,0 +1,124 @@ +package {{.PackageName}} +{{if .IsScalar -}} +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +{{- end}} +import ( + "encoding/binary" + "fmt" + {{- if .IsScalar}} + "unsafe" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + {{- end}} +) + +const ( + {{toConst .FieldPrefix}}LIMBS int = {{.NUM_LIMBS}} +) + +type {{.FieldPrefix}}Field struct { + limbs [{{toConst .FieldPrefix}}LIMBS]uint32 +} + +func (f {{.FieldPrefix}}Field) Len() int { + return int({{toConst .FieldPrefix}}LIMBS) +} + +func (f {{.FieldPrefix}}Field) Size() int { + return int({{toConst .FieldPrefix}}LIMBS * 4) +} + +func (f {{.FieldPrefix}}Field) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f {{.FieldPrefix}}Field) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *{{.FieldPrefix}}Field) FromUint32(v uint32) {{.FieldPrefix}}Field { + f.limbs[0] = v + return *f +} + +func (f *{{.FieldPrefix}}Field) FromLimbs(limbs []uint32) {{.FieldPrefix}}Field { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *{{.FieldPrefix}}Field) Zero() {{.FieldPrefix}}Field { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *{{.FieldPrefix}}Field) One() {{.FieldPrefix}}Field { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *{{.FieldPrefix}}Field) FromBytesLittleEndian(bytes []byte) {{.FieldPrefix}}Field { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f {{.FieldPrefix}}Field) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} +{{if .IsScalar}} +func GenerateScalars(size int) core.HostSlice[{{.FieldPrefix}}Field] { + scalarSlice := make(core.HostSlice[{{.FieldPrefix}}Field], size) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.{{.Field}}_generate_scalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.{{.Field}}_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + scalars.CheckDevice() + return convertScalarsMontgomery(scalars, false) +}{{end}} diff --git a/wrappers/golang_v3/internal/generator/fields/templates/field_test.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/field_test.go.tmpl new file mode 100644 index 000000000..2a10ef24c --- /dev/null +++ b/wrappers/golang_v3/internal/generator/fields/templates/field_test.go.tmpl @@ -0,0 +1,121 @@ +package tests + +import ( + {{- if .IsScalar}} + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"{{end}} + {{if ne .FieldPrefix "G2"}}{{.Field}}{{end}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}{{if eq .FieldPrefix "G2"}}/g2{{end}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + + const ( + {{toConst .FieldPrefix}}LIMBS = {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{toConst .FieldPrefix}}LIMBS +) + +func Test{{.FieldPrefix}}FieldFromLimbs(t *testing.T) { + emptyField := {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field{} + randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the {{.FieldPrefix}}Field's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func Test{{.FieldPrefix}}FieldGetLimbs(t *testing.T) { + emptyField := {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field{} + randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the {{.FieldPrefix}}Field's limbs") +} + +func Test{{.FieldPrefix}}FieldOne(t *testing.T) { + var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int({{toConst .FieldPrefix}}LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "{{.FieldPrefix}}Field with limbs to field one did not work") +} + +func Test{{.FieldPrefix}}FieldZero(t *testing.T) { + var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field + emptyField.Zero() + limbsZero := make([]uint32, {{toConst .FieldPrefix}}LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "{{.FieldPrefix}}Field with limbs to field zero failed") +} + +func Test{{.FieldPrefix}}FieldSize(t *testing.T) { + var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field + randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func Test{{.FieldPrefix}}FieldAsPointer(t *testing.T) { + var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field + randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func Test{{.FieldPrefix}}FieldFromBytes(t *testing.T) { + var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field + bytes, expected := test_helpers.GenerateBytesArray(int({{toConst .FieldPrefix}}LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func Test{{.FieldPrefix}}FieldToBytes(t *testing.T) { + var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field + expected, limbs := test_helpers.GenerateBytesArray(int({{toConst .FieldPrefix}}LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} +{{if .IsScalar}} +func Test{{capitalize .Field}}GenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := {{.Field}}.GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := {{.Field}}.{{.FieldPrefix}}Field{} + assert.NotContains(t, scalars, zeroScalar) +} + +func Test{{capitalize .Field}}MongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := {{.Field}}.GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + {{.Field}}.ToMontgomery(&deviceScalars) + + scalarsMontHost := {{.Field}}.GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + {{.Field}}.FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +}{{end}} diff --git a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl new file mode 100644 index 000000000..f2ee003e0 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl @@ -0,0 +1,4 @@ +package {{.PackageName}} + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../{{.UpDirs}}icicle/build/lib -lingo_field_{{.Field}} -lstdc++ -lm +import "C" diff --git a/wrappers/golang_v3/internal/generator/fields/templates/scalar_field.h.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/scalar_field.h.tmpl new file mode 100644 index 000000000..2401d0985 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/fields/templates/scalar_field.h.tmpl @@ -0,0 +1,21 @@ +#include +#include + +#ifndef _{{toUpper .Field}}_FIELD_H +#define _{{toUpper .Field}}_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct DeviceContext DeviceContext; + +void {{.Field}}_generate_scalars(scalar_t* scalars, int size); +cudaError_t {{.Field}}_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/internal/generator/generator_utils/generate.go b/wrappers/golang_v3/internal/generator/generator_utils/generate.go new file mode 100644 index 000000000..902fc9d36 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/generator_utils/generate.go @@ -0,0 +1,107 @@ +package generator_utils + +import ( + "bytes" + "fmt" + "io" + "os" + "path" + "path/filepath" + "strings" + "text/template" +) + +const ( + // Since path.Join joins from the cwd we only need to go up two directories + // from wrappers/golang/internal/generator/main.go to get to wrappers/golang + GOLANG_WRAPPER_ROOT_DIR = "../../" +) + +func create(output string, buf *bytes.Buffer) error { + // create output dir if not exist + _ = os.MkdirAll(filepath.Dir(output), os.ModePerm) + + // create output file + file, err := os.Create(output) + if err != nil { + return err + } + + if _, err := io.Copy(file, buf); err != nil { + file.Close() + return err + } + + file.Close() + return nil +} + +type entry struct { + outputName string + parsedTemplate *template.Template +} + +func toPackage(s string) string { + return strings.ReplaceAll(s, "-", "") +} + +func toCName(s string) string { + if s == "" { + return "" + } + return strings.ToLower(s) + "_" +} + +func toCNameBackwards(s string) string { + if s == "" { + return "" + } + return "_" + strings.ToLower(s) +} + +func toConst(s string) string { + if s == "" { + return "" + } + return strings.ToUpper(s) + "_" +} +func capitalize(s string) string { + if s == "" { + return "" + } + return strings.ToUpper(s[:1]) + s[1:] +} + +var templateFuncs = template.FuncMap{ + "log": fmt.Println, + "toLower": strings.ToLower, + "toUpper": strings.ToUpper, + "toPackage": toPackage, + "toCName": toCName, + "toCNameBackwards": toCNameBackwards, + "toConst": toConst, + "capitalize": capitalize, +} + +func parseTemplateFile(tmplPath string) entry { + tmplName := tmplPath[strings.LastIndex(tmplPath, "/")+1:] + tmpl := template.New(tmplName).Funcs(templateFuncs) + tmplParsed, err := tmpl.ParseFiles(tmplPath) + if err != nil { + panic(err) + } + fileName, ok := strings.CutSuffix(tmplName, ".tmpl") + if !ok { + panic(".tmpl suffix not found") + } + + return entry{outputName: fileName, parsedTemplate: tmplParsed} +} + +func GenerateFile(templateFilePath, baseDir, fileNamePrefix, fileNameSuffix string, data any) { + entry := parseTemplateFile(templateFilePath) + var buf bytes.Buffer + entry.parsedTemplate.Execute(&buf, data) + outFile := path.Join(GOLANG_WRAPPER_ROOT_DIR, baseDir, fileNamePrefix+entry.outputName+fileNameSuffix) + create(outFile, &buf) +} diff --git a/wrappers/golang_v3/internal/generator/lib_linker/generate.go b/wrappers/golang_v3/internal/generator/lib_linker/generate.go new file mode 100644 index 000000000..24c6ba5ad --- /dev/null +++ b/wrappers/golang_v3/internal/generator/lib_linker/generate.go @@ -0,0 +1,33 @@ +package lib_linker + +import ( + "strings" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +type MainTemplateType string + +const ( + CURVE MainTemplateType = "curves" + FIELD MainTemplateType = "fields" +) + +var mainTemplates = map[MainTemplateType]string{ + "fields": "fields/templates/main.go.tmpl", + "curves": "curves/templates/main.go.tmpl", +} + +func Generate(baseDir, packageName, field string, templateType MainTemplateType, numAdditionalDirectoriesToLib int) { + data := struct { + PackageName string + Field string + UpDirs string + }{ + packageName, + field, + strings.Repeat("../", numAdditionalDirectoriesToLib), + } + + generator.GenerateFile(mainTemplates[templateType], baseDir, "", "", data) +} diff --git a/wrappers/golang_v3/internal/generator/main.go b/wrappers/golang_v3/internal/generator/main.go new file mode 100644 index 000000000..ded450417 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/main.go @@ -0,0 +1,100 @@ +package main + +import ( + "fmt" + "os" + "os/exec" + "path" + + config "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/config" + curves "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/curves" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/ecntt" + fields "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/fields" + lib_linker "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/lib_linker" + mock "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/mock" + msm "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/msm" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/ntt" + poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/polynomial" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/poseidon" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/tests" + vecops "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/vecOps" +) + +func generateFiles() { + fmt.Println("Generating files") + + for _, curve := range config.Curves { + curveDir := path.Join("curves", curve.PackageName) + scalarFieldPrefix := "Scalar" + fields.Generate(curveDir, curve.PackageName, curve.Curve, scalarFieldPrefix, true, curve.ScalarFieldNumLimbs) + fields.Generate(curveDir, curve.PackageName, curve.Curve, "Base", false, curve.BaseFieldNumLimbs) + curves.Generate(curveDir, curve.PackageName, curve.Curve, "") + vecops.Generate(curveDir, curve.Curve, scalarFieldPrefix) + if curve.SupportsPoly { + poly.Generate(curveDir, curve.Curve, scalarFieldPrefix, curve.GnarkImport) + } + lib_linker.Generate(curveDir, curve.PackageName, curve.Curve, lib_linker.CURVE, 0) + + if curve.SupportsNTT { + ntt.Generate(curveDir, "", curve.Curve, scalarFieldPrefix, curve.GnarkImport, 0, true, "", "") + } + + if curve.SupportsECNTT { + ecntt.Generate(curveDir, curve.Curve, curve.GnarkImport) + } + + msm.Generate(curveDir, "msm", curve.Curve, "", curve.GnarkImport) + poseidon.Generate(curveDir, "", curve.Curve, scalarFieldPrefix) + if curve.SupportsG2 { + g2BaseDir := path.Join(curveDir, "g2") + packageName := "g2" + fields.Generate(g2BaseDir, packageName, curve.Curve, "G2Base", false, curve.G2FieldNumLimbs) + curves.Generate(g2BaseDir, packageName, curve.Curve, "G2") + msm.Generate(curveDir, "g2", curve.Curve, "G2", curve.GnarkImport) + } + + tests.Generate(curveDir, curve.Curve, scalarFieldPrefix, curve.GnarkImport, 0, curve.SupportsNTT, curve.SupportsPoly) + } + + for _, field := range config.Fields { + fieldDir := path.Join("fields", field.PackageName) + scalarFieldPrefix := "Scalar" + fields.Generate(fieldDir, field.PackageName, field.Field, scalarFieldPrefix, true, field.LimbsNum) + vecops.Generate(fieldDir, field.Field, scalarFieldPrefix) + if field.SupportsPoly { + poly.Generate(fieldDir, field.Field, scalarFieldPrefix, field.GnarkImport) + } + ntt.Generate(fieldDir, "", field.Field, scalarFieldPrefix, field.GnarkImport, field.ROU, true, "", "") + lib_linker.Generate(fieldDir, field.PackageName, field.Field, lib_linker.FIELD, 0) + + if field.SupportsExtension { + extensionsDir := path.Join(fieldDir, "extension") + extensionField := field.Field + "_extension" + extensionFieldPrefix := "Extension" + fields.Generate(extensionsDir, "extension", extensionField, extensionFieldPrefix, true, field.ExtensionLimbsNum) + vecops.Generate(extensionsDir, extensionField, extensionFieldPrefix) + ntt.Generate(fieldDir, "extension", field.Field, scalarFieldPrefix, field.GnarkImport, field.ROU, false, extensionField, extensionFieldPrefix) + lib_linker.Generate(extensionsDir, "extension", field.Field, lib_linker.FIELD, 1) + } + + tests.Generate(fieldDir, field.Field, scalarFieldPrefix, field.GnarkImport, field.ROU, field.SupportsNTT, field.SupportsPoly) + } + + // Mock field and curve files for core + mock.Generate("core/internal", "internal", "Mock", "MockBase", false, 4) +} + +//go:generate go run main.go +func main() { + generateFiles() + + cmd := exec.Command("gofmt", "-w", "../../") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err := cmd.Run() + if err != nil { + fmt.Printf("\n%s\n", err.Error()) + os.Exit(-1) + } +} diff --git a/wrappers/golang_v3/internal/generator/mock/generate.go b/wrappers/golang_v3/internal/generator/mock/generate.go new file mode 100644 index 000000000..ec4c55413 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/mock/generate.go @@ -0,0 +1,38 @@ +package fields + +import ( + "strings" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var mockTemplates = map[string]string{ + "field": "fields/templates/field.go.tmpl", + "curve": "curves/templates/curve.go.tmpl", +} + +func Generate(baseDir, packageName, field, fieldPrefix string, isScalar bool, numLimbs int) { + fieldData := struct { + PackageName string + Field string + FieldPrefix string + IsScalar bool + NUM_LIMBS int + }{ + packageName, + field, + fieldPrefix, + isScalar, + numLimbs, + } + generator.GenerateFile(mockTemplates["field"], baseDir, strings.ToLower(field)+"_", "", fieldData) + + curveData := struct { + PackageName string + CurvePrefix string + }{ + packageName, + field, + } + generator.GenerateFile(mockTemplates["curve"], baseDir, strings.ToLower(field)+"_", "", curveData) +} diff --git a/wrappers/golang_v3/internal/generator/msm/generate.go b/wrappers/golang_v3/internal/generator/msm/generate.go new file mode 100644 index 000000000..304c192af --- /dev/null +++ b/wrappers/golang_v3/internal/generator/msm/generate.go @@ -0,0 +1,39 @@ +package msm + +import ( + "path" + "path/filepath" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var msmTemplates = map[string]string{ + "src": "msm/templates/msm.go.tmpl", + "test": "msm/templates/msm_test.go.tmpl", + "header": "msm/templates/msm.h.tmpl", +} + +func Generate(baseDir, packageName, curve, curvePrefix, gnarkImport string) { + data := struct { + PackageName string + Curve string + CurvePrefix string + BaseImportPath string + GnarkImport string + }{ + packageName, + curve, + curvePrefix, + baseDir, + gnarkImport, + } + + filePrefix := "" + if packageName == "g2" { + filePrefix = "g2_" + } + + generator.GenerateFile(msmTemplates["src"], path.Join(baseDir, packageName), "", "", data) + generator.GenerateFile(msmTemplates["header"], path.Join(baseDir, packageName, "include"), "", "", data) + generator.GenerateFile(msmTemplates["test"], filepath.Join(baseDir, "tests"), filePrefix, "", data) +} diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl new file mode 100644 index 000000000..735111cd8 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl @@ -0,0 +1,63 @@ +package {{.PackageName}} + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "unsafe" +) + +func {{.CurvePrefix}}GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func {{.CurvePrefix}}Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) + cResults := (*C.{{toCName .CurvePrefix}}projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(cfgPointer) + + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} + +// Deprecated: {{.CurvePrefix}}PrecomputeBases exists for backward compatibility. +// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// {{.CurvePrefix}}PrecomputePoints should be used instead. +func {{.CurvePrefix}}PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { + cfg := {{.CurvePrefix}}GetDefaultMSMConfig() + cfg.PrecomputeFactor = precomputeFactor + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + + cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) + cPointsLen := (C.int)(points.Len()) + cPrecomputeFactor := (C.int)(precomputeFactor) + cC := (C.int)(c) + cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) + cOutputBases := (*C.{{toCName .CurvePrefix}}affine_t)(outputBasesPointer) + + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} + +func {{.CurvePrefix}}PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { + pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + + cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) + cMsmSize := (C.int)(msmSize) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.{{toCName .CurvePrefix}}affine_t)(outputBasesPointer) + + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl new file mode 100644 index 000000000..cd3520f1f --- /dev/null +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _{{toUpper .Curve}}_{{.CurvePrefix}}MSM_H +#define _{{toUpper .Curve}}_{{.CurvePrefix}}MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct {{toCName .CurvePrefix}}projective_t {{toCName .CurvePrefix}}projective_t; +typedef struct {{toCName .CurvePrefix}}affine_t {{toCName .CurvePrefix}}affine_t; +typedef struct MSMConfig MSMConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_cuda(const scalar_t* scalars,const {{toCName .CurvePrefix}}affine_t* points, int count, MSMConfig* config, {{toCName .CurvePrefix}}projective_t* out); +cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_bases_cuda({{toCName .CurvePrefix}}affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, {{toCName .CurvePrefix}}affine_t* out); +cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_points_cuda({{toCName .CurvePrefix}}affine_t* points, int msm_size, MSMConfig* config, {{toCName .CurvePrefix}}affine_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl new file mode 100644 index 000000000..0fb9e6c19 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl @@ -0,0 +1,417 @@ +package tests + +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + {{if ne .GnarkImport "" -}} + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}" + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fp" + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr" + {{end}} + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + icicle{{capitalize .Curve}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/{{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}" +) +{{if ne .GnarkImport "" -}} +{{$isBW6 := eq .Curve "bw6_761"}}{{$isG2 := eq .CurvePrefix "G2"}}{{$isG1 := ne .CurvePrefix "G2"}}{{if or $isBW6 $isG1}} +func projectiveToGnarkAffine{{if and $isBW6 $isG2}}G2{{end}}(p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{if and $isBW6 $isG2}}G2{{end}}Projective) {{toPackage .GnarkImport}}.{{if and $isBW6 $isG2}}G2{{else}}G1{{end}}Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return {{toPackage .GnarkImport}}.{{if and $isBW6 $isG2}}G2{{else}}G1{{end}}Affine{X: *x, Y: *y} +} +{{end}} +{{- $isNotBW6 := ne .Curve "bw6_761"}}{{$isG2 := eq .CurvePrefix "G2"}}{{if and $isNotBW6 $isG2 }} +func projectiveToGnarkAffineG2(p g2.G2Projective) {{toPackage .GnarkImport}}.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := {{toPackage .GnarkImport}}.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := {{toPackage .GnarkImport}}.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := {{toPackage .GnarkImport}}.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared {{toPackage .GnarkImport}}.E2 + zSquared.Mul(&z, &z) + + var X {{toPackage .GnarkImport}}.E2 + X.Mul(&x, &z) + + var Y {{toPackage .GnarkImport}}.E2 + Y.Mul(&y, &zSquared) + + g2Jac := {{toPackage .GnarkImport}}.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine {{toPackage .GnarkImport}}.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} +{{end}} +func testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars core.HostSlice[icicle{{capitalize .Curve}}.ScalarField], points core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Affine], out {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]{{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine{{.CurvePrefix}}(v.ToProjective()) + } + + return testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[{{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Affine], out {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective) bool { + var msmRes {{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac {{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Jac + proj := projectiveToGnarkAffine{{.CurvePrefix}}(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +{{$isBW6 := eq .Curve "bw6_761"}}{{$isG2 := eq .CurvePrefix "G2"}}{{$isG1 := ne .CurvePrefix "G2"}}{{if or $isBW6 $isG1 -}} +func convertIcicleAffineTo{{if and $isBW6 $isG2}}G2{{else}}G1{{end}}Affine(iciclePoints []{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Affine) []{{toPackage .GnarkImport}}.{{if and $isBW6 $isG2}}G2{{else}}G1{{end}}Affine { + points := make([]{{toPackage .GnarkImport}}.{{if and $isBW6 $isG2}}G2{{else}}G1{{end}}Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes]byte)(iciclePoint.X.ToBytesLittleEndian()) + fpXElem, _ := fp.LittleEndian.Element(&xBytes) + + yBytes := ([fp.Bytes]byte)(iciclePoint.Y.ToBytesLittleEndian()) + fpYElem, _ := fp.LittleEndian.Element(&yBytes) + points[index] = {{toPackage .GnarkImport}}.{{if and $isBW6 $isG2}}G2{{else}}G1{{end}}Affine{ + X: fpXElem, + Y: fpYElem, + } + } + + return points +}{{end}} +{{ $isNotBW6 := ne .Curve "bw6_761"}}{{$isG2 := eq .CurvePrefix "G2"}}{{if and $isNotBW6 $isG2 -}} +func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []{{toPackage .GnarkImport}}.G2Affine { + points := make([]{{toPackage .GnarkImport}}.G2Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian()) + xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes]) + xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:]) + xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes) + xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes) + + yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian()) + yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes]) + yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:]) + yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes) + yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes) + + points[index] = {{toPackage .GnarkImport}}.G2Affine{ + X: {{toPackage .GnarkImport}}.E2{ + A0: xA0Elem, + A1: xA1Elem, + }, + Y: {{toPackage .GnarkImport}}.E2{ + A0: yA0Elem, + A1: yA1Elem, + }, + } + } + + return points +}{{end}}{{end}} + +func TestMSM{{.CurvePrefix}}(t *testing.T) { + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) + points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + {{if ne .GnarkImport "" -}} + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])) + {{end}} + } +} + +func TestMSM{{.CurvePrefix}}PinnedHostMemory(t *testing.T) { + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() + for _, power := range []int{10} { + size := 1 << power + + scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) + points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) + + pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) + lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + + pinnableAndLockable := pinnable == 1 && lockable == 0 + + var pinnedPoints core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Affine] + if pinnableAndLockable { + points.Pin(cr.CudaHostRegisterDefault) + pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) + assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") + } + + var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + + outHost.CopyFromDevice(&out) + {{if ne .GnarkImport "" -}} + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])) + {{end}} + + if pinnableAndLockable { + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, pinnedPoints, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + + outHost.CopyFromDevice(&out) + {{if ne .GnarkImport "" -}} + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, pinnedPoints, outHost[0])) + {{end}} + } + + out.Free() + + if pinnableAndLockable { + points.Unpin() + pinnedPoints.FreePinned() + } + } +} +{{if ne .GnarkImport "" -}} +func TestMSM{{if eq .CurvePrefix "G2"}}G2{{end}}GnarkCryptoTypes(t *testing.T) { + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() + for _, power := range []int{3} { + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) + pointsGnark := convertIcicle{{$isNotBW6 := ne .Curve "bw6_761"}}{{$isG2 := eq .CurvePrefix "G2"}}{{if and $isNotBW6 $isG2}}G2{{end}}AffineTo{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Affine(points) + pointsHost := (core.HostSlice[{{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Affine])(pointsGnark) + + var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.ArePointsMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + } +} +{{end}} +func TestMSM{{.CurvePrefix}}Batch(t *testing.T) { + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicle{{capitalize .Curve}}.GenerateScalars(totalSize) + points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(totalSize) + + var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + {{if ne .GnarkImport "" -}} + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalarsSlice, pointsSlice, out)) + }{{end}} + } + } +} + +func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) { + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := icicle{{capitalize .Curve}}.GenerateScalars(totalSize) + points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}PrecomputePoints(points, size, &cfg, precomputeOut) + assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + + var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + {{if ne .GnarkImport "" -}} + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalarsSlice, pointsSlice, out)) + }{{end}} + } + } +} + +func TestMSM{{.CurvePrefix}}SkewedDistribution(t *testing.T) { + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + {{if ne .GnarkImport "" -}} + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])){{end}} + } +} + +func TestMSM{{.CurvePrefix}}MultiDevice(t *testing.T) { + numDevices, _ := cr.GetDeviceCount() + fmt.Println("There are ", numDevices, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + wg.Add(1) + cr.RunOnDevice(i, func(args ...any) { + defer wg.Done() + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) + points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + cr.SynchronizeStream(&stream) + {{if ne .GnarkImport "" -}}// Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])){{end}} + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/internal/generator/ntt/generate.go b/wrappers/golang_v3/internal/generator/ntt/generate.go new file mode 100644 index 000000000..740a0f2a2 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ntt/generate.go @@ -0,0 +1,54 @@ +package ntt + +import ( + "path" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var nttTemplates = map[string]string{ + "src": "ntt/templates/ntt.go.tmpl", + "test": "ntt/templates/ntt_test.go.tmpl", + "testNoDomain": "ntt/templates/ntt_no_domain_test.go.tmpl", + "header": "ntt/templates/ntt.h.tmpl", +} + +func Generate(baseDir, additionalDirPath, field, fieldPrefix, gnarkImport string, rou int, withDomain bool, fieldNoDomain, fieldNoDomainPrefix string) { + baseImportPathNoDomain := "" + if !withDomain { + baseImportPathNoDomain = path.Join(baseDir, additionalDirPath) + } + + data := struct { + PackageName string + Field string + FieldPrefix string + WithDomain bool + BaseImportPath string + GnarkImport string + ROU int + FieldNoDomain string + FieldNoDomainPrefix string + BaseImportPathNoDomain string + }{ + "ntt", + field, + fieldPrefix, + withDomain, + baseDir, + gnarkImport, + rou, + fieldNoDomain, + fieldNoDomainPrefix, + baseImportPathNoDomain, + } + + testPath := nttTemplates["test"] + if !withDomain { + testPath = nttTemplates["testNoDomain"] + } + + generator.GenerateFile(nttTemplates["src"], path.Join(baseDir, additionalDirPath, "ntt"), "", "", data) + generator.GenerateFile(nttTemplates["header"], path.Join(baseDir, additionalDirPath, "ntt", "include"), "", "", data) + generator.GenerateFile(testPath, path.Join(baseDir, "tests"), "", "", data) +} diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt.go.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt.go.tmpl new file mode 100644 index 000000000..eef062816 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt.go.tmpl @@ -0,0 +1,58 @@ +package {{.PackageName}} + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + {{if .WithDomain}}{{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}"{{end}} + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +{{if .WithDomain}} +import ( + "unsafe" +){{end}} + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(size) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(cfgPointer) + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.{{if .WithDomain}}{{.Field}}{{else}}{{.FieldNoDomain}}{{end}}_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} +{{if .WithDomain}} +func GetDefaultNttConfig() core.NTTConfig[[{{.Field}}.{{toConst .FieldPrefix}}LIMBS]uint32] { + cosetGenField := {{.Field}}.{{.FieldPrefix}}Field{} + cosetGenField.One() + var cosetGen [{{.Field}}.{{toConst .FieldPrefix}}LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func InitDomain(primitiveRoot {{.Field}}.{{.FieldPrefix}}Field, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.{{.Field}}_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + __ret := C.{{.Field}}_release_domain(cCtx) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} +{{end}} \ No newline at end of file diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt.h.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt.h.tmpl new file mode 100644 index 000000000..76f74bdc0 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt.h.tmpl @@ -0,0 +1,24 @@ +#include +#include + +#ifndef _{{if .WithDomain}}{{toUpper .Field}}{{else}}{{toUpper .FieldNoDomain}}{{end}}_NTT_H +#define _{{if .WithDomain}}{{toUpper .Field}}{{else}}{{toUpper .FieldNoDomain}}{{end}}_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct NTTConfig NTTConfig; +{{if .WithDomain}}typedef struct DeviceContext DeviceContext;{{end}} + +cudaError_t {{if .WithDomain}}{{.Field}}{{else}}{{.FieldNoDomain}}{{end}}_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +{{if .WithDomain -}} +cudaError_t {{.Field}}_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); +cudaError_t {{.Field}}_release_domain(DeviceContext* ctx);{{end}} + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_no_domain_test.go.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_no_domain_test.go.tmpl new file mode 100644 index 000000000..0317695b2 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_no_domain_test.go.tmpl @@ -0,0 +1,85 @@ +package tests + +import ( + {{if ne .GnarkImport "" -}} + "reflect" + {{end -}} + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + {{.FieldNoDomain}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPathNoDomain}}" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt" +) + +func TestNttNoDomain(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := {{.FieldNoDomain}}.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[{{.FieldNoDomain}}.{{.FieldNoDomainPrefix}}Field](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[{{.FieldNoDomain}}.{{.FieldNoDomainPrefix}}Field], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + } + } +} + +func TestNttDeviceAsyncNoDomain(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := {{.FieldNoDomain}}.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[{{.FieldNoDomain}}.{{.FieldNoDomainPrefix}}Field](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[{{.FieldNoDomain}}.{{.FieldNoDomainPrefix}}Field], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + } + } + } +} + +func TestNttBatchNoDomain(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + largestTestSize := 12 + largestBatchSize := 100 + scalars := {{.FieldNoDomain}}.GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{2, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[{{.FieldNoDomain}}.{{.FieldNoDomainPrefix}}Field](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[{{.FieldNoDomain}}.{{.FieldNoDomainPrefix}}Field], totalSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + } + } +} diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl new file mode 100644 index 000000000..19b324902 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl @@ -0,0 +1,277 @@ +package tests + +import ( + {{if ne .GnarkImport "" -}} + "reflect" + {{end -}} + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt" + {{if ne .GnarkImport "" -}} + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr" + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr/fft" + {{end -}} + "github.com/stretchr/testify/assert" +) + +{{if ne .GnarkImport "" -}} +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], output core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], order core.Ordering, direction core.NTTDir) bool { + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) +} + +func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} +{{end -}} + +func TestNTTGetDefaultConfig(t *testing.T) { + actual := ntt.GetDefaultNttConfig() + expected := test_helpers.GenerateLimbOne(int({{.Field}}.{{toConst .FieldPrefix}}LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := {{.Field}}.{{.FieldPrefix}}Field{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := {{.Field}}.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[{{.Field}}.{{.FieldPrefix}}Field](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + {{if ne .GnarkImport "" -}} + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + {{end -}} + } + } +} +{{if ne .GnarkImport "" -}} +func TestNttFrElement(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := make([]fr.Element, 4) + var x fr.Element + for i := 0; i < 4; i++ { + x.SetRandom() + scalars[i] = x + } + + for _, size := range []int{4} { + for _, v := range [1]core.Ordering{core.KNN} { + testSize := size + + scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[fr.Element], testSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} +{{end}} +func TestNttDeviceAsync(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + scalars := {{.Field}}.GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[{{.Field}}.{{.FieldPrefix}}Field](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + {{if ne .GnarkImport "" -}} + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + {{end -}} + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + largestTestSize := 12 + largestBatchSize := 100 + scalars := {{.Field}}.GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{2, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[{{.Field}}.{{.FieldPrefix}}Field](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], totalSize) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + + {{if ne .GnarkImport "" -}} + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + {{end -}} + } + } +} + +func TestReleaseDomain(t *testing.T) { + t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") + cfg := ntt.GetDefaultNttConfig() + e := ntt.ReleaseDomain(cfg.Ctx) + assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := ntt.GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[{{.FieldPrefix}}Field] +// for _, v := range scalars { +// var scalar {{.FieldPrefix}}Field +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := {{.FieldPrefix}}Field{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[{{.FieldPrefix}}Field], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang_v3/internal/generator/polynomial/generate.go b/wrappers/golang_v3/internal/generator/polynomial/generate.go new file mode 100644 index 000000000..f91eedd56 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/polynomial/generate.go @@ -0,0 +1,31 @@ +package polynomial + +import ( + "path" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var polynomialTemplates = map[string]string{ + "src": "polynomial/templates/polynomial.go.tmpl", + "test": "polynomial/templates/polynomial_test.go.tmpl", + "header": "polynomial/templates/polynomial.h.tmpl", +} + +func Generate(baseDir, field, fieldPrefix, gnarkImport string) { + data := struct { + Field string + FieldPrefix string + BaseImportPath string + GnarkImport string + }{ + field, + fieldPrefix, + baseDir, + gnarkImport, + } + + generator.GenerateFile(polynomialTemplates["src"], path.Join(baseDir, "polynomial"), "", "", data) + generator.GenerateFile(polynomialTemplates["header"], path.Join(baseDir, "polynomial", "include"), "", "", data) + generator.GenerateFile(polynomialTemplates["test"], path.Join(baseDir, "tests"), "", "", data) +} diff --git a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.go.tmpl b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.go.tmpl new file mode 100644 index 000000000..6a523ac19 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.go.tmpl @@ -0,0 +1,176 @@ +package polynomial + +// #cgo CFLAGS: -I./include/ +// #include "polynomial.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" +) + +type PolynomialHandle = C.struct_PolynomialInst + +type DensePolynomial struct { + handle *PolynomialHandle +} + +func InitPolyBackend() bool { + return (bool)(C.{{.Field}}_polynomial_init_cuda_backend()) +} + +func (up *DensePolynomial) Print() { + C.{{.Field}}_polynomial_print(up.handle) +} + +func (up *DensePolynomial) CreateFromCoeffecitients(coeffs core.HostOrDeviceSlice) DensePolynomial { + if coeffs.IsOnDevice() { + coeffs.(core.DeviceSlice).CheckDevice() + } + coeffsPointer := (*C.scalar_t)(coeffs.AsUnsafePointer()) + cSize := (C.size_t)(coeffs.Len()) + up.handle = C.{{.Field}}_polynomial_create_from_coefficients(coeffsPointer, cSize) + return *up +} + +func (up *DensePolynomial) CreateFromROUEvaluations(evals core.HostOrDeviceSlice) DensePolynomial { + evalsPointer := (*C.scalar_t)(evals.AsUnsafePointer()) + cSize := (C.size_t)(evals.Len()) + up.handle = C.{{.Field}}_polynomial_create_from_coefficients(evalsPointer, cSize) + return *up +} + +func (up *DensePolynomial) Clone() DensePolynomial { + return DensePolynomial{ + handle: C.{{.Field}}_polynomial_clone(up.handle), + } +} + +// TODO @jeremyfelder: Maybe this should be in a SetFinalizer that is set on Create functions? +func (up *DensePolynomial) Delete() { + C.{{.Field}}_polynomial_delete(up.handle) +} + +func (up *DensePolynomial) Add(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.{{.Field}}_polynomial_add(up.handle, b.handle), + } +} + +func (up *DensePolynomial) AddInplace(b *DensePolynomial) { + C.{{.Field}}_polynomial_add_inplace(up.handle, b.handle) +} + +func (up *DensePolynomial) Subtract(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.{{.Field}}_polynomial_subtract(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Multiply(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.{{.Field}}_polynomial_multiply(up.handle, b.handle), + } +} + +func (up *DensePolynomial) MultiplyByScalar(scalar {{.Field}}.{{.FieldPrefix}}Field) DensePolynomial { + cScalar := (*C.scalar_t)(unsafe.Pointer(scalar.AsPointer())) + return DensePolynomial{ + handle: C.{{.Field}}_polynomial_multiply_by_scalar(up.handle, cScalar), + } +} + +func (up *DensePolynomial) Divide(b *DensePolynomial) (DensePolynomial, DensePolynomial) { + var q, r *PolynomialHandle + C.{{.Field}}_polynomial_division(up.handle, b.handle, &q, &r) + return DensePolynomial{ + handle: q, + }, DensePolynomial{ + handle: r, + } +} + +func (up *DensePolynomial) Quotient(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.{{.Field}}_polynomial_quotient(up.handle, b.handle), + } +} + +func (up *DensePolynomial) Remainder(b *DensePolynomial) DensePolynomial { + return DensePolynomial{ + handle: C.{{.Field}}_polynomial_remainder(up.handle, b.handle), + } +} + +func (up *DensePolynomial) DivideByVanishing(vanishing_degree uint64) DensePolynomial { + cVanishingDegree := (C.ulong)(vanishing_degree) + return DensePolynomial{ + handle: C.{{.Field}}_polynomial_divide_by_vanishing(up.handle, cVanishingDegree), + } +} + +func (up *DensePolynomial) AddMonomial(monomialCoeff {{.Field}}.{{.FieldPrefix}}Field, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]{{.Field}}.{{.FieldPrefix}}Field{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.{{.Field}}_polynomial_add_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) SubMonomial(monomialCoeff {{.Field}}.{{.FieldPrefix}}Field, monomial uint64) DensePolynomial { + hs := core.HostSliceFromElements([]{{.Field}}.{{.FieldPrefix}}Field{monomialCoeff}) + cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer()) + cMonomial := (C.ulong)(monomial) + C.{{.Field}}_polynomial_sub_monomial_inplace(up.handle, cMonomialCoeff, cMonomial) + return *up +} + +func (up *DensePolynomial) Eval(x {{.Field}}.{{.FieldPrefix}}Field) {{.Field}}.{{.FieldPrefix}}Field { + domains := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], 1) + domains[0] = x + evals := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], 1) + up.EvalOnDomain(domains, evals) + return evals[0] +} + +func (up *DensePolynomial) EvalOnDomain(domain, evals core.HostOrDeviceSlice) core.HostOrDeviceSlice { + cDomain := (*C.scalar_t)(domain.AsUnsafePointer()) + cDomainSize := (C.size_t)(domain.Len()) + cEvals := (*C.scalar_t)(evals.AsUnsafePointer()) + C.{{.Field}}_polynomial_evaluate_on_domain(up.handle, cDomain, cDomainSize, cEvals) + return evals +} + +func (up *DensePolynomial) Degree() int { + return int(C.{{.Field}}_polynomial_degree(up.handle)) +} + +func (up *DensePolynomial) CopyCoeffsRange(start, end int, out core.HostOrDeviceSlice) (int, core.HostOrDeviceSlice) { + cStart := (C.size_t)(start) + cEnd := (C.size_t)(end) + cScalarOut := (*C.scalar_t)(out.AsUnsafePointer()) + __cNumCoeffsRead := C.{{.Field}}_polynomial_copy_coeffs_range(up.handle, cScalarOut, cStart, cEnd) + return int(__cNumCoeffsRead), out +} + +func (up *DensePolynomial) GetCoeff(idx int) {{.Field}}.{{.FieldPrefix}}Field { + out := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], 1) + up.CopyCoeffsRange(idx, idx, out) + return out[0] +} + +func (up *DensePolynomial) Even() DensePolynomial { + evenPoly := C.{{.Field}}_polynomial_even(up.handle) + return DensePolynomial{ + handle: evenPoly, + } +} + +func (up *DensePolynomial) Odd() DensePolynomial { + oddPoly := C.{{.Field}}_polynomial_odd(up.handle) + return DensePolynomial{ + handle: oddPoly, + } +} diff --git a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.h.tmpl b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.h.tmpl new file mode 100644 index 000000000..4c3c3dedd --- /dev/null +++ b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.h.tmpl @@ -0,0 +1,51 @@ +#include +#include + +#ifndef _{{toUpper .Field}}_POLY_H +#define _{{toUpper .Field}}_POLY_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PolynomialInst PolynomialInst; +typedef struct IntegrityPointer IntegrityPointer; + +bool {{.Field}}_polynomial_init_cuda_backend(); +PolynomialInst* {{.Field}}_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); +PolynomialInst* {{.Field}}_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); +PolynomialInst* {{.Field}}_polynomial_clone(const PolynomialInst* p); +void {{.Field}}_polynomial_print(PolynomialInst* p); +void {{.Field}}_polynomial_delete(PolynomialInst* instance); +PolynomialInst* {{.Field}}_polynomial_add(const PolynomialInst* a, const PolynomialInst* b); +void {{.Field}}_polynomial_add_inplace(PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* {{.Field}}_polynomial_subtract(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* {{.Field}}_polynomial_multiply(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* {{.Field}}_polynomial_multiply_by_scalar(const PolynomialInst* a, const scalar_t* scalar); +void {{.Field}}_polynomial_division(const PolynomialInst* a, const PolynomialInst* b, PolynomialInst** q /*OUT*/, PolynomialInst** r /*OUT*/); +PolynomialInst* {{.Field}}_polynomial_quotient(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* {{.Field}}_polynomial_remainder(const PolynomialInst* a, const PolynomialInst* b); +PolynomialInst* {{.Field}}_polynomial_divide_by_vanishing(const PolynomialInst* p, size_t vanishing_poly_degree); +void {{.Field}}_polynomial_add_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void {{.Field}}_polynomial_sub_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial); +void {{.Field}}_polynomial_evaluate_on_domain(const PolynomialInst* p, scalar_t* domain, size_t domain_size, scalar_t* evals /*OUT*/); +size_t {{.Field}}_polynomial_degree(PolynomialInst* p); +size_t {{.Field}}_polynomial_copy_coeffs_range(PolynomialInst* p, scalar_t* memory, size_t start_idx, size_t end_idx); +PolynomialInst* {{.Field}}_polynomial_even(PolynomialInst* p); +PolynomialInst* {{.Field}}_polynomial_odd(PolynomialInst* p); + +// scalar_t* {{.Field}}_polynomial_get_coeffs_raw_ptr(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// PolynomialInst* {{.Field}}_polynomial_slice(PolynomialInst* p, size_t offset, size_t stride, size_t size); +// IntegrityPointer* {{.Field}}_polynomial_get_coeff_view(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// IntegrityPointer* {{.Field}}_polynomial_get_rou_evaluations_view(PolynomialInst* p, size_t nof_evals, bool is_reversed, size_t* size /*OUT*/, size_t* device_id /*OUT*/); +// const scalar_t* {{.Field}}_polynomial_intergrity_ptr_get(IntegrityPointer* p); +// bool {{.Field}}_polynomial_intergrity_ptr_is_valid(IntegrityPointer* p); +// void {{.Field}}_polynomial_intergrity_ptr_destroy(IntegrityPointer* p); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial_test.go.tmpl b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial_test.go.tmpl new file mode 100644 index 000000000..b2adefa47 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial_test.go.tmpl @@ -0,0 +1,229 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/vecOps" + "github.com/stretchr/testify/assert" +) + +var one, two, three, four, five {{.Field}}.{{.FieldPrefix}}Field + +func init() { + one.One() + two.FromUint32(2) + three.FromUint32(3) + four.FromUint32(4) + five.FromUint32(5) +} + +func rand() {{.Field}}.{{.FieldPrefix}}Field { + return {{.Field}}.GenerateScalars(1)[0] +} + +func randomPoly(size int) (f polynomial.DensePolynomial) { + f.CreateFromCoeffecitients(core.HostSliceFromElements({{.Field}}.GenerateScalars(size))) + return f +} + +func vecOp(a, b {{.Field}}.{{.FieldPrefix}}Field, op core.VecOps) {{.Field}}.{{.FieldPrefix}}Field { + ahost := core.HostSliceWithValue(a, 1) + bhost := core.HostSliceWithValue(b, 1) + out := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], 1) + + cfg := core.DefaultVecOpsConfig() + vecOps.VecOp(ahost, bhost, out, cfg, op) + return out[0] +} + +func TestPolyCreateFromCoefficients(t *testing.T) { + scalars := {{.Field}}.GenerateScalars(33) + var uniPoly polynomial.DensePolynomial + + poly := uniPoly.CreateFromCoeffecitients(scalars) + poly.Print() +} + +func TestPolyEval(t *testing.T) { + // testing correct evaluation of f(8) for f(x)=4x^2+2x+5 + coeffs := core.HostSliceFromElements([]{{.Field}}.{{.FieldPrefix}}Field{five, two, four}) + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(coeffs) + + var x {{.Field}}.{{.FieldPrefix}}Field + x.FromUint32(8) + domains := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], 1) + domains[0] = x + evals := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], 1) + fEvaled := f.EvalOnDomain(domains, evals) + var expected {{.Field}}.{{.FieldPrefix}}Field + assert.Equal(t, expected.FromUint32(277), fEvaled.(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field])[0]) +} + +func TestPolyClone(t *testing.T) { + f := randomPoly(8) + x := rand() + fx := f.Eval(x) + + g := f.Clone() + fg := f.Add(&g) + + gx := g.Eval(x) + fgx := fg.Eval(x) + + assert.Equal(t, fx, gx) + assert.Equal(t, vecOp(fx, gx, core.Add), fgx) +} + +func TestPolyAddSubMul(t *testing.T) { + testSize := 1 << 10 + f := randomPoly(testSize) + g := randomPoly(testSize) + x := rand() + + fx := f.Eval(x) + gx := g.Eval(x) + + polyAdd := f.Add(&g) + fxAddgx := vecOp(fx, gx, core.Add) + assert.Equal(t, polyAdd.Eval(x), fxAddgx) + + polySub := f.Subtract(&g) + fxSubgx := vecOp(fx, gx, core.Sub) + assert.Equal(t, polySub.Eval(x), fxSubgx) + + polyMul := f.Multiply(&g) + fxMulgx := vecOp(fx, gx, core.Mul) + assert.Equal(t, polyMul.Eval(x), fxMulgx) + + s1 := rand() + polMulS1 := f.MultiplyByScalar(s1) + assert.Equal(t, polMulS1.Eval(x), vecOp(fx, s1, core.Mul)) + + s2 := rand() + polMulS2 := f.MultiplyByScalar(s2) + assert.Equal(t, polMulS2.Eval(x), vecOp(fx, s2, core.Mul)) +} + +func TestPolyMonomials(t *testing.T) { + var zero {{.Field}}.{{.FieldPrefix}}Field + var f polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements([]{{.Field}}.{{.FieldPrefix}}Field{one, zero, two})) + x := rand() + + fx := f.Eval(x) + f.AddMonomial(three, 1) + fxAdded := f.Eval(x) + assert.Equal(t, fxAdded, vecOp(fx, vecOp(three, x, core.Mul), core.Add)) + + f.SubMonomial(one, 0) + fxSub := f.Eval(x) + assert.Equal(t, fxSub, vecOp(fxAdded, one, core.Sub)) +} + +func TestPolyReadCoeffs(t *testing.T) { + var f polynomial.DensePolynomial + coeffs := core.HostSliceFromElements([]{{.Field}}.{{.FieldPrefix}}Field{one, two, three, four}) + f.CreateFromCoeffecitients(coeffs) + coeffsCopied := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], coeffs.Len()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsCopied) + assert.ElementsMatch(t, coeffs, coeffsCopied) + + var coeffsDevice core.DeviceSlice + coeffsDevice.Malloc(coeffs.Len()*one.Size(), one.Size()) + _, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsDevice) + coeffsHost := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], coeffs.Len()) + coeffsHost.CopyFromDevice(&coeffsDevice) + + assert.ElementsMatch(t, coeffs, coeffsHost) +} + +func TestPolyOddEvenSlicing(t *testing.T) { + size := 1<<10 - 3 + f := randomPoly(size) + + even := f.Even() + odd := f.Odd() + assert.Equal(t, f.Degree(), even.Degree()+odd.Degree()+1) + + x := rand() + var evenExpected, oddExpected {{.Field}}.{{.FieldPrefix}}Field + for i := size; i >= 0; i-- { + if i%2 == 0 { + mul := vecOp(evenExpected, x, core.Mul) + evenExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } else { + mul := vecOp(oddExpected, x, core.Mul) + oddExpected = vecOp(mul, f.GetCoeff(i), core.Add) + } + } + + evenEvaled := even.Eval(x) + assert.Equal(t, evenExpected, evenEvaled) + + oddEvaled := odd.Eval(x) + assert.Equal(t, oddExpected, oddEvaled) +} + +func TestPolynomialDivision(t *testing.T) { + // divide f(x)/g(x), compute q(x), r(x) and check f(x)=q(x)*g(x)+r(x) + var f, g polynomial.DensePolynomial + f.CreateFromCoeffecitients(core.HostSliceFromElements({{.Field}}.GenerateScalars(1 << 4))) + g.CreateFromCoeffecitients(core.HostSliceFromElements({{.Field}}.GenerateScalars(1 << 2))) + + q, r := f.Divide(&g) + + qMulG := q.Multiply(&g) + fRecon := qMulG.Add(&r) + + x := {{.Field}}.GenerateScalars(1)[0] + fEval := f.Eval(x) + fReconEval := fRecon.Eval(x) + assert.Equal(t, fEval, fReconEval) +} + +func TestDivideByVanishing(t *testing.T) { + // poly of x^4-1 vanishes ad 4th rou + var zero {{.Field}}.{{.FieldPrefix}}Field + minus_one := vecOp(zero, one, core.Sub) + coeffs := core.HostSliceFromElements([]{{.Field}}.{{.FieldPrefix}}Field{minus_one, zero, zero, zero, one}) // x^4-1 + var v polynomial.DensePolynomial + v.CreateFromCoeffecitients(coeffs) + + f := randomPoly(1 << 3) + + fv := f.Multiply(&v) + fDegree := f.Degree() + fvDegree := fv.Degree() + assert.Equal(t, fDegree+4, fvDegree) + + fReconstructed := fv.DivideByVanishing(4) + assert.Equal(t, fDegree, fReconstructed.Degree()) + + x := rand() + assert.Equal(t, f.Eval(x), fReconstructed.Eval(x)) +} + +// func TestPolySlice(t *testing.T) { +// size := 4 +// coeffs := {{.Field}}.GenerateScalars(size) +// var f DensePolynomial +// f.CreateFromCoeffecitients(coeffs) +// fSlice := f.AsSlice() +// assert.True(t, fSlice.IsOnDevice()) +// assert.Equal(t, size, fSlice.Len()) + +// hostSlice := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], size) +// hostSlice.CopyFromDevice(fSlice) +// assert.Equal(t, coeffs, hostSlice) + +// cfg := ntt.GetDefaultNttConfig() +// res := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], size) +// ntt.Ntt(fSlice, core.KForward, cfg, res) + +// assert.Equal(t, f.Eval(one), res[0]) +// } diff --git a/wrappers/golang_v3/internal/generator/poseidon/generate.go b/wrappers/golang_v3/internal/generator/poseidon/generate.go new file mode 100644 index 000000000..3b20149b5 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/poseidon/generate.go @@ -0,0 +1,32 @@ +package poseidon + +import ( + "path" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var poseidonTemplates = map[string]string{ + "src": "poseidon/templates/poseidon.go.tmpl", + "test": "poseidon/templates/poseidon_test.go.tmpl", + "header": "poseidon/templates/poseidon.h.tmpl", +} + +func Generate(baseDir, additionalDirPath, field, fieldPrefix string) { + + data := struct { + PackageName string + Field string + FieldPrefix string + BaseImportPath string + }{ + "poseidon", + field, + fieldPrefix, + baseDir, + } + + generator.GenerateFile(poseidonTemplates["src"], path.Join(baseDir, additionalDirPath, "poseidon"), "", "", data) + generator.GenerateFile(poseidonTemplates["header"], path.Join(baseDir, additionalDirPath, "poseidon", "include"), "", "", data) + generator.GenerateFile(poseidonTemplates["test"], path.Join(baseDir, "tests"), "", "", data) +} diff --git a/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.go.tmpl b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.go.tmpl new file mode 100644 index 000000000..ca83d4bbd --- /dev/null +++ b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.go.tmpl @@ -0,0 +1,57 @@ +package {{.PackageName}} + +// #cgo CFLAGS: -I./include/ +// #include "poseidon.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +) + +func GetDefaultPoseidonConfig() core.PoseidonConfig { + return core.GetDefaultPoseidonConfig() +} + +func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { + scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) + + cScalars := (*C.scalar_t)(scalarsPointer) + cResults := (*C.scalar_t)(resultsPointer) + cNumberOfStates := (C.int)(numberOfStates) + cArity := (C.int)(constants.Arity) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + cCfg := (*C.PoseidonConfig)(cfgPointer) + + __ret := C.{{.Field}}_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) + + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cFullRoundsHalfs := (C.int)(fullRoundsHalfs) + cPartialRounds := (C.int)(partialRounds) + cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) + + __ret := C.{{.Field}}_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { + + cArity := (C.int)(arity) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) + + __ret := C.{{.Field}}_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.h.tmpl b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.h.tmpl new file mode 100644 index 000000000..e5ac4d1dd --- /dev/null +++ b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.h.tmpl @@ -0,0 +1,25 @@ +#include +#include + +#ifndef _{{toUpper .Field}}_POSEIDON_H +#define _{{toUpper .Field}}_POSEIDON_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct PoseidonConfig PoseidonConfig; +typedef struct DeviceContext DeviceContext; +typedef struct PoseidonConstants PoseidonConstants; + + +cudaError_t {{.Field}}_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); +cudaError_t {{.Field}}_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); +cudaError_t {{.Field}}_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon_test.go.tmpl b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon_test.go.tmpl new file mode 100644 index 000000000..13aeedc2e --- /dev/null +++ b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon_test.go.tmpl @@ -0,0 +1,59 @@ +package tests + +import ( + "testing" + + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/poseidon" + + {{if eq .Field "bls12_381"}} + "fmt" + "github.com/stretchr/testify/assert" + {{end}} +) +{{if eq .Field "bls12_381"}} +func formatOutput(x {{.Field}}.{{.FieldPrefix}}Field) string { + r := x.GetLimbs() + return fmt.Sprintf("%08x%08x%08x%08x%08x%08x%08x%08x", r[7], r[6], r[5], r[4], r[3], r[2], r[1], r[0]) +} +{{end}} + +func TestPoseidon(t *testing.T) { + + arity := 2 + numberOfStates := 1 + + cfg := poseidon.GetDefaultPoseidonConfig() + cfg.IsAsync = true + stream, _ := cr.CreateStream() + cfg.Ctx.Stream = &stream + + var constants core.PoseidonConstants[{{.Field}}.{{.FieldPrefix}}Field] + + poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants + + scalars := {{.Field}}.GenerateScalars(numberOfStates * arity) + scalars[0] = scalars[0].Zero() + scalars[1] = scalars[0].Zero() + + scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function + + output := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], numberOfStates) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + {{if eq .Field "bls12_381"}} + expectedString := "48fe0b1331196f6cdb33a7c6e5af61b76fd388e1ef1d3d418be5147f0e4613d4" //This result is from https://github.com/triplewz/poseidon + outputString := formatOutput(output[0]) + + assert.Equal(t, outputString, expectedString, "Poseidon hash does not match expected result") + {{end}} +} diff --git a/wrappers/golang_v3/internal/generator/tests/generate.go b/wrappers/golang_v3/internal/generator/tests/generate.go new file mode 100644 index 000000000..3e4d733bc --- /dev/null +++ b/wrappers/golang_v3/internal/generator/tests/generate.go @@ -0,0 +1,29 @@ +package tests + +import ( + "path" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +func Generate(baseDir, field, fieldPrefix, gnarkImport string, rou int, supportsNTT, supportsPoly bool) { + data := struct { + Field string + FieldPrefix string + BaseImportPath string + GnarkImport string + ROU int + SupportsNTT bool + SupportsPoly bool + }{ + field, + fieldPrefix, + baseDir, + gnarkImport, + rou, + supportsNTT, + supportsPoly, + } + + generator.GenerateFile("tests/templates/main_test.go.tmpl", path.Join(baseDir, "tests"), "", "", data) +} diff --git a/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl b/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl new file mode 100644 index 000000000..1ecfca605 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl @@ -0,0 +1,58 @@ +package tests + +import ( + "os" + "testing" + + {{if or .SupportsNTT .SupportsPoly -}} + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}"{{end}} + {{if .SupportsNTT -}} + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt"{{end}} + {{if .SupportsPoly -}} + poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/polynomial"{{end}} + + {{if ne .GnarkImport "" -}} + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr/fft" + {{end -}} +) + +const ( + largestTestSize = 20 +) +{{if or .SupportsNTT .SupportsPoly -}} +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { + {{if ne .GnarkImport "" -}} + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := {{.Field}}.{{.FieldPrefix}}Field{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + {{else -}} + rouIcicle := {{.Field}}.{{.FieldPrefix}}Field{} + rouIcicle.FromUint32({{.ROU}}) + {{end -}} + e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + return e +}{{end}} + +func TestMain(m *testing.M) { + {{if .SupportsPoly -}}poly.InitPolyBackend(){{end}} + + {{if or .SupportsNTT .SupportsPoly -}}// setup domain + cfg := ntt.GetDefaultNttConfig() + e := initDomain(largestTestSize, cfg) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("initDomain failed") + }{{end}} + + // execute tests + os.Exit(m.Run()) + + {{if or .SupportsNTT .SupportsPoly -}}// release domain + e = ntt.ReleaseDomain(cfg.Ctx) + if e.IcicleErrorCode != core.IcicleErrorCode(0) { + panic("ReleaseDomain failed") + }{{end}} +} diff --git a/wrappers/golang_v3/internal/generator/vecOps/generate.go b/wrappers/golang_v3/internal/generator/vecOps/generate.go new file mode 100644 index 000000000..a5e72497e --- /dev/null +++ b/wrappers/golang_v3/internal/generator/vecOps/generate.go @@ -0,0 +1,39 @@ +package vecops + +import ( + "path" + + generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" +) + +var vecOpsTemplates = map[string]string{ + "src": "vecOps/templates/vec_ops.go.tmpl", + "test": "vecOps/templates/vec_ops_test.go.tmpl", + "header": "vecOps/templates/vec_ops.h.tmpl", +} + +func Generate(baseDir, field, fieldPrefix string) { + data := struct { + PackageName string + Field string + FieldPrefix string + BaseImportPath string + }{ + "vecOps", + field, + fieldPrefix, + baseDir, + } + + testDir := "tests" + filePrefix := "" + parentDir := path.Base(baseDir) + if parentDir == "extension" { + testDir = "../tests" + filePrefix = "extension_" + } + + generator.GenerateFile(vecOpsTemplates["src"], path.Join(baseDir, "vecOps"), "", "", data) + generator.GenerateFile(vecOpsTemplates["header"], path.Join(baseDir, "vecOps", "include"), "", "", data) + generator.GenerateFile(vecOpsTemplates["test"], path.Join(baseDir, testDir), filePrefix, "", data) +} diff --git a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.go.tmpl b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.go.tmpl new file mode 100644 index 000000000..4377bc012 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.go.tmpl @@ -0,0 +1,48 @@ +package {{.PackageName}} + +// #cgo CFLAGS: -I./include/ +// #include "vec_ops.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + + "unsafe" +) + +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Sub: + ret = (cr.CudaError)(C.{{.Field}}_sub_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Add: + ret = (cr.CudaError)(C.{{.Field}}_add_cuda(cA, cB, cSize, cConfig, cOut)) + case core.Mul: + ret = (cr.CudaError)(C.{{.Field}}_mul_cuda(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} + +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError){ + core.TransposeCheck(in, out, onDevice) + + cIn := (*C.scalar_t)(in.AsUnsafePointer()) + cOut := (*C.scalar_t)(out.AsUnsafePointer()) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cRowSize := (C.int)(rowSize) + cColumnSize := (C.int)(columnSize) + cOnDevice := (C._Bool)(onDevice) + cIsAsync := (C._Bool)(isAsync) + + err := (cr.CudaError)(C.{{.Field}}_transpose_matrix_cuda( cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) + return core.FromCudaError(err) +} diff --git a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.h.tmpl b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.h.tmpl new file mode 100644 index 000000000..9f3c9eff0 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.h.tmpl @@ -0,0 +1,53 @@ +#include +#include + +#ifndef _{{toUpper .Field}}_VEC_OPS_H +#define _{{toUpper .Field}}_VEC_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scalar_t scalar_t; +typedef struct VecOpsConfig VecOpsConfig; +typedef struct DeviceContext DeviceContext; + +cudaError_t {{.Field}}_mul_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t {{.Field}}_add_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t {{.Field}}_sub_cuda( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + +cudaError_t {{.Field}}_transpose_matrix_cuda( + scalar_t* mat_in, + int row_size, + int column_size, + scalar_t* mat_out, + DeviceContext* ctx, + bool on_device, + bool is_async +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops_test.go.tmpl b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops_test.go.tmpl new file mode 100644 index 000000000..817a5dba6 --- /dev/null +++ b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops_test.go.tmpl @@ -0,0 +1,69 @@ +package tests + +import ( + "testing" + + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/vecOps" + "github.com/stretchr/testify/assert" +) + +func Test{{capitalize .Field}}VecOps(t *testing.T) { + testSize := 1 << 14 + + a := {{.Field}}.GenerateScalars(testSize) + b := {{.Field}}.GenerateScalars(testSize) + var scalar {{.Field}}.{{.FieldPrefix}}Field + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], testSize) + out2 := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], testSize) + out3 := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.VecOp(a, b, out, cfg, core.Add) + vecOps.VecOp(out, b, out2, cfg, core.Sub) + + assert.Equal(t, a, out2) + + vecOps.VecOp(a, ones, out3, cfg, core.Mul) + + assert.Equal(t, a, out3) +} + +func Test{{capitalize .Field}}Transpose(t *testing.T) { + rowSize := 1 << 6 + columnSize := 1 << 8 + onDevice := false + isAsync := false + + matrix := {{.Field}}.GenerateScalars(rowSize * columnSize) + + out := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], rowSize*columnSize) + out2 := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], rowSize*columnSize) + + ctx, _ := cr.GetDefaultDeviceContext() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + + assert.Equal(t, matrix, out2) + + var dMatrix, dOut, dOut2 core.DeviceSlice + onDevice = true + + matrix.CopyToDevice(&dMatrix, true) + dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + output := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], rowSize*columnSize) + output.CopyFromDevice(&dOut2) + + assert.Equal(t, matrix, output) +} diff --git a/wrappers/golang_v3/runtime/config.go b/wrappers/golang_v3/runtime/config.go new file mode 100644 index 000000000..0890381fd --- /dev/null +++ b/wrappers/golang_v3/runtime/config.go @@ -0,0 +1,51 @@ +package runtime + +// #cgo CFLAGS: -I./include/ +// #include "config_extension.h" +import "C" +import ( + "runtime" + "unsafe" +) + +type ConfigExtensionHandler = unsafe.Pointer + +type ConfigExtension struct { + handler ConfigExtensionHandler +} + +func CreateConfigExtension() *ConfigExtension { + ext := &ConfigExtension{handler: C.create_config_extension()} + runtime.SetFinalizer(ext, Delete) + return ext +} + +func Delete(ext *ConfigExtension) { + C.destroy_config_extension(ext.handler) +} + +func (ext *ConfigExtension) SetInt(key string, value int) { + cKey := C.CString(key) + cValue := C.int(value) + C.config_extension_set_int(ext.handler, cKey, cValue) +} + +func (ext *ConfigExtension) SetBool(key string, value bool) { + cKey := C.CString(key) + cValue := C._Bool(value) + C.config_extension_set_bool(ext.handler, cKey, cValue) +} + +func (ext *ConfigExtension) GetInt(key string) int { + cKey := C.CString(key) + return int(C.config_extension_get_int(ext.handler, cKey)) +} + +func (ext *ConfigExtension) GetBool(key string) bool { + cKey := C.CString(key) + return C.config_extension_get_bool(ext.handler, cKey) == C._Bool(true) +} + +func (ext *ConfigExtension) AsUnsafePointer() unsafe.Pointer { + return ext.handler +} diff --git a/wrappers/golang_v3/runtime/device.go b/wrappers/golang_v3/runtime/device.go new file mode 100644 index 000000000..2a3f69d3b --- /dev/null +++ b/wrappers/golang_v3/runtime/device.go @@ -0,0 +1,40 @@ +package runtime + +import "C" +import "unsafe" + +const MAX_TYPE_SIZE = 64 + +type Device struct { + DeviceType [MAX_TYPE_SIZE]C.char + Id C.int +} + +type DeviceProperties struct { + UsingHostMemory bool + NumMemoryRegions int32 + SupportsPinnedMemory bool +} + +func CreateDevice(deviceType string, id int32) Device { + var cDeviceType [MAX_TYPE_SIZE]C.char + for i, v := range deviceType { + if i >= MAX_TYPE_SIZE { + break + } + cDeviceType[i] = C.char(v) + } + // Ensure the last character is null if the source string is too long + if len(deviceType) >= MAX_TYPE_SIZE { + cDeviceType[MAX_TYPE_SIZE-1] = C.char(0) + } + return Device{DeviceType: cDeviceType, Id: C.int(id)} +} + +func (self *Device) GetDeviceType() string { + n := 0 + for n < MAX_TYPE_SIZE && self.DeviceType[n] != 0 { + n++ + } + return C.GoStringN((*C.char)(unsafe.Pointer(&self.DeviceType[0])), C.int(n)) +} diff --git a/wrappers/golang_v3/runtime/errors.go b/wrappers/golang_v3/runtime/errors.go new file mode 100644 index 000000000..a98cdca17 --- /dev/null +++ b/wrappers/golang_v3/runtime/errors.go @@ -0,0 +1,20 @@ +package runtime + +// eIcicleError represents the error codes +type EIcicleError int + +const ( + Success EIcicleError = iota // Operation completed successfully + InvalidDevice // The specified device is invalid + OutOfMemory // Memory allocation failed due to insufficient memory + InvalidPointer // The specified pointer is invalid + AllocationFailed // Memory allocation failed + DeallocationFailed // Memory deallocation failed + CopyFailed // Data copy operation failed + SynchronizationFailed // Device synchronization failed + StreamCreationFailed // Stream creation failed + StreamDestructionFailed // Stream destruction failed + ApiNotImplemented // The API is not implemented for a device + InvalidArgument // Invalid argument passed + UnknownError // An unknown error occurred +) diff --git a/wrappers/golang_v3/runtime/include/config_extension.h b/wrappers/golang_v3/runtime/include/config_extension.h new file mode 100644 index 000000000..4341b79a0 --- /dev/null +++ b/wrappers/golang_v3/runtime/include/config_extension.h @@ -0,0 +1,24 @@ +#include + +#ifndef _CONFIG_EXTENSION_H +#define _CONFIG_EXTENSION_H + +#ifdef __cplusplus +extern "C" { +#endif + +// typedef ConfigExtension ConfigExtension; + +void* create_config_extension(); +void destroy_config_extension(void* ext); +void config_extension_set_int(void* ext, const char* key, int value); +void config_extension_set_bool(void* ext, const char* key, bool value); +int config_extension_get_int(const void* ext, const char* key); +bool config_extension_get_bool(const void* ext, const char* key); +void* clone_config_extension(const void* ext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang_v3/runtime/include/runtime.h b/wrappers/golang_v3/runtime/include/runtime.h new file mode 100644 index 000000000..6be58b4ba --- /dev/null +++ b/wrappers/golang_v3/runtime/include/runtime.h @@ -0,0 +1,41 @@ +#include + +#ifndef _RUNTIME_H +#define _RUNTIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct Device Device; +typedef struct DeviceProperties DeviceProperties; +typedef struct icicleStreamHandle icicleStreamHandle; + +int icicle_load_backend(const char* path, bool is_recursive); +int icicle_set_device(const Device* device); +int icicle_get_active_device(Device* device); +int icicle_is_host_memory(const void* ptr); +int icicle_is_active_device_memory(const void* ptr); +int icicle_get_device_count(int* device_count); +int icicle_malloc(void** ptr, size_t size); +int icicle_malloc_async(void** ptr, size_t size, void* stream); +int icicle_free(void* ptr); +int icicle_free_async(void* ptr, void* stream); +int icicle_get_available_memory(size_t* total, size_t* free); +int icicle_copy_to_host(void* dst, const void* src, size_t size); +int icicle_copy_to_host_async(void* dst, const void* src, size_t size, void* stream); +int icicle_copy_to_device(void* dst, const void* src, size_t size); +int icicle_copy_to_device_async(void* dst, const void* src, size_t size, void* stream); +int icicle_create_stream(void** stream); +int icicle_destroy_stream(void* stream); +int icicle_stream_synchronize(void* stream); +int icicle_device_synchronize(); +int icicle_get_device_properties(DeviceProperties* properties); +int icicle_is_device_avialable(const Device* dev); +int icicle_get_registered_devices(char* output, size_t output_size); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang_v3/runtime/main.go b/wrappers/golang_v3/runtime/main.go new file mode 100644 index 000000000..da22d0b19 --- /dev/null +++ b/wrappers/golang_v3/runtime/main.go @@ -0,0 +1,4 @@ +package runtime + +// #cgo LDFLAGS: -L${SRCDIR}/../../../icicle_v3/build -licicle_device -lstdc++ -lm -Wl,-rpath=${SRCDIR}/../../../icicle_v3/build +import "C" diff --git a/wrappers/golang_v3/runtime/memory.go b/wrappers/golang_v3/runtime/memory.go new file mode 100644 index 000000000..df3bee3c0 --- /dev/null +++ b/wrappers/golang_v3/runtime/memory.go @@ -0,0 +1,76 @@ +package runtime + +// #cgo CFLAGS: -I./include/ +// #include "runtime.h" +import "C" +import "unsafe" + +func Malloc(size uint) (unsafe.Pointer, EIcicleError) { + if size == 0 { + return nil, AllocationFailed + } + + var p C.void + devicePtr := unsafe.Pointer(&p) + cSize := (C.size_t)(size) + + ret := C.icicle_malloc(&devicePtr, cSize) + err := EIcicleError(ret) + + return devicePtr, err +} + +func MallocAsync(size uint, stream Stream) (unsafe.Pointer, EIcicleError) { + if size == 0 { + return nil, AllocationFailed + } + + var p C.void + devicePtr := unsafe.Pointer(&p) + cSize := (C.size_t)(size) + + ret := C.icicle_malloc_async(&devicePtr, cSize, stream) + err := EIcicleError(ret) + + return devicePtr, err +} + +func Free(devicePtr unsafe.Pointer) EIcicleError { + ret := C.icicle_free(devicePtr) + err := EIcicleError(ret) + return err +} + +func FreeAsync(devicePtr unsafe.Pointer, stream Stream) EIcicleError { + ret := C.icicle_free_async(devicePtr, stream) + err := EIcicleError(ret) + return err +} + +func CopyFromDevice(hostDst, deviceSrc unsafe.Pointer, size uint) (unsafe.Pointer, EIcicleError) { + cSize := (C.size_t)(size) + ret := C.icicle_copy_to_host(hostDst, deviceSrc, cSize) + err := (EIcicleError)(ret) + return hostDst, err +} + +func CopyFromDeviceAsync(hostDst, deviceSrc unsafe.Pointer, size uint, stream Stream) EIcicleError { + cSize := (C.size_t)(size) + ret := C.icicle_copy_to_host_async(hostDst, deviceSrc, cSize, stream) + err := (EIcicleError)(ret) + return err +} + +func CopyToDevice(deviceDst, hostSrc unsafe.Pointer, size uint) (unsafe.Pointer, EIcicleError) { + cSize := (C.size_t)(size) + ret := C.icicle_copy_to_device(deviceDst, hostSrc, cSize) + err := (EIcicleError)(ret) + return deviceDst, err +} + +func CopyToDeviceAsync(deviceDst, hostSrc unsafe.Pointer, size uint, stream Stream) EIcicleError { + cSize := (C.size_t)(size) + ret := C.icicle_copy_to_device_async(deviceDst, hostSrc, cSize, stream) + err := (EIcicleError)(ret) + return err +} diff --git a/wrappers/golang_v3/runtime/runtime.go b/wrappers/golang_v3/runtime/runtime.go new file mode 100644 index 000000000..ed90f034b --- /dev/null +++ b/wrappers/golang_v3/runtime/runtime.go @@ -0,0 +1,116 @@ +package runtime + +// #cgo CFLAGS: -I./include/ +// #include "runtime.h" +import "C" +import ( + "os" + "strings" + "unsafe" +) + +func LoadBackend(path string, isRecursive bool) EIcicleError { + cPath := C.CString(path) + cIsRecursive := C._Bool(isRecursive) + cErr := C.icicle_load_backend(cPath, cIsRecursive) + return EIcicleError(cErr) +} + +func LoadBackendFromEnv() EIcicleError { + path := os.Getenv("DEFAULT_BACKEND_INSTALL_DIR") + path = "/home/administrator/users/Timur/Projects/icicle/icicle_v3/build" + return LoadBackend(path, true) +} + +func SetDevice(device *Device) EIcicleError { + cDevice := (*C.Device)(unsafe.Pointer(device)) + cErr := C.icicle_set_device(cDevice) + return EIcicleError(cErr) +} + +func GetActiveDevice() (*Device, EIcicleError) { + device := CreateDevice("invalid", -1) + cDevice := (*C.Device)(unsafe.Pointer(&device)) + cErr := C.icicle_get_active_device(cDevice) + err := EIcicleError(cErr) + if err != Success { + return nil, err + } + return &device, err +} + +func IsDeviceAvailable(device *Device) bool { + cDevice := (*C.Device)(unsafe.Pointer(device)) + cErr := C.icicle_is_device_avialable(cDevice) + return EIcicleError(cErr) == Success +} + +func GetDeviceCount() (int, EIcicleError) { + res := 0 + cRes := (*C.int)(unsafe.Pointer(&res)) + cErr := C.icicle_get_device_count(cRes) + return res, EIcicleError(cErr) +} + +func GetRegisteredDevices() ([]string, EIcicleError) { + const BUFFER_SIZE = 256 + var buffer [BUFFER_SIZE]C.char + cErr := C.icicle_get_registered_devices((*C.char)(unsafe.Pointer(&buffer[0])), BUFFER_SIZE) + err := EIcicleError(cErr) + if err != Success { + return nil, err + } + n := 0 + for n < BUFFER_SIZE && buffer[n] != 0 { + n++ + } + res := C.GoStringN((*C.char)(unsafe.Pointer(&buffer[0])), C.int(n)) + return strings.Split(res, ","), err +} + +func DeviceSynchronize() EIcicleError { + cErr := C.icicle_device_synchronize() + return EIcicleError(cErr) +} + +func GetDeviceProperties() (*DeviceProperties, EIcicleError) { + properties := DeviceProperties{ + UsingHostMemory: false, + NumMemoryRegions: 0, + SupportsPinnedMemory: false, + } + cProperties := (*C.DeviceProperties)(unsafe.Pointer(&properties)) + cErr := C.icicle_get_device_properties(cProperties) + err := EIcicleError(cErr) + if err != Success { + return nil, err + } + return &properties, err +} + +type AvailableMemory struct { + Total uint + Free uint +} + +func GetAvailableMemory() (*AvailableMemory, EIcicleError) { + memory := AvailableMemory{Total: 0, Free: 0} + cTotal := (*C.size_t)(unsafe.Pointer(&memory.Total)) + cFree := (*C.size_t)(unsafe.Pointer(&memory.Free)) + cErr := C.icicle_get_available_memory(cTotal, cFree) + err := EIcicleError(cErr) + if err != Success { + return nil, err + } + return &memory, err +} + +func IsHostMemory(ptr unsafe.Pointer) bool { + cErr := C.icicle_is_host_memory(ptr) + return EIcicleError(cErr) == Success +} + +func IsActiveDeviceMemory(ptr unsafe.Pointer) bool { + cErr := C.icicle_is_active_device_memory(ptr) + return EIcicleError(cErr) == Success +} diff --git a/wrappers/golang_v3/runtime/stream.go b/wrappers/golang_v3/runtime/stream.go new file mode 100644 index 000000000..58b7cc6e7 --- /dev/null +++ b/wrappers/golang_v3/runtime/stream.go @@ -0,0 +1,30 @@ +package runtime + +// #cgo CFLAGS: -I./include/ +// #include "runtime.h" +import "C" +import "unsafe" + +type Stream = unsafe.Pointer + +func CreateStream() (Stream, EIcicleError) { + var stream Stream + ret := C.icicle_create_stream(&stream) + err := (EIcicleError)(ret) + return stream, err +} + +func DestroyStream(stream Stream) EIcicleError { + ret := C.icicle_destroy_stream(stream) + err := (EIcicleError)(ret) + if err == Success { + stream = nil + } + return err +} + +func SynchronizeStream(stream Stream) EIcicleError { + ret := C.icicle_stream_synchronize(stream) + err := (EIcicleError)(ret) + return err +} diff --git a/wrappers/golang_v3/runtime/tests/config_test.go b/wrappers/golang_v3/runtime/tests/config_test.go new file mode 100644 index 000000000..a6752dbde --- /dev/null +++ b/wrappers/golang_v3/runtime/tests/config_test.go @@ -0,0 +1,71 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + + "github.com/stretchr/testify/assert" +) + +func TestConfigExtensionIntValues(t *testing.T) { + config := runtime.CreateConfigExtension() + for i := 0; i < 100; i++ { + config.SetInt("test", i) + assert.Equal(t, config.GetInt("test"), i, "result does not match") + } + for i := 0; i < 100; i++ { + key := fmt.Sprintf("test%d", i) + config.SetInt(key, i) + assert.Equal(t, config.GetInt(key), i, "result does not match") + } + for i := 0; i < 100; i++ { + key := fmt.Sprintf("test%d", i) + config.SetInt(key, i*3) + assert.Equal(t, config.GetInt(key), i*3, "result does not match") + } +} + +func TestConfigExtensionBoolValues(t *testing.T) { + config := runtime.CreateConfigExtension() + for i := 0; i < 100; i++ { + config.SetBool("test", i%2 == 1) + assert.Equal(t, config.GetBool("test"), i%2 == 1, "result does not match") + } + for i := 0; i < 100; i++ { + key := fmt.Sprintf("test%d", i) + config.SetBool(key, i%2 == 1) + assert.Equal(t, config.GetBool(key), i%2 == 1, "result does not match") + } +} + +func TestConfigExtensionSetDifferentValueTypes(t *testing.T) { + config := runtime.CreateConfigExtension() + for i := 0; i < 100; i++ { + key := fmt.Sprintf("test%d", i) + config.SetInt(key, i) + assert.Equal(t, config.GetInt(key), i, "result does not match") + config.SetBool(key, i%2 == 1) + assert.Equal(t, config.GetBool(key), i%2 == 1, "result does not match") + } +} + +func TestConfigExtensionCreateManyConfigs(t *testing.T) { + var configs [5]runtime.ConfigExtension + for i := range configs { + configs[i] = *runtime.CreateConfigExtension() + } + for i := 1; i <= 100; i++ { + key := fmt.Sprintf("test%d", i) + for j, config := range configs { + config.SetInt(key, i*(j+1)) + } + } + for i := 1; i <= 100; i++ { + key := fmt.Sprintf("test%d", i) + for j, config := range configs { + assert.Equal(t, config.GetInt(key), i*(j+1), "result does not match") + } + } +} diff --git a/wrappers/golang_v3/runtime/tests/device_test.go b/wrappers/golang_v3/runtime/tests/device_test.go new file mode 100644 index 000000000..854ac9df4 --- /dev/null +++ b/wrappers/golang_v3/runtime/tests/device_test.go @@ -0,0 +1,16 @@ +package test + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + + "github.com/stretchr/testify/assert" +) + +func TestGetDeviceType(t *testing.T) { + config := runtime.CreateDevice("test", 0) + assert.Equal(t, config.GetDeviceType(), "test") + configLargeName := runtime.CreateDevice("testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest", 1) + assert.Equal(t, configLargeName.GetDeviceType(), "testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttes") +} diff --git a/wrappers/golang_v3/runtime/tests/runtime_test.go b/wrappers/golang_v3/runtime/tests/runtime_test.go new file mode 100644 index 000000000..5925f0da5 --- /dev/null +++ b/wrappers/golang_v3/runtime/tests/runtime_test.go @@ -0,0 +1,84 @@ +package test + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/stretchr/testify/assert" +) + +func TestIsDeviceAvailable(t *testing.T) { + runtime.LoadBackendFromEnv() + dev := runtime.CreateDevice("CUDA", 0) + err := runtime.SetDevice(&dev) + res, err := runtime.GetDeviceCount() + assert.Equal(t, runtime.Success, err) + assert.Equal(t, res, 2) + err = runtime.LoadBackendFromEnv() + assert.Equal(t, runtime.Success, err) + devCuda := runtime.CreateDevice("CUDA", 0) + assert.True(t, runtime.IsDeviceAvailable(&devCuda)) + devCpu := runtime.CreateDevice("CPU", 0) + assert.True(t, runtime.IsDeviceAvailable(&devCpu)) + devInvalid := runtime.CreateDevice("invalid", 0) + assert.False(t, runtime.IsDeviceAvailable(&devInvalid)) +} + +func TestRegisteredDevices(t *testing.T) { + err := runtime.LoadBackendFromEnv() + assert.Equal(t, runtime.Success, err) + devices, err := runtime.GetRegisteredDevices() + assert.Equal(t, []string{"CUDA", "CPU"}, devices) +} + +func TestDeviceProperties(t *testing.T) { + err := runtime.LoadBackendFromEnv() + assert.Equal(t, runtime.Success, err) + dev := runtime.CreateDevice("CUDA", 0) + err = runtime.SetDevice(&dev) + assert.Equal(t, runtime.Success, err) + _, err = runtime.GetDeviceProperties() + assert.Equal(t, runtime.Success, err) + +} + +func TestActiveDevice(t *testing.T) { + err := runtime.LoadBackendFromEnv() + assert.Equal(t, runtime.Success, err) + dev1 := runtime.CreateDevice("CUDA", 0) + err = runtime.SetDevice(&dev1) + assert.Equal(t, runtime.Success, err) + activeDevice, err := runtime.GetActiveDevice() + assert.Equal(t, runtime.Success, err) + assert.Equal(t, dev1, *activeDevice) + memory1, err := runtime.GetAvailableMemory() + assert.Equal(t, runtime.Success, err) + assert.Greater(t, memory1.Total, uint(0)) + assert.Greater(t, memory1.Free, uint(0)) +} + +// func TestDestroyStream(t *testing.T) { +// stream, err := runtime.CreateStream() +// assert.Equal(t, runtime.Success, err, "Unable to create stream due to %d", err) + +// err = runtime.DestroyStream(stream) +// assert.Equal(t, runtime.Success, err, "Unable to destroy stream due to %d", err) +// } + +// func TestSyncStream(t *testing.T) { +// stream, err := runtime.CreateStream() +// assert.Equal(t, runtime.Success, err, "Unable to create stream due to %d", err) + +// _, err = MallocAsync(200000, stream) +// assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) + +// dp, err := Malloc(20) +// assert.NotNil(t, dp) +// assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) + +// err = SynchronizeStream(&stream) +// assert.Equal(t, CudaSuccess, err, "Unable to sync stream due to %d", err) + +// err = DestroyStream(&stream) +// assert.Equal(t, CudaSuccess, err, "Unable to destroy stream due to %d", err) +// } diff --git a/wrappers/golang_v3/runtime/tests/stream_test.go b/wrappers/golang_v3/runtime/tests/stream_test.go new file mode 100644 index 000000000..8daa558fb --- /dev/null +++ b/wrappers/golang_v3/runtime/tests/stream_test.go @@ -0,0 +1,55 @@ +package test + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/stretchr/testify/assert" +) + +func TestCreateStream(t *testing.T) { + err := runtime.LoadBackendFromEnv() + assert.Equal(t, runtime.Success, err) + dev := runtime.CreateDevice("CUDA", 0) + assert.True(t, runtime.IsDeviceAvailable(&dev)) + err = runtime.SetDevice(&dev) + assert.Equal(t, runtime.Success, err) + _, err = runtime.CreateStream() + assert.Equal(t, runtime.Success, err, "Unable to create stream due to %d", err) +} + +func TestDestroyStream(t *testing.T) { + err := runtime.LoadBackend("/home/administrator/users/Timur/Projects/icicle/icicle_v3/build/backend", true) + assert.Equal(t, runtime.Success, err) + dev := runtime.CreateDevice("CUDA", 0) + assert.True(t, runtime.IsDeviceAvailable(&dev)) + stream, err := runtime.CreateStream() + assert.Equal(t, runtime.Success, err, "Unable to create stream due to %d", err) + + err = runtime.DestroyStream(stream) + assert.Equal(t, runtime.Success, err, "Unable to destroy stream due to %d", err) +} + +func TestSyncStream(t *testing.T) { + err := runtime.LoadBackendFromEnv() + assert.Equal(t, runtime.Success, err) + dev := runtime.CreateDevice("CUDA", 0) + assert.True(t, runtime.IsDeviceAvailable(&dev)) + runtime.SetDevice(&dev) + + stream, err := runtime.CreateStream() + assert.Equal(t, runtime.Success, err, "Unable to create stream due to %d", err) + + _, err = runtime.MallocAsync(200000, stream) + assert.Equal(t, runtime.Success, err, "Unable to allocate device memory due to %d", err) + + dp, err := runtime.Malloc(20) + assert.NotNil(t, dp) + assert.Equal(t, runtime.Success, err, "Unable to allocate device memory due to %d", err) + + err = runtime.SynchronizeStream(stream) + assert.Equal(t, runtime.Success, err, "Unable to sync stream due to %d", err) + + err = runtime.DestroyStream(stream) + assert.Equal(t, runtime.Success, err, "Unable to destroy stream due to %d", err) +} diff --git a/wrappers/golang_v3/test_helpers/helpers.go b/wrappers/golang_v3/test_helpers/helpers.go new file mode 100644 index 000000000..09a2a7dff --- /dev/null +++ b/wrappers/golang_v3/test_helpers/helpers.go @@ -0,0 +1,31 @@ +package test_helpers + +import ( + "math/rand" +) + +func GenerateRandomLimb(size int) []uint32 { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + return limbs +} + +func GenerateLimbOne(size int) []uint32 { + limbs := make([]uint32, size) + limbs[0] = 1 + return limbs +} + +func GenerateBytesArray(size int) ([]byte, []uint32) { + baseBytes := []byte{1, 2, 3, 4} + var bytes []byte + var limbs []uint32 + for i := 0; i < size; i++ { + bytes = append(bytes, baseBytes...) + limbs = append(limbs, 67305985) + } + + return bytes, limbs +} From fb971bb8aee491e39250b8922a66b4716cae9354 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Sat, 20 Jul 2024 16:13:36 +0000 Subject: [PATCH 18/38] msm golang wrappers --- go.sum | 1 + wrappers/golang_v3/core/msm.go | 28 +- .../curves/bls12377/g2/include/scalar_field.h | 5 +- .../curves/bls12377/include/scalar_field.h | 5 +- .../curves/bls12377/ntt/include/ntt.h | 10 +- wrappers/golang_v3/curves/bls12377/ntt/ntt.go | 45 +- .../bls12377/polynomial/include/polynomial.h | 1 - .../curves/bls12377/polynomial/polynomial.go | 8 +- .../golang_v3/curves/bls12377/scalar_field.go | 21 +- .../curves/bls12377/tests/base_field_test.go | 4 +- .../bls12377/tests/g2_g2base_field_test.go | 4 +- .../curves/bls12377/tests/main_test.go | 24 +- .../curves/bls12377/tests/ntt_test.go | 23 +- .../curves/bls12377/tests/polynomial_test.go | 10 +- .../bls12377/tests/scalar_field_test.go | 10 +- .../curves/bls12377/tests/vec_ops_test.go | 20 +- .../curves/bls12377/vecOps/include/vec_ops.h | 15 +- .../curves/bls12377/vecOps/vec_ops.go | 30 +- .../curves/bls12381/g2/include/scalar_field.h | 5 +- .../curves/bls12381/include/scalar_field.h | 5 +- .../curves/bls12381/ntt/include/ntt.h | 10 +- wrappers/golang_v3/curves/bls12381/ntt/ntt.go | 45 +- .../bls12381/polynomial/include/polynomial.h | 1 - .../curves/bls12381/polynomial/polynomial.go | 8 +- .../golang_v3/curves/bls12381/scalar_field.go | 21 +- .../curves/bls12381/tests/base_field_test.go | 4 +- .../bls12381/tests/g2_g2base_field_test.go | 4 +- .../curves/bls12381/tests/main_test.go | 24 +- .../curves/bls12381/tests/ntt_test.go | 23 +- .../curves/bls12381/tests/polynomial_test.go | 10 +- .../bls12381/tests/scalar_field_test.go | 10 +- .../curves/bls12381/tests/vec_ops_test.go | 20 +- .../curves/bls12381/vecOps/include/vec_ops.h | 15 +- .../curves/bls12381/vecOps/vec_ops.go | 30 +- wrappers/golang_v3/curves/bn254/curve.go | 38 +- wrappers/golang_v3/curves/bn254/g2/curve.go | 346 ++++---- .../golang_v3/curves/bn254/g2/g2base_field.go | 164 ++-- .../curves/bn254/g2/include/scalar_field.h | 5 +- wrappers/golang_v3/curves/bn254/g2/msm.go | 122 +-- .../golang_v3/curves/bn254/include/curve.h | 6 +- .../curves/bn254/include/scalar_field.h | 5 +- wrappers/golang_v3/curves/bn254/main.go | 2 +- .../golang_v3/curves/bn254/msm/include/msm.h | 7 +- wrappers/golang_v3/curves/bn254/msm/msm.go | 49 +- .../golang_v3/curves/bn254/ntt/include/ntt.h | 10 +- wrappers/golang_v3/curves/bn254/ntt/ntt.go | 45 +- .../bn254/polynomial/include/polynomial.h | 1 - .../curves/bn254/polynomial/polynomial.go | 8 +- .../golang_v3/curves/bn254/scalar_field.go | 21 +- .../curves/bn254/tests/base_field_test.go | 4 +- .../curves/bn254/tests/curve_test.go | 202 ++--- .../curves/bn254/tests/ecntt_test.go | 46 +- .../curves/bn254/tests/g2_curve_test.go | 202 ++--- .../bn254/tests/g2_g2base_field_test.go | 172 ++-- .../curves/bn254/tests/g2_msm_test.go | 738 +++++++++--------- .../golang_v3/curves/bn254/tests/main_test.go | 24 +- .../golang_v3/curves/bn254/tests/msm_test.go | 289 ++++--- .../golang_v3/curves/bn254/tests/ntt_test.go | 51 +- .../curves/bn254/tests/polynomial_test.go | 10 +- .../curves/bn254/tests/poseidon_test.go | 56 +- .../curves/bn254/tests/scalar_field_test.go | 10 +- .../curves/bn254/tests/vec_ops_test.go | 20 +- .../curves/bn254/vecOps/include/vec_ops.h | 15 +- .../golang_v3/curves/bn254/vecOps/vec_ops.go | 30 +- .../curves/bw6761/g2/include/scalar_field.h | 5 +- .../curves/bw6761/include/scalar_field.h | 5 +- .../golang_v3/curves/bw6761/ntt/include/ntt.h | 10 +- wrappers/golang_v3/curves/bw6761/ntt/ntt.go | 45 +- .../bw6761/polynomial/include/polynomial.h | 1 - .../curves/bw6761/polynomial/polynomial.go | 8 +- .../golang_v3/curves/bw6761/scalar_field.go | 21 +- .../curves/bw6761/tests/base_field_test.go | 4 +- .../bw6761/tests/g2_g2base_field_test.go | 4 +- .../curves/bw6761/tests/main_test.go | 24 +- .../golang_v3/curves/bw6761/tests/ntt_test.go | 23 +- .../curves/bw6761/tests/polynomial_test.go | 10 +- .../curves/bw6761/tests/scalar_field_test.go | 10 +- .../curves/bw6761/tests/vec_ops_test.go | 20 +- .../curves/bw6761/vecOps/include/vec_ops.h | 15 +- .../golang_v3/curves/bw6761/vecOps/vec_ops.go | 30 +- .../curves/grumpkin/include/scalar_field.h | 5 +- .../golang_v3/curves/grumpkin/scalar_field.go | 21 +- .../curves/grumpkin/tests/base_field_test.go | 4 +- .../curves/grumpkin/tests/main_test.go | 5 + .../grumpkin/tests/scalar_field_test.go | 10 +- .../curves/grumpkin/tests/vec_ops_test.go | 20 +- .../curves/grumpkin/vecOps/include/vec_ops.h | 15 +- .../curves/grumpkin/vecOps/vec_ops.go | 30 +- .../babybear/extension/extension_field.go | 3 +- .../babybear/extension/include/scalar_field.h | 2 - .../babybear/extension/ntt/include/ntt.h | 1 - .../extension/vecOps/include/vec_ops.h | 5 +- .../fields/babybear/include/scalar_field.h | 1 - .../fields/babybear/ntt/include/ntt.h | 1 - .../golang_v3/fields/babybear/scalar_field.go | 3 +- .../babybear/tests/extension_field_test.go | 120 +++ .../babybear/tests/extension_vec_ops_test.go | 65 ++ .../fields/babybear/tests/main_test.go | 2 - .../fields/babybear/tests/polynomial_test.go | 3 +- .../babybear/tests/scalar_field_test.go | 3 +- .../fields/babybear/tests/vec_ops_test.go | 1 - .../fields/babybear/vecOps/include/vec_ops.h | 1 - .../generator/fields/templates/field.go.tmpl | 21 +- .../fields/templates/field_test.go.tmpl | 12 +- .../generator/fields/templates/main.go.tmpl | 2 +- .../fields/templates/scalar_field.h.tmpl | 5 +- .../generator/msm/templates/msm.go.tmpl | 53 +- .../generator/msm/templates/msm.h.tmpl | 7 +- .../generator/msm/templates/msm_test.go.tmpl | 126 +-- .../generator/ntt/templates/ntt.go.tmpl | 49 +- .../generator/ntt/templates/ntt.h.tmpl | 10 +- .../ntt/templates/ntt_no_domain_test.go.tmpl | 14 +- .../generator/ntt/templates/ntt_test.go.tmpl | 23 +- .../polynomial/templates/polynomial.go.tmpl | 8 +- .../polynomial/templates/polynomial.h.tmpl | 1 - .../templates/polynomial_test.go.tmpl | 10 +- .../internal/generator/poseidon/generate.go | 44 +- .../tests/templates/main_test.go.tmpl | 25 +- .../vecOps/templates/vec_ops.go.tmpl | 37 +- .../generator/vecOps/templates/vec_ops.h.tmpl | 15 +- .../vecOps/templates/vec_ops_test.go.tmpl | 21 +- 121 files changed, 2153 insertions(+), 2083 deletions(-) create mode 100644 wrappers/golang_v3/fields/babybear/tests/extension_field_test.go create mode 100644 wrappers/golang_v3/fields/babybear/tests/extension_vec_ops_test.go diff --git a/go.sum b/go.sum index a3e38a8d1..da0837081 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,7 @@ golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/wrappers/golang_v3/core/msm.go b/wrappers/golang_v3/core/msm.go index 76e46964a..7b136a732 100644 --- a/wrappers/golang_v3/core/msm.go +++ b/wrappers/golang_v3/core/msm.go @@ -39,24 +39,24 @@ type MSMConfig struct { /// and you'd need to synchronize it explicitly by running `cudaStreamSynchronize` or `cudaDeviceSynchronize`. /// If set to `false`, the MSM function will block the current CPU thread. IsAsync bool - Ext runtime.ConfigExtension + Ext runtime.ConfigExtensionHandler } func GetDefaultMSMConfig() MSMConfig { return MSMConfig{ - unsafe.Pointer(nil), // StreamHandle - 0, // basesSize - 1, // PrecomputeFactor - 0, // C - 0, // Bitsize - 1, // batchSize - false, // areScalarsOnDevice - false, // AreScalarsMontgomeryForm - false, // areBasesOnDevice - false, // AreBasesMontgomeryForm - false, // areResultsOnDevice - false, // IsAsync - *runtime.CreateConfigExtension(), // Ext + nil, // StreamHandle + 0, // basesSize + 1, // PrecomputeFactor + 0, // C + 0, // Bitsize + 1, // batchSize + false, // areScalarsOnDevice + false, // AreScalarsMontgomeryForm + false, // areBasesOnDevice + false, // AreBasesMontgomeryForm + false, // areResultsOnDevice + false, // IsAsync + nil, // Ext } } diff --git a/wrappers/golang_v3/curves/bls12377/g2/include/scalar_field.h b/wrappers/golang_v3/curves/bls12377/g2/include/scalar_field.h index 09b1bfb7f..97de9e414 100644 --- a/wrappers/golang_v3/curves/bls12377/g2/include/scalar_field.h +++ b/wrappers/golang_v3/curves/bls12377/g2/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_377_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void bls12_377_generate_scalars(scalar_t* scalars, int size); -cudaError_t bls12_377_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int bls12_377_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12377/include/scalar_field.h b/wrappers/golang_v3/curves/bls12377/include/scalar_field.h index 09b1bfb7f..97de9e414 100644 --- a/wrappers/golang_v3/curves/bls12377/include/scalar_field.h +++ b/wrappers/golang_v3/curves/bls12377/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_377_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void bls12_377_generate_scalars(scalar_t* scalars, int size); -cudaError_t bls12_377_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int bls12_377_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12377/ntt/include/ntt.h b/wrappers/golang_v3/curves/bls12377/ntt/include/ntt.h index d933f5ba0..146d0c311 100644 --- a/wrappers/golang_v3/curves/bls12377/ntt/include/ntt.h +++ b/wrappers/golang_v3/curves/bls12377/ntt/include/ntt.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_377_NTT_H @@ -10,11 +9,12 @@ extern "C" { typedef struct scalar_t scalar_t; typedef struct NTTConfig NTTConfig; -typedef struct DeviceContext DeviceContext; +typedef struct NTTInitDomainConfig NTTInitDomainConfig; -cudaError_t bls12_377_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); -cudaError_t bls12_377_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); -cudaError_t bls12_377_release_domain(DeviceContext* ctx); +int bls12_377_ntt(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +int bls12_377_ntt_init_domain(scalar_t* primitive_root, NTTInitDomainConfig* ctx); +int bls12_377_ntt_release_domain(); +int* bls12_377_get_root_of_unity(size_t size); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12377/ntt/ntt.go b/wrappers/golang_v3/curves/bls12377/ntt/ntt.go index 4403abcca..fa59ee0b0 100644 --- a/wrappers/golang_v3/curves/bls12377/ntt/ntt.go +++ b/wrappers/golang_v3/curves/bls12377/ntt/ntt.go @@ -4,17 +4,15 @@ package ntt // #include "ntt.h" import "C" -import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" -) - import ( "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) @@ -23,9 +21,9 @@ func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTCo cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.scalar_t)(resultsPointer) - __ret := C.bls12_377_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.bls12_377_ntt(cScalars, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } func GetDefaultNttConfig() core.NTTConfig[[bls12_377.SCALAR_LIMBS]uint32] { @@ -39,18 +37,23 @@ func GetDefaultNttConfig() core.NTTConfig[[bls12_377.SCALAR_LIMBS]uint32] { return core.GetDefaultNTTConfig(cosetGen) } -func InitDomain(primitiveRoot bls12_377.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { +func GetRootOfUnity(size uint64) bls12_377.ScalarField { + cRes := C.bls12_377_get_root_of_unity((C.size_t)(size)) + var res bls12_377.ScalarField + res.FromLimbs(*(*[]uint32)(unsafe.Pointer(cRes))) + return res +} + +func InitDomain(primitiveRoot bls12_377.ScalarField, cfg core.NTTInitDomainConfig) runtime.EIcicleError { cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cFastTwiddles := (C._Bool)(fastTwiddles) - __ret := C.bls12_377_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + cCfg := (*C.NTTInitDomainConfig)(unsafe.Pointer(&cfg)) + __ret := C.bls12_377_ntt_init_domain(cPrimitiveRoot, cCfg) + err := runtime.EIcicleError(__ret) + return err } -func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - __ret := C.bls12_377_release_domain(cCtx) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) +func ReleaseDomain() runtime.EIcicleError { + __ret := C.bls12_377_ntt_release_domain() + err := runtime.EIcicleError(__ret) + return err } diff --git a/wrappers/golang_v3/curves/bls12377/polynomial/include/polynomial.h b/wrappers/golang_v3/curves/bls12377/polynomial/include/polynomial.h index 6aa6e3bfb..967bcdad5 100644 --- a/wrappers/golang_v3/curves/bls12377/polynomial/include/polynomial.h +++ b/wrappers/golang_v3/curves/bls12377/polynomial/include/polynomial.h @@ -12,7 +12,6 @@ typedef struct scalar_t scalar_t; typedef struct PolynomialInst PolynomialInst; typedef struct IntegrityPointer IntegrityPointer; -bool bls12_377_polynomial_init_cuda_backend(); PolynomialInst* bls12_377_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); PolynomialInst* bls12_377_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); PolynomialInst* bls12_377_polynomial_clone(const PolynomialInst* p); diff --git a/wrappers/golang_v3/curves/bls12377/polynomial/polynomial.go b/wrappers/golang_v3/curves/bls12377/polynomial/polynomial.go index 2f3998a8e..de12e0be8 100644 --- a/wrappers/golang_v3/curves/bls12377/polynomial/polynomial.go +++ b/wrappers/golang_v3/curves/bls12377/polynomial/polynomial.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" ) type PolynomialHandle = C.struct_PolynomialInst @@ -17,10 +17,6 @@ type DensePolynomial struct { handle *PolynomialHandle } -func InitPolyBackend() bool { - return (bool)(C.bls12_377_polynomial_init_cuda_backend()) -} - func (up *DensePolynomial) Print() { C.bls12_377_polynomial_print(up.handle) } diff --git a/wrappers/golang_v3/curves/bls12377/scalar_field.go b/wrappers/golang_v3/curves/bls12377/scalar_field.go index 716207644..4734ac7d7 100644 --- a/wrappers/golang_v3/curves/bls12377/scalar_field.go +++ b/wrappers/golang_v3/curves/bls12377/scalar_field.go @@ -6,8 +6,8 @@ import "C" import ( "encoding/binary" "fmt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "unsafe" ) @@ -99,23 +99,20 @@ func GenerateScalars(size int) core.HostSlice[ScalarField] { return scalarSlice } -func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) - cSize := (C.size_t)(scalars.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_377_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*scalars, *scalars, *scalars, &defaultCfg) + cErr := C.bls12_377_scalar_convert_montgomery((*C.scalar_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.scalar_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func ToMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, true) } -func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func FromMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, false) } diff --git a/wrappers/golang_v3/curves/bls12377/tests/base_field_test.go b/wrappers/golang_v3/curves/bls12377/tests/base_field_test.go index cb5106f26..8de4b0f28 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/base_field_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/base_field_test.go @@ -1,8 +1,8 @@ package tests import ( - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_g2base_field_test.go index dcaa8bcac..49eaad307 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_g2base_field_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_g2base_field_test.go @@ -1,8 +1,8 @@ package tests import ( - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/curves/bls12377/tests/main_test.go b/wrappers/golang_v3/curves/bls12377/tests/main_test.go index 928e6c3fa..dc593ca78 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/main_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/main_test.go @@ -4,10 +4,10 @@ import ( "os" "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt" - poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft" ) @@ -16,24 +16,26 @@ const ( largestTestSize = 20 ) -func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { +func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() rouIcicle := bls12_377.ScalarField{} limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) rouIcicle.FromLimbs(limbs) - e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + e := ntt.InitDomain(rouIcicle, cfg) return e } func TestMain(m *testing.M) { - poly.InitPolyBackend() + runtime.LoadBackendFromEnv() + device := runtime.CreateDevice("CUDA", 0) + runtime.SetDevice(&device) // setup domain - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() e := initDomain(largestTestSize, cfg) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + if e != runtime.Success { panic("initDomain failed") } @@ -41,8 +43,8 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) // release domain - e = ntt.ReleaseDomain(cfg.Ctx) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + e = ntt.ReleaseDomain() + if e != runtime.Success { panic("ReleaseDomain failed") } } diff --git a/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go b/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go index 8014e56d8..d8fb84e05 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go @@ -6,11 +6,11 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" ) @@ -65,7 +65,7 @@ func TestNTTGetDefaultConfig(t *testing.T) { func TestInitDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) } @@ -125,11 +125,11 @@ func TestNttDeviceAsync(t *testing.T) { testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:testSize]) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() cfg.Ordering = v cfg.IsAsync = true - cfg.Ctx.Stream = &stream + cfg.StreamHandle = stream var deviceInput core.DeviceSlice scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) @@ -141,7 +141,7 @@ func TestNttDeviceAsync(t *testing.T) { output := make(core.HostSlice[bls12_377.ScalarField], testSize) output.CopyFromDeviceAsync(&deviceOutput, stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Compare with gnark-crypto assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) } @@ -195,9 +195,8 @@ func TestNttBatch(t *testing.T) { func TestReleaseDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() - e := ntt.ReleaseDomain(cfg.Ctx) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") + e := ntt.ReleaseDomain() + assert.Equal(t, runtime.Success, e, "ReleasDomain failed") } // func TestNttArbitraryCoset(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12377/tests/polynomial_test.go b/wrappers/golang_v3/curves/bls12377/tests/polynomial_test.go index de9d2c1b9..1effcfb0c 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/polynomial_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/polynomial_test.go @@ -3,11 +3,11 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/polynomial" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/vecOps" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/curves/bls12377/tests/scalar_field_test.go b/wrappers/golang_v3/curves/bls12377/tests/scalar_field_test.go index d5063e90e..a96e7e7a6 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/scalar_field_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/scalar_field_test.go @@ -1,9 +1,9 @@ package tests import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) @@ -100,7 +100,7 @@ func TestBls12_377GenerateScalars(t *testing.T) { } func TestBls12_377MongtomeryConversion(t *testing.T) { - size := 1 << 15 + size := 1 << 20 scalars := bls12_377.GenerateScalars(size) var deviceScalars core.DeviceSlice @@ -108,7 +108,7 @@ func TestBls12_377MongtomeryConversion(t *testing.T) { bls12_377.ToMontgomery(&deviceScalars) - scalarsMontHost := bls12_377.GenerateScalars(size) + scalarsMontHost := make(core.HostSlice[bls12_377.ScalarField], size) scalarsMontHost.CopyFromDevice(&deviceScalars) assert.NotEqual(t, scalars, scalarsMontHost) diff --git a/wrappers/golang_v3/curves/bls12377/tests/vec_ops_test.go b/wrappers/golang_v3/curves/bls12377/tests/vec_ops_test.go index c9e67e25f..fb789a87e 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/vec_ops_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/vec_ops_test.go @@ -3,10 +3,9 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/vecOps" "github.com/stretchr/testify/assert" ) @@ -38,30 +37,27 @@ func TestBls12_377VecOps(t *testing.T) { func TestBls12_377Transpose(t *testing.T) { rowSize := 1 << 6 columnSize := 1 << 8 - onDevice := false - isAsync := false matrix := bls12_377.GenerateScalars(rowSize * columnSize) out := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize) out2 := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize) - ctx, _ := cr.GetDefaultDeviceContext() + cfg := core.DefaultVecOpsConfig() - vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) assert.Equal(t, matrix, out2) var dMatrix, dOut, dOut2 core.DeviceSlice - onDevice = true matrix.CopyToDevice(&dMatrix, true) dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) - vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, cfg) output := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize) output.CopyFromDevice(&dOut2) diff --git a/wrappers/golang_v3/curves/bls12377/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/bls12377/vecOps/include/vec_ops.h index 54a4968e3..ac62d3e5d 100644 --- a/wrappers/golang_v3/curves/bls12377/vecOps/include/vec_ops.h +++ b/wrappers/golang_v3/curves/bls12377/vecOps/include/vec_ops.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_377_VEC_OPS_H @@ -12,7 +11,7 @@ typedef struct scalar_t scalar_t; typedef struct VecOpsConfig VecOpsConfig; typedef struct DeviceContext DeviceContext; -cudaError_t bls12_377_mul_cuda( +int bls12_377_vector_mul( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -20,7 +19,7 @@ cudaError_t bls12_377_mul_cuda( scalar_t* result ); -cudaError_t bls12_377_add_cuda( +int bls12_377_vector_add( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -28,7 +27,7 @@ cudaError_t bls12_377_add_cuda( scalar_t* result ); -cudaError_t bls12_377_sub_cuda( +int bls12_377_vector_sub( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -36,14 +35,12 @@ cudaError_t bls12_377_sub_cuda( scalar_t* result ); -cudaError_t bls12_377_transpose_matrix_cuda( +int bls12_377_matrix_transpose( scalar_t* mat_in, int row_size, int column_size, - scalar_t* mat_out, - DeviceContext* ctx, - bool on_device, - bool is_async + VecOpsConfig* config, + scalar_t* mat_out ); #ifdef __cplusplus diff --git a/wrappers/golang_v3/curves/bls12377/vecOps/vec_ops.go b/wrappers/golang_v3/curves/bls12377/vecOps/vec_ops.go index d883828f7..d592bc9b9 100644 --- a/wrappers/golang_v3/curves/bls12377/vecOps/vec_ops.go +++ b/wrappers/golang_v3/curves/bls12377/vecOps/vec_ops.go @@ -5,13 +5,11 @@ package vecOps import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - - "unsafe" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) cA := (*C.scalar_t)(aPointer) @@ -22,27 +20,25 @@ func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.V switch op { case core.Sub: - ret = (cr.CudaError)(C.bls12_377_sub_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bls12_377_vector_sub(cA, cB, cSize, cConfig, cOut)) case core.Add: - ret = (cr.CudaError)(C.bls12_377_add_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bls12_377_vector_add(cA, cB, cSize, cConfig, cOut)) case core.Mul: - ret = (cr.CudaError)(C.bls12_377_mul_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bls12_377_vector_mul(cA, cB, cSize, cConfig, cOut)) } return ret } -func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { - core.TransposeCheck(in, out, onDevice) +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, config core.VecOpsConfig) runtime.EIcicleError { + inPointer, _, outPointer, cfgPointer, _ := core.VecOpCheck(in, in, out, &config) - cIn := (*C.scalar_t)(in.AsUnsafePointer()) - cOut := (*C.scalar_t)(out.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cIn := (*C.scalar_t)(inPointer) cRowSize := (C.int)(rowSize) cColumnSize := (C.int)(columnSize) - cOnDevice := (C._Bool)(onDevice) - cIsAsync := (C._Bool)(isAsync) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cOut := (*C.scalar_t)(outPointer) - err := (cr.CudaError)(C.bls12_377_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) - return core.FromCudaError(err) + err := (C.bls12_377_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) + return runtime.EIcicleError(err) } diff --git a/wrappers/golang_v3/curves/bls12381/g2/include/scalar_field.h b/wrappers/golang_v3/curves/bls12381/g2/include/scalar_field.h index 842a6e101..f0807d9e9 100644 --- a/wrappers/golang_v3/curves/bls12381/g2/include/scalar_field.h +++ b/wrappers/golang_v3/curves/bls12381/g2/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_381_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void bls12_381_generate_scalars(scalar_t* scalars, int size); -cudaError_t bls12_381_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int bls12_381_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12381/include/scalar_field.h b/wrappers/golang_v3/curves/bls12381/include/scalar_field.h index 842a6e101..f0807d9e9 100644 --- a/wrappers/golang_v3/curves/bls12381/include/scalar_field.h +++ b/wrappers/golang_v3/curves/bls12381/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_381_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void bls12_381_generate_scalars(scalar_t* scalars, int size); -cudaError_t bls12_381_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int bls12_381_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12381/ntt/include/ntt.h b/wrappers/golang_v3/curves/bls12381/ntt/include/ntt.h index 34133442c..b305a181d 100644 --- a/wrappers/golang_v3/curves/bls12381/ntt/include/ntt.h +++ b/wrappers/golang_v3/curves/bls12381/ntt/include/ntt.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_381_NTT_H @@ -10,11 +9,12 @@ extern "C" { typedef struct scalar_t scalar_t; typedef struct NTTConfig NTTConfig; -typedef struct DeviceContext DeviceContext; +typedef struct NTTInitDomainConfig NTTInitDomainConfig; -cudaError_t bls12_381_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); -cudaError_t bls12_381_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); -cudaError_t bls12_381_release_domain(DeviceContext* ctx); +int bls12_381_ntt(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +int bls12_381_ntt_init_domain(scalar_t* primitive_root, NTTInitDomainConfig* ctx); +int bls12_381_ntt_release_domain(); +int* bls12_381_get_root_of_unity(size_t size); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12381/ntt/ntt.go b/wrappers/golang_v3/curves/bls12381/ntt/ntt.go index 37be3ffe6..683e6e12a 100644 --- a/wrappers/golang_v3/curves/bls12381/ntt/ntt.go +++ b/wrappers/golang_v3/curves/bls12381/ntt/ntt.go @@ -4,17 +4,15 @@ package ntt // #include "ntt.h" import "C" -import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" -) - import ( "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) @@ -23,9 +21,9 @@ func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTCo cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.scalar_t)(resultsPointer) - __ret := C.bls12_381_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.bls12_381_ntt(cScalars, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } func GetDefaultNttConfig() core.NTTConfig[[bls12_381.SCALAR_LIMBS]uint32] { @@ -39,18 +37,23 @@ func GetDefaultNttConfig() core.NTTConfig[[bls12_381.SCALAR_LIMBS]uint32] { return core.GetDefaultNTTConfig(cosetGen) } -func InitDomain(primitiveRoot bls12_381.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { +func GetRootOfUnity(size uint64) bls12_381.ScalarField { + cRes := C.bls12_381_get_root_of_unity((C.size_t)(size)) + var res bls12_381.ScalarField + res.FromLimbs(*(*[]uint32)(unsafe.Pointer(cRes))) + return res +} + +func InitDomain(primitiveRoot bls12_381.ScalarField, cfg core.NTTInitDomainConfig) runtime.EIcicleError { cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cFastTwiddles := (C._Bool)(fastTwiddles) - __ret := C.bls12_381_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + cCfg := (*C.NTTInitDomainConfig)(unsafe.Pointer(&cfg)) + __ret := C.bls12_381_ntt_init_domain(cPrimitiveRoot, cCfg) + err := runtime.EIcicleError(__ret) + return err } -func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - __ret := C.bls12_381_release_domain(cCtx) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) +func ReleaseDomain() runtime.EIcicleError { + __ret := C.bls12_381_ntt_release_domain() + err := runtime.EIcicleError(__ret) + return err } diff --git a/wrappers/golang_v3/curves/bls12381/polynomial/include/polynomial.h b/wrappers/golang_v3/curves/bls12381/polynomial/include/polynomial.h index 2a36c90a5..52476bdfa 100644 --- a/wrappers/golang_v3/curves/bls12381/polynomial/include/polynomial.h +++ b/wrappers/golang_v3/curves/bls12381/polynomial/include/polynomial.h @@ -12,7 +12,6 @@ typedef struct scalar_t scalar_t; typedef struct PolynomialInst PolynomialInst; typedef struct IntegrityPointer IntegrityPointer; -bool bls12_381_polynomial_init_cuda_backend(); PolynomialInst* bls12_381_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); PolynomialInst* bls12_381_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); PolynomialInst* bls12_381_polynomial_clone(const PolynomialInst* p); diff --git a/wrappers/golang_v3/curves/bls12381/polynomial/polynomial.go b/wrappers/golang_v3/curves/bls12381/polynomial/polynomial.go index 016c9ab18..bc2c4d839 100644 --- a/wrappers/golang_v3/curves/bls12381/polynomial/polynomial.go +++ b/wrappers/golang_v3/curves/bls12381/polynomial/polynomial.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" ) type PolynomialHandle = C.struct_PolynomialInst @@ -17,10 +17,6 @@ type DensePolynomial struct { handle *PolynomialHandle } -func InitPolyBackend() bool { - return (bool)(C.bls12_381_polynomial_init_cuda_backend()) -} - func (up *DensePolynomial) Print() { C.bls12_381_polynomial_print(up.handle) } diff --git a/wrappers/golang_v3/curves/bls12381/scalar_field.go b/wrappers/golang_v3/curves/bls12381/scalar_field.go index 1dedd0b90..65e16782a 100644 --- a/wrappers/golang_v3/curves/bls12381/scalar_field.go +++ b/wrappers/golang_v3/curves/bls12381/scalar_field.go @@ -6,8 +6,8 @@ import "C" import ( "encoding/binary" "fmt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "unsafe" ) @@ -99,23 +99,20 @@ func GenerateScalars(size int) core.HostSlice[ScalarField] { return scalarSlice } -func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) - cSize := (C.size_t)(scalars.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_381_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*scalars, *scalars, *scalars, &defaultCfg) + cErr := C.bls12_381_scalar_convert_montgomery((*C.scalar_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.scalar_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func ToMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, true) } -func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func FromMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, false) } diff --git a/wrappers/golang_v3/curves/bls12381/tests/base_field_test.go b/wrappers/golang_v3/curves/bls12381/tests/base_field_test.go index 28552bcb1..5bd6aaa49 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/base_field_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/base_field_test.go @@ -1,8 +1,8 @@ package tests import ( - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_g2base_field_test.go index 2ec14da06..e5796f313 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_g2base_field_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_g2base_field_test.go @@ -1,8 +1,8 @@ package tests import ( - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/g2" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/curves/bls12381/tests/main_test.go b/wrappers/golang_v3/curves/bls12381/tests/main_test.go index 31077b7bb..5cf2e30f3 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/main_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/main_test.go @@ -4,10 +4,10 @@ import ( "os" "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt" - poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/fft" ) @@ -16,24 +16,26 @@ const ( largestTestSize = 20 ) -func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { +func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() rouIcicle := bls12_381.ScalarField{} limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) rouIcicle.FromLimbs(limbs) - e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + e := ntt.InitDomain(rouIcicle, cfg) return e } func TestMain(m *testing.M) { - poly.InitPolyBackend() + runtime.LoadBackendFromEnv() + device := runtime.CreateDevice("CUDA", 0) + runtime.SetDevice(&device) // setup domain - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() e := initDomain(largestTestSize, cfg) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + if e != runtime.Success { panic("initDomain failed") } @@ -41,8 +43,8 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) // release domain - e = ntt.ReleaseDomain(cfg.Ctx) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + e = ntt.ReleaseDomain() + if e != runtime.Success { panic("ReleaseDomain failed") } } diff --git a/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go b/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go index bc13119e6..1a503f087 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go @@ -6,11 +6,11 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/fft" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" ) @@ -65,7 +65,7 @@ func TestNTTGetDefaultConfig(t *testing.T) { func TestInitDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) } @@ -125,11 +125,11 @@ func TestNttDeviceAsync(t *testing.T) { testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:testSize]) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() cfg.Ordering = v cfg.IsAsync = true - cfg.Ctx.Stream = &stream + cfg.StreamHandle = stream var deviceInput core.DeviceSlice scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) @@ -141,7 +141,7 @@ func TestNttDeviceAsync(t *testing.T) { output := make(core.HostSlice[bls12_381.ScalarField], testSize) output.CopyFromDeviceAsync(&deviceOutput, stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Compare with gnark-crypto assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) } @@ -195,9 +195,8 @@ func TestNttBatch(t *testing.T) { func TestReleaseDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() - e := ntt.ReleaseDomain(cfg.Ctx) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") + e := ntt.ReleaseDomain() + assert.Equal(t, runtime.Success, e, "ReleasDomain failed") } // func TestNttArbitraryCoset(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12381/tests/polynomial_test.go b/wrappers/golang_v3/curves/bls12381/tests/polynomial_test.go index 0c376cf85..376a18e4e 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/polynomial_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/polynomial_test.go @@ -3,11 +3,11 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/polynomial" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/vecOps" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/curves/bls12381/tests/scalar_field_test.go b/wrappers/golang_v3/curves/bls12381/tests/scalar_field_test.go index 4701fba70..b0617c3bf 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/scalar_field_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/scalar_field_test.go @@ -1,9 +1,9 @@ package tests import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) @@ -100,7 +100,7 @@ func TestBls12_381GenerateScalars(t *testing.T) { } func TestBls12_381MongtomeryConversion(t *testing.T) { - size := 1 << 15 + size := 1 << 20 scalars := bls12_381.GenerateScalars(size) var deviceScalars core.DeviceSlice @@ -108,7 +108,7 @@ func TestBls12_381MongtomeryConversion(t *testing.T) { bls12_381.ToMontgomery(&deviceScalars) - scalarsMontHost := bls12_381.GenerateScalars(size) + scalarsMontHost := make(core.HostSlice[bls12_381.ScalarField], size) scalarsMontHost.CopyFromDevice(&deviceScalars) assert.NotEqual(t, scalars, scalarsMontHost) diff --git a/wrappers/golang_v3/curves/bls12381/tests/vec_ops_test.go b/wrappers/golang_v3/curves/bls12381/tests/vec_ops_test.go index 8a383ee48..872e9169e 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/vec_ops_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/vec_ops_test.go @@ -3,10 +3,9 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/vecOps" "github.com/stretchr/testify/assert" ) @@ -38,30 +37,27 @@ func TestBls12_381VecOps(t *testing.T) { func TestBls12_381Transpose(t *testing.T) { rowSize := 1 << 6 columnSize := 1 << 8 - onDevice := false - isAsync := false matrix := bls12_381.GenerateScalars(rowSize * columnSize) out := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize) out2 := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize) - ctx, _ := cr.GetDefaultDeviceContext() + cfg := core.DefaultVecOpsConfig() - vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) assert.Equal(t, matrix, out2) var dMatrix, dOut, dOut2 core.DeviceSlice - onDevice = true matrix.CopyToDevice(&dMatrix, true) dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) - vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, cfg) output := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize) output.CopyFromDevice(&dOut2) diff --git a/wrappers/golang_v3/curves/bls12381/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/bls12381/vecOps/include/vec_ops.h index 65ff61787..d82f8375f 100644 --- a/wrappers/golang_v3/curves/bls12381/vecOps/include/vec_ops.h +++ b/wrappers/golang_v3/curves/bls12381/vecOps/include/vec_ops.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_381_VEC_OPS_H @@ -12,7 +11,7 @@ typedef struct scalar_t scalar_t; typedef struct VecOpsConfig VecOpsConfig; typedef struct DeviceContext DeviceContext; -cudaError_t bls12_381_mul_cuda( +int bls12_381_vector_mul( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -20,7 +19,7 @@ cudaError_t bls12_381_mul_cuda( scalar_t* result ); -cudaError_t bls12_381_add_cuda( +int bls12_381_vector_add( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -28,7 +27,7 @@ cudaError_t bls12_381_add_cuda( scalar_t* result ); -cudaError_t bls12_381_sub_cuda( +int bls12_381_vector_sub( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -36,14 +35,12 @@ cudaError_t bls12_381_sub_cuda( scalar_t* result ); -cudaError_t bls12_381_transpose_matrix_cuda( +int bls12_381_matrix_transpose( scalar_t* mat_in, int row_size, int column_size, - scalar_t* mat_out, - DeviceContext* ctx, - bool on_device, - bool is_async + VecOpsConfig* config, + scalar_t* mat_out ); #ifdef __cplusplus diff --git a/wrappers/golang_v3/curves/bls12381/vecOps/vec_ops.go b/wrappers/golang_v3/curves/bls12381/vecOps/vec_ops.go index a17aa93af..f27c6fe6a 100644 --- a/wrappers/golang_v3/curves/bls12381/vecOps/vec_ops.go +++ b/wrappers/golang_v3/curves/bls12381/vecOps/vec_ops.go @@ -5,13 +5,11 @@ package vecOps import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - - "unsafe" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) cA := (*C.scalar_t)(aPointer) @@ -22,27 +20,25 @@ func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.V switch op { case core.Sub: - ret = (cr.CudaError)(C.bls12_381_sub_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bls12_381_vector_sub(cA, cB, cSize, cConfig, cOut)) case core.Add: - ret = (cr.CudaError)(C.bls12_381_add_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bls12_381_vector_add(cA, cB, cSize, cConfig, cOut)) case core.Mul: - ret = (cr.CudaError)(C.bls12_381_mul_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bls12_381_vector_mul(cA, cB, cSize, cConfig, cOut)) } return ret } -func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { - core.TransposeCheck(in, out, onDevice) +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, config core.VecOpsConfig) runtime.EIcicleError { + inPointer, _, outPointer, cfgPointer, _ := core.VecOpCheck(in, in, out, &config) - cIn := (*C.scalar_t)(in.AsUnsafePointer()) - cOut := (*C.scalar_t)(out.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cIn := (*C.scalar_t)(inPointer) cRowSize := (C.int)(rowSize) cColumnSize := (C.int)(columnSize) - cOnDevice := (C._Bool)(onDevice) - cIsAsync := (C._Bool)(isAsync) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cOut := (*C.scalar_t)(outPointer) - err := (cr.CudaError)(C.bls12_381_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) - return core.FromCudaError(err) + err := (C.bls12_381_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) + return runtime.EIcicleError(err) } diff --git a/wrappers/golang_v3/curves/bn254/curve.go b/wrappers/golang_v3/curves/bn254/curve.go index 80a844c7a..8ad65ba10 100644 --- a/wrappers/golang_v3/curves/bn254/curve.go +++ b/wrappers/golang_v3/curves/bn254/curve.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) type Projective struct { @@ -134,44 +134,38 @@ func GenerateAffinePoints(size int) core.HostSlice[Affine] { return pointsSlice } -func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bn254_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bn254_affine_convert_montgomery((*C.affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, true) } -func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, false) } -func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bn254_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bn254_projective_convert_montgomery((*C.projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, true) } -func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/curves/bn254/g2/curve.go b/wrappers/golang_v3/curves/bn254/g2/curve.go index 586d23831..77bb2aa49 100644 --- a/wrappers/golang_v3/curves/bn254/g2/curve.go +++ b/wrappers/golang_v3/curves/bn254/g2/curve.go @@ -1,177 +1,177 @@ package g2 -// #cgo CFLAGS: -I./include/ -// #include "curve.h" -import "C" - -import ( - "unsafe" +// // #cgo CFLAGS: -I./include/ +// // #include "curve.h" +// import "C" + +// import ( +// "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" -) +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" +// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +// ) -type G2Projective struct { - X, Y, Z G2BaseField -} - -func (p G2Projective) Size() int { - return p.X.Size() * 3 -} - -func (p G2Projective) AsPointer() *uint32 { - return p.X.AsPointer() -} - -func (p *G2Projective) Zero() G2Projective { - p.X.Zero() - p.Y.One() - p.Z.Zero() - - return *p -} - -func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { - p.X.FromLimbs(x) - p.Y.FromLimbs(y) - p.Z.FromLimbs(z) - - return *p -} - -func (p *G2Projective) FromAffine(a G2Affine) G2Projective { - z := G2BaseField{} - z.One() - - p.X = a.X - p.Y = a.Y - p.Z = z - - return *p -} - -func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) - cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) - __ret := C.bn254_g2_eq(cP, cP2) - return __ret == (C._Bool)(true) -} - -func (p *G2Projective) ProjectiveToAffine() G2Affine { - var a G2Affine - - cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) - cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) - C.bn254_g2_to_affine(cP, cA) - return a -} - -func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { - points := make([]G2Projective, size) - for i := range points { - points[i] = G2Projective{} - } - - pointsSlice := core.HostSliceFromElements[G2Projective](points) - pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) - cSize := (C.int)(size) - C.bn254_g2_generate_projective_points(pPoints, cSize) - - return pointsSlice -} - -type G2Affine struct { - X, Y G2BaseField -} - -func (a G2Affine) Size() int { - return a.X.Size() * 2 -} - -func (a G2Affine) AsPointer() *uint32 { - return a.X.AsPointer() -} - -func (a *G2Affine) Zero() G2Affine { - a.X.Zero() - a.Y.Zero() - - return *a -} - -func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { - a.X.FromLimbs(x) - a.Y.FromLimbs(y) - - return *a -} - -func (a G2Affine) ToProjective() G2Projective { - var z G2BaseField - - return G2Projective{ - X: a.X, - Y: a.Y, - Z: z.One(), - } -} - -func G2AffineFromProjective(p *G2Projective) G2Affine { - return p.ProjectiveToAffine() -} - -func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { - points := make([]G2Affine, size) - for i := range points { - points[i] = G2Affine{} - } - - pointsSlice := core.HostSliceFromElements[G2Affine](points) - cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) - cSize := (C.int)(size) - C.bn254_g2_generate_affine_points(cPoints, cSize) - - return pointsSlice -} - -func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bn254_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) - return err -} - -func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { - points.CheckDevice() - return convertG2AffinePointsMontgomery(points, true) -} - -func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { - points.CheckDevice() - return convertG2AffinePointsMontgomery(points, false) -} - -func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bn254_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) - return err -} - -func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { - points.CheckDevice() - return convertG2ProjectivePointsMontgomery(points, true) -} - -func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { - points.CheckDevice() - return convertG2ProjectivePointsMontgomery(points, false) -} +// type G2Projective struct { +// X, Y, Z G2BaseField +// } + +// func (p G2Projective) Size() int { +// return p.X.Size() * 3 +// } + +// func (p G2Projective) AsPointer() *uint32 { +// return p.X.AsPointer() +// } + +// func (p *G2Projective) Zero() G2Projective { +// p.X.Zero() +// p.Y.One() +// p.Z.Zero() + +// return *p +// } + +// func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { +// p.X.FromLimbs(x) +// p.Y.FromLimbs(y) +// p.Z.FromLimbs(z) + +// return *p +// } + +// func (p *G2Projective) FromAffine(a G2Affine) G2Projective { +// z := G2BaseField{} +// z.One() + +// p.X = a.X +// p.Y = a.Y +// p.Z = z + +// return *p +// } + +// func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { +// cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) +// cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) +// __ret := C.bn254_g2_eq(cP, cP2) +// return __ret == (C._Bool)(true) +// } + +// func (p *G2Projective) ProjectiveToAffine() G2Affine { +// var a G2Affine + +// cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) +// cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) +// C.bn254_g2_to_affine(cP, cA) +// return a +// } + +// func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { +// points := make([]G2Projective, size) +// for i := range points { +// points[i] = G2Projective{} +// } + +// pointsSlice := core.HostSliceFromElements[G2Projective](points) +// pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) +// cSize := (C.int)(size) +// C.bn254_g2_generate_projective_points(pPoints, cSize) + +// return pointsSlice +// } + +// type G2Affine struct { +// X, Y G2BaseField +// } + +// func (a G2Affine) Size() int { +// return a.X.Size() * 2 +// } + +// func (a G2Affine) AsPointer() *uint32 { +// return a.X.AsPointer() +// } + +// func (a *G2Affine) Zero() G2Affine { +// a.X.Zero() +// a.Y.Zero() + +// return *a +// } + +// func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { +// a.X.FromLimbs(x) +// a.Y.FromLimbs(y) + +// return *a +// } + +// func (a G2Affine) ToProjective() G2Projective { +// var z G2BaseField + +// return G2Projective{ +// X: a.X, +// Y: a.Y, +// Z: z.One(), +// } +// } + +// func G2AffineFromProjective(p *G2Projective) G2Affine { +// return p.ProjectiveToAffine() +// } + +// func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { +// points := make([]G2Affine, size) +// for i := range points { +// points[i] = G2Affine{} +// } + +// pointsSlice := core.HostSliceFromElements[G2Affine](points) +// cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) +// cSize := (C.int)(size) +// C.bn254_g2_generate_affine_points(cPoints, cSize) + +// return pointsSlice +// } + +// func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { +// cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) +// cSize := (C.size_t)(points.Len()) +// cIsInto := (C._Bool)(isInto) +// defaultCtx, _ := cr.GetDefaultDeviceContext() +// cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) +// __ret := C.bn254_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) +// err := (cr.CudaError)(__ret) +// return err +// } + +// func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +// points.CheckDevice() +// return convertG2AffinePointsMontgomery(points, true) +// } + +// func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +// points.CheckDevice() +// return convertG2AffinePointsMontgomery(points, false) +// } + +// func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { +// cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) +// cSize := (C.size_t)(points.Len()) +// cIsInto := (C._Bool)(isInto) +// defaultCtx, _ := cr.GetDefaultDeviceContext() +// cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) +// __ret := C.bn254_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) +// err := (cr.CudaError)(__ret) +// return err +// } + +// func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +// points.CheckDevice() +// return convertG2ProjectivePointsMontgomery(points, true) +// } + +// func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +// points.CheckDevice() +// return convertG2ProjectivePointsMontgomery(points, false) +// } diff --git a/wrappers/golang_v3/curves/bn254/g2/g2base_field.go b/wrappers/golang_v3/curves/bn254/g2/g2base_field.go index 409a7d5ad..ab1c8404b 100644 --- a/wrappers/golang_v3/curves/bn254/g2/g2base_field.go +++ b/wrappers/golang_v3/curves/bn254/g2/g2base_field.go @@ -1,84 +1,84 @@ package g2 -import ( - "encoding/binary" - "fmt" -) - -const ( - G2BASE_LIMBS int = 16 -) - -type G2BaseField struct { - limbs [G2BASE_LIMBS]uint32 -} - -func (f G2BaseField) Len() int { - return int(G2BASE_LIMBS) -} - -func (f G2BaseField) Size() int { - return int(G2BASE_LIMBS * 4) -} - -func (f G2BaseField) GetLimbs() []uint32 { - return f.limbs[:] -} - -func (f G2BaseField) AsPointer() *uint32 { - return &f.limbs[0] -} - -func (f *G2BaseField) FromUint32(v uint32) G2BaseField { - f.limbs[0] = v - return *f -} - -func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { - if len(limbs) != f.Len() { - panic("Called FromLimbs with limbs of different length than field") - } - for i := range f.limbs { - f.limbs[i] = limbs[i] - } - - return *f -} - -func (f *G2BaseField) Zero() G2BaseField { - for i := range f.limbs { - f.limbs[i] = 0 - } - - return *f -} - -func (f *G2BaseField) One() G2BaseField { - for i := range f.limbs { - f.limbs[i] = 0 - } - f.limbs[0] = 1 - - return *f -} - -func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { - if len(bytes)/4 != f.Len() { - panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) - } - - for i := range f.limbs { - f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) - } - - return *f -} - -func (f G2BaseField) ToBytesLittleEndian() []byte { - bytes := make([]byte, f.Len()*4) - for i, v := range f.limbs { - binary.LittleEndian.PutUint32(bytes[i*4:], v) - } - - return bytes -} +// import ( +// "encoding/binary" +// "fmt" +// ) + +// const ( +// G2BASE_LIMBS int = 16 +// ) + +// type G2BaseField struct { +// limbs [G2BASE_LIMBS]uint32 +// } + +// func (f G2BaseField) Len() int { +// return int(G2BASE_LIMBS) +// } + +// func (f G2BaseField) Size() int { +// return int(G2BASE_LIMBS * 4) +// } + +// func (f G2BaseField) GetLimbs() []uint32 { +// return f.limbs[:] +// } + +// func (f G2BaseField) AsPointer() *uint32 { +// return &f.limbs[0] +// } + +// func (f *G2BaseField) FromUint32(v uint32) G2BaseField { +// f.limbs[0] = v +// return *f +// } + +// func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { +// if len(limbs) != f.Len() { +// panic("Called FromLimbs with limbs of different length than field") +// } +// for i := range f.limbs { +// f.limbs[i] = limbs[i] +// } + +// return *f +// } + +// func (f *G2BaseField) Zero() G2BaseField { +// for i := range f.limbs { +// f.limbs[i] = 0 +// } + +// return *f +// } + +// func (f *G2BaseField) One() G2BaseField { +// for i := range f.limbs { +// f.limbs[i] = 0 +// } +// f.limbs[0] = 1 + +// return *f +// } + +// func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { +// if len(bytes)/4 != f.Len() { +// panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) +// } + +// for i := range f.limbs { +// f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) +// } + +// return *f +// } + +// func (f G2BaseField) ToBytesLittleEndian() []byte { +// bytes := make([]byte, f.Len()*4) +// for i, v := range f.limbs { +// binary.LittleEndian.PutUint32(bytes[i*4:], v) +// } + +// return bytes +// } diff --git a/wrappers/golang_v3/curves/bn254/g2/include/scalar_field.h b/wrappers/golang_v3/curves/bn254/g2/include/scalar_field.h index f37e47db9..9101faa80 100644 --- a/wrappers/golang_v3/curves/bn254/g2/include/scalar_field.h +++ b/wrappers/golang_v3/curves/bn254/g2/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BN254_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void bn254_generate_scalars(scalar_t* scalars, int size); -cudaError_t bn254_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int bn254_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/g2/msm.go b/wrappers/golang_v3/curves/bn254/g2/msm.go index 1e2c8d3e2..9a01ee6d8 100644 --- a/wrappers/golang_v3/curves/bn254/g2/msm.go +++ b/wrappers/golang_v3/curves/bn254/g2/msm.go @@ -1,63 +1,63 @@ package g2 -// #cgo CFLAGS: -I./include/ -// #include "msm.h" -import "C" - -import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - "unsafe" -) - -func G2GetDefaultMSMConfig() core.MSMConfig { - return core.GetDefaultMSMConfig() -} - -func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) - - cScalars := (*C.scalar_t)(scalarsPointer) - cPoints := (*C.g2_affine_t)(pointsPointer) - cResults := (*C.g2_projective_t)(resultsPointer) - cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) - - __ret := C.bn254_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) - return err -} - -// Deprecated: G2PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// G2PrecomputePoints should be used instead. -func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := G2GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.g2_affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.g2_affine_t)(outputBasesPointer) - - __ret := C.bn254_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) - return err -} - -func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) - - cPoints := (*C.g2_affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) - cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) - cOutputBases := (*C.g2_affine_t)(outputBasesPointer) - - __ret := C.bn254_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) - return err -} +// // #cgo CFLAGS: -I./include/ +// // #include "msm.h" +// import "C" + +// import ( +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" +// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +// "unsafe" +// ) + +// func G2GetDefaultMSMConfig() core.MSMConfig { +// return core.GetDefaultMSMConfig() +// } + +// func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { +// scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + +// cScalars := (*C.scalar_t)(scalarsPointer) +// cPoints := (*C.g2_affine_t)(pointsPointer) +// cResults := (*C.g2_projective_t)(resultsPointer) +// cSize := (C.int)(size) +// cCfg := (*C.MSMConfig)(cfgPointer) + +// __ret := C.bn254_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) +// err := (cr.CudaError)(__ret) +// return err +// } + +// // Deprecated: G2PrecomputeBases exists for backward compatibility. +// // It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. +// // G2PrecomputePoints should be used instead. +// func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { +// cfg := G2GetDefaultMSMConfig() +// cfg.PrecomputeFactor = precomputeFactor +// pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) + +// cPoints := (*C.g2_affine_t)(pointsPointer) +// cPointsLen := (C.int)(points.Len()) +// cPrecomputeFactor := (C.int)(precomputeFactor) +// cC := (C.int)(c) +// cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) +// cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) +// cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + +// __ret := C.bn254_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) +// err := (cr.CudaError)(__ret) +// return err +// } + +// func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { +// pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) + +// cPoints := (*C.g2_affine_t)(pointsPointer) +// cMsmSize := (C.int)(msmSize) +// cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) +// cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + +// __ret := C.bn254_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) +// err := (cr.CudaError)(__ret) +// return err +// } diff --git a/wrappers/golang_v3/curves/bn254/include/curve.h b/wrappers/golang_v3/curves/bn254/include/curve.h index 069600aa4..d42ac01b4 100644 --- a/wrappers/golang_v3/curves/bn254/include/curve.h +++ b/wrappers/golang_v3/curves/bn254/include/curve.h @@ -10,14 +10,14 @@ extern "C" { typedef struct projective_t projective_t; typedef struct affine_t affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool bn254_eq(projective_t* point1, projective_t* point2); void bn254_to_affine(projective_t* point, affine_t* point_out); void bn254_generate_projective_points(projective_t* points, int size); void bn254_generate_affine_points(affine_t* points, int size); -cudaError_t bn254_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t bn254_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bn254_affine_convert_montgomery(const affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, affine_t* d_out); +cudaError_t bn254_projective_convert_montgomery(const projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/include/scalar_field.h b/wrappers/golang_v3/curves/bn254/include/scalar_field.h index f37e47db9..9101faa80 100644 --- a/wrappers/golang_v3/curves/bn254/include/scalar_field.h +++ b/wrappers/golang_v3/curves/bn254/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BN254_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void bn254_generate_scalars(scalar_t* scalars, int size); -cudaError_t bn254_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int bn254_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/main.go b/wrappers/golang_v3/curves/bn254/main.go index 2d88cd5be..3acfd384b 100644 --- a/wrappers/golang_v3/curves/bn254/main.go +++ b/wrappers/golang_v3/curves/bn254/main.go @@ -1,4 +1,4 @@ package bn254 -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bn254 -lingo_field_bn254 -lstdc++ -lm +// #cgo LDFLAGS: -L${SRCDIR}/../../../icicle_v3/build -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../icicle_v3/build import "C" diff --git a/wrappers/golang_v3/curves/bn254/msm/include/msm.h b/wrappers/golang_v3/curves/bn254/msm/include/msm.h index 47985945a..456e27878 100644 --- a/wrappers/golang_v3/curves/bn254/msm/include/msm.h +++ b/wrappers/golang_v3/curves/bn254/msm/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BN254_MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct projective_t projective_t; typedef struct affine_t affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t bn254_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); -cudaError_t bn254_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); -cudaError_t bn254_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); +int bn254_msm(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); +int bn254_msm_precompute_bases(affine_t* points, int bases_size, MSMConfig* config, affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/msm/msm.go b/wrappers/golang_v3/curves/bn254/msm/msm.go index 61695d82c..42014c94d 100644 --- a/wrappers/golang_v3/curves/bn254/msm/msm.go +++ b/wrappers/golang_v3/curves/bn254/msm/msm.go @@ -5,16 +5,17 @@ package msm import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) @@ -23,41 +24,41 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor cSize := (C.int)(size) cCfg := (*C.MSMConfig)(cfgPointer) - __ret := C.bn254_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) + __ret := C.bn254_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } // Deprecated: PrecomputeBases exists for backward compatibility. // It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. // PrecomputePoints should be used instead. -func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) +// func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) runtime.EIcicleError { +// cfg := GetDefaultMSMConfig() +// cfg.PrecomputeFactor = precomputeFactor +// pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - cPoints := (*C.affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.affine_t)(outputBasesPointer) +// cPoints := (*C.affine_t)(pointsPointer) +// cPointsLen := (C.int)(points.Len()) +// cPrecomputeFactor := (C.int)(precomputeFactor) +// cC := (C.int)(c) +// cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) +// cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) +// cOutputBases := (*C.affine_t)(outputBasesPointer) - __ret := C.bn254_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) - return err -} +// __ret := C.bn254_precompute_msm_bases(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) +// err := (runtime.EIcicleError)(__ret) +// return err +// } -func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { +func PrecomputeBases(points core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) cPoints := (*C.affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cMsmSize := (C.int)(points.Len()) cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.affine_t)(outputBasesPointer) - __ret := C.bn254_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bn254_msm_precompute_bases(cPoints, cMsmSize, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bn254/ntt/include/ntt.h b/wrappers/golang_v3/curves/bn254/ntt/include/ntt.h index 48b244aa1..92d468fd6 100644 --- a/wrappers/golang_v3/curves/bn254/ntt/include/ntt.h +++ b/wrappers/golang_v3/curves/bn254/ntt/include/ntt.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BN254_NTT_H @@ -10,11 +9,12 @@ extern "C" { typedef struct scalar_t scalar_t; typedef struct NTTConfig NTTConfig; -typedef struct DeviceContext DeviceContext; +typedef struct NTTInitDomainConfig NTTInitDomainConfig; -cudaError_t bn254_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); -cudaError_t bn254_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); -cudaError_t bn254_release_domain(DeviceContext* ctx); +int bn254_ntt(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +int bn254_ntt_init_domain(scalar_t* primitive_root, NTTInitDomainConfig* ctx); +int bn254_ntt_release_domain(); +int* bn254_get_root_of_unity(size_t size); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/ntt/ntt.go b/wrappers/golang_v3/curves/bn254/ntt/ntt.go index 3137c8001..7c9c92652 100644 --- a/wrappers/golang_v3/curves/bn254/ntt/ntt.go +++ b/wrappers/golang_v3/curves/bn254/ntt/ntt.go @@ -4,17 +4,15 @@ package ntt // #include "ntt.h" import "C" -import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" -) - import ( "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) @@ -23,9 +21,9 @@ func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTCo cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.scalar_t)(resultsPointer) - __ret := C.bn254_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.bn254_ntt(cScalars, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } func GetDefaultNttConfig() core.NTTConfig[[bn254.SCALAR_LIMBS]uint32] { @@ -39,18 +37,23 @@ func GetDefaultNttConfig() core.NTTConfig[[bn254.SCALAR_LIMBS]uint32] { return core.GetDefaultNTTConfig(cosetGen) } -func InitDomain(primitiveRoot bn254.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { +func GetRootOfUnity(size uint64) bn254.ScalarField { + cRes := C.bn254_get_root_of_unity((C.size_t)(size)) + var res bn254.ScalarField + res.FromLimbs(*(*[]uint32)(unsafe.Pointer(cRes))) + return res +} + +func InitDomain(primitiveRoot bn254.ScalarField, cfg core.NTTInitDomainConfig) runtime.EIcicleError { cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cFastTwiddles := (C._Bool)(fastTwiddles) - __ret := C.bn254_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + cCfg := (*C.NTTInitDomainConfig)(unsafe.Pointer(&cfg)) + __ret := C.bn254_ntt_init_domain(cPrimitiveRoot, cCfg) + err := runtime.EIcicleError(__ret) + return err } -func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - __ret := C.bn254_release_domain(cCtx) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) +func ReleaseDomain() runtime.EIcicleError { + __ret := C.bn254_ntt_release_domain() + err := runtime.EIcicleError(__ret) + return err } diff --git a/wrappers/golang_v3/curves/bn254/polynomial/include/polynomial.h b/wrappers/golang_v3/curves/bn254/polynomial/include/polynomial.h index 14cf6eeb2..fe8e9a1af 100644 --- a/wrappers/golang_v3/curves/bn254/polynomial/include/polynomial.h +++ b/wrappers/golang_v3/curves/bn254/polynomial/include/polynomial.h @@ -12,7 +12,6 @@ typedef struct scalar_t scalar_t; typedef struct PolynomialInst PolynomialInst; typedef struct IntegrityPointer IntegrityPointer; -bool bn254_polynomial_init_cuda_backend(); PolynomialInst* bn254_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); PolynomialInst* bn254_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); PolynomialInst* bn254_polynomial_clone(const PolynomialInst* p); diff --git a/wrappers/golang_v3/curves/bn254/polynomial/polynomial.go b/wrappers/golang_v3/curves/bn254/polynomial/polynomial.go index ffee8af55..64bf9bda1 100644 --- a/wrappers/golang_v3/curves/bn254/polynomial/polynomial.go +++ b/wrappers/golang_v3/curves/bn254/polynomial/polynomial.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" ) type PolynomialHandle = C.struct_PolynomialInst @@ -17,10 +17,6 @@ type DensePolynomial struct { handle *PolynomialHandle } -func InitPolyBackend() bool { - return (bool)(C.bn254_polynomial_init_cuda_backend()) -} - func (up *DensePolynomial) Print() { C.bn254_polynomial_print(up.handle) } diff --git a/wrappers/golang_v3/curves/bn254/scalar_field.go b/wrappers/golang_v3/curves/bn254/scalar_field.go index cac10ce8c..8c9019290 100644 --- a/wrappers/golang_v3/curves/bn254/scalar_field.go +++ b/wrappers/golang_v3/curves/bn254/scalar_field.go @@ -6,8 +6,8 @@ import "C" import ( "encoding/binary" "fmt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "unsafe" ) @@ -99,23 +99,20 @@ func GenerateScalars(size int) core.HostSlice[ScalarField] { return scalarSlice } -func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) - cSize := (C.size_t)(scalars.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bn254_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*scalars, *scalars, *scalars, &defaultCfg) + cErr := C.bn254_scalar_convert_montgomery((*C.scalar_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.scalar_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func ToMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, true) } -func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func FromMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, false) } diff --git a/wrappers/golang_v3/curves/bn254/tests/base_field_test.go b/wrappers/golang_v3/curves/bn254/tests/base_field_test.go index 72b5b9a1c..07d4f84c4 100644 --- a/wrappers/golang_v3/curves/bn254/tests/base_field_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/base_field_test.go @@ -1,8 +1,8 @@ package tests import ( - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/curves/bn254/tests/curve_test.go b/wrappers/golang_v3/curves/bn254/tests/curve_test.go index 4774340e5..92c3a3519 100644 --- a/wrappers/golang_v3/curves/bn254/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/curve_test.go @@ -1,103 +1,103 @@ package tests -import ( - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestAffineZero(t *testing.T) { - var fieldZero = bn254.BaseField{} - - var affineZero bn254.Affine - assert.Equal(t, affineZero.X, fieldZero) - assert.Equal(t, affineZero.Y, fieldZero) - - x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - var affine bn254.Affine - affine.FromLimbs(x, y) - - affine.Zero() - assert.Equal(t, affine.X, fieldZero) - assert.Equal(t, affine.Y, fieldZero) -} - -func TestAffineFromLimbs(t *testing.T) { - randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - - var affine bn254.Affine - affine.FromLimbs(randLimbs, randLimbs2) - - assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) - assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) -} - -func TestAffineToProjective(t *testing.T) { - randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - var fieldOne bn254.BaseField - fieldOne.One() - - var expected bn254.Projective - expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) - - var affine bn254.Affine - affine.FromLimbs(randLimbs, randLimbs2) - - projectivePoint := affine.ToProjective() - assert.Equal(t, expected, projectivePoint) -} - -func TestProjectiveZero(t *testing.T) { - var projectiveZero bn254.Projective - projectiveZero.Zero() - var fieldZero = bn254.BaseField{} - var fieldOne bn254.BaseField - fieldOne.One() - - assert.Equal(t, projectiveZero.X, fieldZero) - assert.Equal(t, projectiveZero.Y, fieldOne) - assert.Equal(t, projectiveZero.Z, fieldZero) - - randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - var projective bn254.Projective - projective.FromLimbs(randLimbs, randLimbs, randLimbs) - - projective.Zero() - assert.Equal(t, projective.X, fieldZero) - assert.Equal(t, projective.Y, fieldOne) - assert.Equal(t, projective.Z, fieldZero) -} - -func TestProjectiveFromLimbs(t *testing.T) { - randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - - var projective bn254.Projective - projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) - - assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) - assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) - assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) -} - -func TestProjectiveFromAffine(t *testing.T) { - randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - var fieldOne bn254.BaseField - fieldOne.One() - - var expected bn254.Projective - expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) - - var affine bn254.Affine - affine.FromLimbs(randLimbs, randLimbs2) - - var projectivePoint bn254.Projective - projectivePoint.FromAffine(affine) - assert.Equal(t, expected, projectivePoint) -} +// import ( +// bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" +// "github.com/stretchr/testify/assert" +// "testing" +// ) + +// func TestAffineZero(t *testing.T) { +// var fieldZero = bn254.BaseField{} + +// var affineZero bn254.Affine +// assert.Equal(t, affineZero.X, fieldZero) +// assert.Equal(t, affineZero.Y, fieldZero) + +// x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// var affine bn254.Affine +// affine.FromLimbs(x, y) + +// affine.Zero() +// assert.Equal(t, affine.X, fieldZero) +// assert.Equal(t, affine.Y, fieldZero) +// } + +// func TestAffineFromLimbs(t *testing.T) { +// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + +// var affine bn254.Affine +// affine.FromLimbs(randLimbs, randLimbs2) + +// assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) +// assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +// } + +// func TestAffineToProjective(t *testing.T) { +// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// var fieldOne bn254.BaseField +// fieldOne.One() + +// var expected bn254.Projective +// expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + +// var affine bn254.Affine +// affine.FromLimbs(randLimbs, randLimbs2) + +// projectivePoint := affine.ToProjective() +// assert.Equal(t, expected, projectivePoint) +// } + +// func TestProjectiveZero(t *testing.T) { +// var projectiveZero bn254.Projective +// projectiveZero.Zero() +// var fieldZero = bn254.BaseField{} +// var fieldOne bn254.BaseField +// fieldOne.One() + +// assert.Equal(t, projectiveZero.X, fieldZero) +// assert.Equal(t, projectiveZero.Y, fieldOne) +// assert.Equal(t, projectiveZero.Z, fieldZero) + +// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// var projective bn254.Projective +// projective.FromLimbs(randLimbs, randLimbs, randLimbs) + +// projective.Zero() +// assert.Equal(t, projective.X, fieldZero) +// assert.Equal(t, projective.Y, fieldOne) +// assert.Equal(t, projective.Z, fieldZero) +// } + +// func TestProjectiveFromLimbs(t *testing.T) { +// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + +// var projective bn254.Projective +// projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + +// assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) +// assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) +// assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +// } + +// func TestProjectiveFromAffine(t *testing.T) { +// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) +// var fieldOne bn254.BaseField +// fieldOne.One() + +// var expected bn254.Projective +// expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + +// var affine bn254.Affine +// affine.FromLimbs(randLimbs, randLimbs2) + +// var projectivePoint bn254.Projective +// projectivePoint.FromAffine(affine) +// assert.Equal(t, expected, projectivePoint) +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go index 08587bba6..77182d9dd 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go @@ -1,30 +1,30 @@ package tests -import ( - "testing" +// import ( +// "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ecntt" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" - "github.com/stretchr/testify/assert" -) +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" +// bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" +// ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ecntt" +// ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" +// "github.com/stretchr/testify/assert" +// ) -func TestECNtt(t *testing.T) { - cfg := ntt.GetDefaultNttConfig() - points := bn254.GenerateProjectivePoints(1 << largestTestSize) +// func TestECNtt(t *testing.T) { +// cfg := ntt.GetDefaultNttConfig() +// points := bn254.GenerateProjectivePoints(1 << largestTestSize) - for _, size := range []int{4, 5, 6, 7, 8} { - for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { - testSize := 1 << size +// for _, size := range []int{4, 5, 6, 7, 8} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size - pointsCopy := core.HostSliceFromElements[bn254.Projective](points[:testSize]) - cfg.Ordering = v - cfg.NttAlgorithm = core.Radix2 +// pointsCopy := core.HostSliceFromElements[bn254.Projective](points[:testSize]) +// cfg.Ordering = v +// cfg.NttAlgorithm = core.Radix2 - output := make(core.HostSlice[bn254.Projective], testSize) - e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") - } - } -} +// output := make(core.HostSlice[bn254.Projective], testSize) +// e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) +// assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") +// } +// } +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go index 546aa81bb..9f1cd6bbb 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go @@ -1,103 +1,103 @@ package tests -import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestG2AffineZero(t *testing.T) { - var fieldZero = g2.G2BaseField{} - - var affineZero g2.G2Affine - assert.Equal(t, affineZero.X, fieldZero) - assert.Equal(t, affineZero.Y, fieldZero) - - x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - var affine g2.G2Affine - affine.FromLimbs(x, y) - - affine.Zero() - assert.Equal(t, affine.X, fieldZero) - assert.Equal(t, affine.Y, fieldZero) -} - -func TestG2AffineFromLimbs(t *testing.T) { - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - - var affine g2.G2Affine - affine.FromLimbs(randLimbs, randLimbs2) - - assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) - assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) -} - -func TestG2AffineToProjective(t *testing.T) { - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - var fieldOne g2.G2BaseField - fieldOne.One() - - var expected g2.G2Projective - expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) - - var affine g2.G2Affine - affine.FromLimbs(randLimbs, randLimbs2) - - projectivePoint := affine.ToProjective() - assert.Equal(t, expected, projectivePoint) -} - -func TestG2ProjectiveZero(t *testing.T) { - var projectiveZero g2.G2Projective - projectiveZero.Zero() - var fieldZero = g2.G2BaseField{} - var fieldOne g2.G2BaseField - fieldOne.One() - - assert.Equal(t, projectiveZero.X, fieldZero) - assert.Equal(t, projectiveZero.Y, fieldOne) - assert.Equal(t, projectiveZero.Z, fieldZero) - - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - var projective g2.G2Projective - projective.FromLimbs(randLimbs, randLimbs, randLimbs) - - projective.Zero() - assert.Equal(t, projective.X, fieldZero) - assert.Equal(t, projective.Y, fieldOne) - assert.Equal(t, projective.Z, fieldZero) -} - -func TestG2ProjectiveFromLimbs(t *testing.T) { - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - - var projective g2.G2Projective - projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) - - assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) - assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) - assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) -} - -func TestG2ProjectiveFromAffine(t *testing.T) { - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - var fieldOne g2.G2BaseField - fieldOne.One() - - var expected g2.G2Projective - expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) - - var affine g2.G2Affine - affine.FromLimbs(randLimbs, randLimbs2) - - var projectivePoint g2.G2Projective - projectivePoint.FromAffine(affine) - assert.Equal(t, expected, projectivePoint) -} +// import ( +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" +// "github.com/stretchr/testify/assert" +// "testing" +// ) + +// func TestG2AffineZero(t *testing.T) { +// var fieldZero = g2.G2BaseField{} + +// var affineZero g2.G2Affine +// assert.Equal(t, affineZero.X, fieldZero) +// assert.Equal(t, affineZero.Y, fieldZero) + +// x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// var affine g2.G2Affine +// affine.FromLimbs(x, y) + +// affine.Zero() +// assert.Equal(t, affine.X, fieldZero) +// assert.Equal(t, affine.Y, fieldZero) +// } + +// func TestG2AffineFromLimbs(t *testing.T) { +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + +// var affine g2.G2Affine +// affine.FromLimbs(randLimbs, randLimbs2) + +// assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) +// assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +// } + +// func TestG2AffineToProjective(t *testing.T) { +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// var fieldOne g2.G2BaseField +// fieldOne.One() + +// var expected g2.G2Projective +// expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + +// var affine g2.G2Affine +// affine.FromLimbs(randLimbs, randLimbs2) + +// projectivePoint := affine.ToProjective() +// assert.Equal(t, expected, projectivePoint) +// } + +// func TestG2ProjectiveZero(t *testing.T) { +// var projectiveZero g2.G2Projective +// projectiveZero.Zero() +// var fieldZero = g2.G2BaseField{} +// var fieldOne g2.G2BaseField +// fieldOne.One() + +// assert.Equal(t, projectiveZero.X, fieldZero) +// assert.Equal(t, projectiveZero.Y, fieldOne) +// assert.Equal(t, projectiveZero.Z, fieldZero) + +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// var projective g2.G2Projective +// projective.FromLimbs(randLimbs, randLimbs, randLimbs) + +// projective.Zero() +// assert.Equal(t, projective.X, fieldZero) +// assert.Equal(t, projective.Y, fieldOne) +// assert.Equal(t, projective.Z, fieldZero) +// } + +// func TestG2ProjectiveFromLimbs(t *testing.T) { +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + +// var projective g2.G2Projective +// projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + +// assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) +// assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) +// assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +// } + +// func TestG2ProjectiveFromAffine(t *testing.T) { +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// var fieldOne g2.G2BaseField +// fieldOne.One() + +// var expected g2.G2Projective +// expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + +// var affine g2.G2Affine +// affine.FromLimbs(randLimbs, randLimbs2) + +// var projectivePoint g2.G2Projective +// projectivePoint.FromAffine(affine) +// assert.Equal(t, expected, projectivePoint) +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go index b822ed7ac..024c05f2a 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go @@ -1,88 +1,88 @@ package tests -import ( - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" - "testing" -) - -const ( - G2BASE_LIMBS = bn254.G2BASE_LIMBS -) - -func TestG2BaseFieldFromLimbs(t *testing.T) { - emptyField := bn254.G2BaseField{} - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - emptyField.FromLimbs(randLimbs[:]) - assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") - randLimbs[0] = 100 - assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) -} - -func TestG2BaseFieldGetLimbs(t *testing.T) { - emptyField := bn254.G2BaseField{} - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - emptyField.FromLimbs(randLimbs[:]) - - assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") -} - -func TestG2BaseFieldOne(t *testing.T) { - var emptyField bn254.G2BaseField - emptyField.One() - limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS)) - assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") - - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - emptyField.FromLimbs(randLimbs[:]) - - emptyField.One() - assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") -} - -func TestG2BaseFieldZero(t *testing.T) { - var emptyField bn254.G2BaseField - emptyField.Zero() - limbsZero := make([]uint32, G2BASE_LIMBS) - assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") - - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - emptyField.FromLimbs(randLimbs[:]) - - emptyField.Zero() - assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") -} - -func TestG2BaseFieldSize(t *testing.T) { - var emptyField bn254.G2BaseField - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - emptyField.FromLimbs(randLimbs[:]) - - assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") -} - -func TestG2BaseFieldAsPointer(t *testing.T) { - var emptyField bn254.G2BaseField - randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - emptyField.FromLimbs(randLimbs[:]) - - assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") -} - -func TestG2BaseFieldFromBytes(t *testing.T) { - var emptyField bn254.G2BaseField - bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) - - emptyField.FromBytesLittleEndian(bytes) - - assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") -} - -func TestG2BaseFieldToBytes(t *testing.T) { - var emptyField bn254.G2BaseField - expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) - emptyField.FromLimbs(limbs) - - assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") -} +// import ( +// bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" +// "github.com/stretchr/testify/assert" +// "testing" +// ) + +// const ( +// G2BASE_LIMBS = bn254.G2BASE_LIMBS +// ) + +// func TestG2BaseFieldFromLimbs(t *testing.T) { +// emptyField := bn254.G2BaseField{} +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// emptyField.FromLimbs(randLimbs[:]) +// assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +// randLimbs[0] = 100 +// assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +// } + +// func TestG2BaseFieldGetLimbs(t *testing.T) { +// emptyField := bn254.G2BaseField{} +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// emptyField.FromLimbs(randLimbs[:]) + +// assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +// } + +// func TestG2BaseFieldOne(t *testing.T) { +// var emptyField bn254.G2BaseField +// emptyField.One() +// limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS)) +// assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// emptyField.FromLimbs(randLimbs[:]) + +// emptyField.One() +// assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +// } + +// func TestG2BaseFieldZero(t *testing.T) { +// var emptyField bn254.G2BaseField +// emptyField.Zero() +// limbsZero := make([]uint32, G2BASE_LIMBS) +// assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// emptyField.FromLimbs(randLimbs[:]) + +// emptyField.Zero() +// assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +// } + +// func TestG2BaseFieldSize(t *testing.T) { +// var emptyField bn254.G2BaseField +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// emptyField.FromLimbs(randLimbs[:]) + +// assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +// } + +// func TestG2BaseFieldAsPointer(t *testing.T) { +// var emptyField bn254.G2BaseField +// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) +// emptyField.FromLimbs(randLimbs[:]) + +// assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +// } + +// func TestG2BaseFieldFromBytes(t *testing.T) { +// var emptyField bn254.G2BaseField +// bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + +// emptyField.FromBytesLittleEndian(bytes) + +// assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +// } + +// func TestG2BaseFieldToBytes(t *testing.T) { +// var emptyField bn254.G2BaseField +// expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) +// emptyField.FromLimbs(limbs) + +// assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go index 8c1eb3da1..24feb123a 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go @@ -1,371 +1,371 @@ package tests -import ( - "fmt" - "sync" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark-crypto/ecc/bn254" - "github.com/consensys/gnark-crypto/ecc/bn254/fp" - "github.com/consensys/gnark-crypto/ecc/bn254/fr" - - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" -) - -func projectiveToGnarkAffineG2(p g2.G2Projective) bn254.G2Affine { - pxBytes := p.X.ToBytesLittleEndian() - pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) - pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) - x := bn254.E2{ - A0: pxA0, - A1: pxA1, - } - - pyBytes := p.Y.ToBytesLittleEndian() - pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) - pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) - y := bn254.E2{ - A0: pyA0, - A1: pyA1, - } - - pzBytes := p.Z.ToBytesLittleEndian() - pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) - pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) - z := bn254.E2{ - A0: pzA0, - A1: pzA1, - } - - var zSquared bn254.E2 - zSquared.Mul(&z, &z) - - var X bn254.E2 - X.Mul(&x, &z) - - var Y bn254.E2 - Y.Mul(&y, &zSquared) - - g2Jac := bn254.G2Jac{ - X: X, - Y: Y, - Z: z, - } - - var g2Affine bn254.G2Affine - return *g2Affine.FromJacobian(&g2Jac) -} - -func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBn254.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { - scalarsFr := make([]fr.Element, len(scalars)) - for i, v := range scalars { - slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) - scalarsFr[i] = slice64 - } - - pointsFp := make([]bn254.G2Affine, len(points)) - for i, v := range points { - pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) - } - - return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) -} - -func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bn254.G2Affine], out g2.G2Projective) bool { - var msmRes bn254.G2Jac - msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - - var icicleResAsJac bn254.G2Jac - proj := projectiveToGnarkAffineG2(out) - icicleResAsJac.FromAffine(&proj) - - return msmRes.Equal(&icicleResAsJac) -} - -func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bn254.G2Affine { - points := make([]bn254.G2Affine, len(iciclePoints)) - for index, iciclePoint := range iciclePoints { - xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian()) - xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes]) - xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:]) - xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes) - xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes) - - yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian()) - yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes]) - yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:]) - yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes) - yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes) - - points[index] = bn254.G2Affine{ - X: bn254.E2{ - A0: xA0Elem, - A1: xA1Elem, - }, - Y: bn254.E2{ - A0: yA0Elem, - A1: yA1Elem, - }, - } - } - - return points -} - -func TestMSMG2(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { - size := 1 << power - - scalars := icicleBn254.GenerateScalars(size) - points := g2.G2GenerateAffinePoints(size) - - stream, _ := cr.CreateStream() - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream - - e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") - outHost := make(core.HostSlice[g2.G2Projective], 1) - outHost.CopyFromDeviceAsync(&out, stream) - out.FreeAsync(stream) - - cr.SynchronizeStream(&stream) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - - } -} - -func TestMSMG2PinnedHostMemory(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicleBn254.GenerateScalars(size) - points := g2.G2GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[g2.G2Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[g2.G2Projective], 1) - - e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - - if pinnableAndLockable { - e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) - - } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} -func TestMSMG2GnarkCryptoTypes(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{3} { - size := 1 << power - - scalars := make([]fr.Element, size) - var x fr.Element - for i := 0; i < size; i++ { - x.SetRandom() - scalars[i] = x - } - scalarsHost := (core.HostSlice[fr.Element])(scalars) - points := g2.G2GenerateAffinePoints(size) - pointsGnark := convertIcicleG2AffineToG2Affine(points) - pointsHost := (core.HostSlice[bn254.G2Affine])(pointsGnark) - - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true - cfg.AreScalarsMontgomeryForm = true - - e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") - outHost := make(core.HostSlice[g2.G2Projective], 1) - outHost.CopyFromDevice(&out) - out.Free() - - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) - } -} - -func TestMSMG2Batch(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { - size := 1 << power - totalSize := size * batchSize - scalars := icicleBn254.GenerateScalars(totalSize) - points := g2.G2GenerateAffinePoints(totalSize) - - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - - e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") - outHost := make(core.HostSlice[g2.G2Projective], batchSize) - outHost.CopyFromDevice(&out) - out.Free() - // Check with gnark-crypto - for i := 0; i < batchSize; i++ { - scalarsSlice := scalars[i*size : (i+1)*size] - pointsSlice := points[i*size : (i+1)*size] - out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) - } - } - } -} - -func TestPrecomputePointsG2(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - const precomputeFactor = 8 - cfg.PrecomputeFactor = precomputeFactor - - for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { - size := 1 << power - totalSize := size * batchSize - scalars := icicleBn254.GenerateScalars(totalSize) - points := g2.G2GenerateAffinePoints(totalSize) - - var precomputeOut core.DeviceSlice - _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") - - e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") - - var p g2.G2Projective - var out core.DeviceSlice - _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") - - e = g2.G2Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") - outHost := make(core.HostSlice[g2.G2Projective], batchSize) - outHost.CopyFromDevice(&out) - out.Free() - precomputeOut.Free() - // Check with gnark-crypto - for i := 0; i < batchSize; i++ { - scalarsSlice := scalars[i*size : (i+1)*size] - pointsSlice := points[i*size : (i+1)*size] - out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) - } - } - } -} - -func TestMSMG2SkewedDistribution(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { - size := 1 << power - - scalars := icicleBn254.GenerateScalars(size) - for i := size / 4; i < size; i++ { - scalars[i].One() - } - points := g2.G2GenerateAffinePoints(size) - for i := 0; i < size/4; i++ { - points[i].Zero() - } - - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - - e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") - outHost := make(core.HostSlice[g2.G2Projective], 1) - outHost.CopyFromDevice(&out) - out.Free() - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - } -} - -func TestMSMG2MultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") - wg := sync.WaitGroup{} - - for i := 0; i < numDevices; i++ { - wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { - defer wg.Done() - cfg := g2.G2GetDefaultMSMConfig() - cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { - size := 1 << power - scalars := icicleBn254.GenerateScalars(size) - points := g2.G2GenerateAffinePoints(size) - - stream, _ := cr.CreateStream() - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream - - e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") - outHost := make(core.HostSlice[g2.G2Projective], 1) - outHost.CopyFromDeviceAsync(&out, stream) - out.FreeAsync(stream) - - cr.SynchronizeStream(&stream) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - } - }) - } - wg.Wait() -} +// import ( +// "fmt" +// "sync" +// "testing" + +// "github.com/stretchr/testify/assert" + +// "github.com/consensys/gnark-crypto/ecc" +// "github.com/consensys/gnark-crypto/ecc/bn254" +// "github.com/consensys/gnark-crypto/ecc/bn254/fp" +// "github.com/consensys/gnark-crypto/ecc/bn254/fr" + +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" +// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +// icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" +// ) + +// func projectiveToGnarkAffineG2(p g2.G2Projective) bn254.G2Affine { +// pxBytes := p.X.ToBytesLittleEndian() +// pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) +// pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) +// x := bn254.E2{ +// A0: pxA0, +// A1: pxA1, +// } + +// pyBytes := p.Y.ToBytesLittleEndian() +// pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) +// pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) +// y := bn254.E2{ +// A0: pyA0, +// A1: pyA1, +// } + +// pzBytes := p.Z.ToBytesLittleEndian() +// pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) +// pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) +// z := bn254.E2{ +// A0: pzA0, +// A1: pzA1, +// } + +// var zSquared bn254.E2 +// zSquared.Mul(&z, &z) + +// var X bn254.E2 +// X.Mul(&x, &z) + +// var Y bn254.E2 +// Y.Mul(&y, &zSquared) + +// g2Jac := bn254.G2Jac{ +// X: X, +// Y: Y, +// Z: z, +// } + +// var g2Affine bn254.G2Affine +// return *g2Affine.FromJacobian(&g2Jac) +// } + +// func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBn254.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { +// scalarsFr := make([]fr.Element, len(scalars)) +// for i, v := range scalars { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } + +// pointsFp := make([]bn254.G2Affine, len(points)) +// for i, v := range points { +// pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) +// } + +// return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) +// } + +// func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bn254.G2Affine], out g2.G2Projective) bool { +// var msmRes bn254.G2Jac +// msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + +// var icicleResAsJac bn254.G2Jac +// proj := projectiveToGnarkAffineG2(out) +// icicleResAsJac.FromAffine(&proj) + +// return msmRes.Equal(&icicleResAsJac) +// } + +// func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bn254.G2Affine { +// points := make([]bn254.G2Affine, len(iciclePoints)) +// for index, iciclePoint := range iciclePoints { +// xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian()) +// xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes]) +// xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:]) +// xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes) +// xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes) + +// yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian()) +// yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes]) +// yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:]) +// yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes) +// yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes) + +// points[index] = bn254.G2Affine{ +// X: bn254.E2{ +// A0: xA0Elem, +// A1: xA1Elem, +// }, +// Y: bn254.E2{ +// A0: yA0Elem, +// A1: yA1Elem, +// }, +// } +// } + +// return points +// } + +// func TestMSMG2(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// cfg.IsAsync = true +// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { +// size := 1 << power + +// scalars := icicleBn254.GenerateScalars(size) +// points := g2.G2GenerateAffinePoints(size) + +// stream, _ := cr.CreateStream() +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.MallocAsync(p.Size(), p.Size(), stream) +// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") +// cfg.Ctx.Stream = &stream + +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) +// outHost.CopyFromDeviceAsync(&out, stream) +// out.FreeAsync(stream) + +// cr.SynchronizeStream(&stream) +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + +// } +// } + +// func TestMSMG2PinnedHostMemory(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power + +// scalars := icicleBn254.GenerateScalars(size) +// points := g2.G2GenerateAffinePoints(size) + +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) + +// pinnableAndLockable := pinnable == 1 && lockable == 0 + +// var pinnedPoints core.HostSlice[g2.G2Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } + +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) + +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") + +// outHost.CopyFromDevice(&out) +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + +// if pinnableAndLockable { +// e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + +// outHost.CopyFromDevice(&out) +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) + +// } + +// out.Free() + +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } +// func TestMSMG2GnarkCryptoTypes(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// for _, power := range []int{3} { +// size := 1 << power + +// scalars := make([]fr.Element, size) +// var x fr.Element +// for i := 0; i < size; i++ { +// x.SetRandom() +// scalars[i] = x +// } +// scalarsHost := (core.HostSlice[fr.Element])(scalars) +// points := g2.G2GenerateAffinePoints(size) +// pointsGnark := convertIcicleG2AffineToG2Affine(points) +// pointsHost := (core.HostSlice[bn254.G2Affine])(pointsGnark) + +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") +// cfg.ArePointsMontgomeryForm = true +// cfg.AreScalarsMontgomeryForm = true + +// e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) +// outHost.CopyFromDevice(&out) +// out.Free() + +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) +// } +// } + +// func TestMSMG2Batch(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// for _, power := range []int{10, 16} { +// for _, batchSize := range []int{1, 3, 16} { +// size := 1 << power +// totalSize := size * batchSize +// scalars := icicleBn254.GenerateScalars(totalSize) +// points := g2.G2GenerateAffinePoints(totalSize) + +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.Malloc(batchSize*p.Size(), p.Size()) +// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") +// outHost := make(core.HostSlice[g2.G2Projective], batchSize) +// outHost.CopyFromDevice(&out) +// out.Free() +// // Check with gnark-crypto +// for i := 0; i < batchSize; i++ { +// scalarsSlice := scalars[i*size : (i+1)*size] +// pointsSlice := points[i*size : (i+1)*size] +// out := outHost[i] +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) +// } +// } +// } +// } + +// func TestPrecomputePointsG2(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// const precomputeFactor = 8 +// cfg.PrecomputeFactor = precomputeFactor + +// for _, power := range []int{10, 16} { +// for _, batchSize := range []int{1, 3, 16} { +// size := 1 << power +// totalSize := size * batchSize +// scalars := icicleBn254.GenerateScalars(totalSize) +// points := g2.G2GenerateAffinePoints(totalSize) + +// var precomputeOut core.DeviceSlice +// _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) +// assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + +// e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) +// assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e = out.Malloc(batchSize*p.Size(), p.Size()) +// assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + +// e = g2.G2Msm(scalars, precomputeOut, &cfg, out) +// assert.Equal(t, cr.CudaSuccess, e, "Msm failed") +// outHost := make(core.HostSlice[g2.G2Projective], batchSize) +// outHost.CopyFromDevice(&out) +// out.Free() +// precomputeOut.Free() +// // Check with gnark-crypto +// for i := 0; i < batchSize; i++ { +// scalarsSlice := scalars[i*size : (i+1)*size] +// pointsSlice := points[i*size : (i+1)*size] +// out := outHost[i] +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) +// } +// } +// } +// } + +// func TestMSMG2SkewedDistribution(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { +// size := 1 << power + +// scalars := icicleBn254.GenerateScalars(size) +// for i := size / 4; i < size; i++ { +// scalars[i].One() +// } +// points := g2.G2GenerateAffinePoints(size) +// for i := 0; i < size/4; i++ { +// points[i].Zero() +// } + +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) +// outHost.CopyFromDevice(&out) +// out.Free() +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) +// } +// } + +// func TestMSMG2MultiDevice(t *testing.T) { +// numDevices, _ := cr.GetDeviceCount() +// fmt.Println("There are ", numDevices, " devices available") +// wg := sync.WaitGroup{} + +// for i := 0; i < numDevices; i++ { +// wg.Add(1) +// cr.RunOnDevice(i, func(args ...any) { +// defer wg.Done() +// cfg := g2.G2GetDefaultMSMConfig() +// cfg.IsAsync = true +// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { +// size := 1 << power +// scalars := icicleBn254.GenerateScalars(size) +// points := g2.G2GenerateAffinePoints(size) + +// stream, _ := cr.CreateStream() +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.MallocAsync(p.Size(), p.Size(), stream) +// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") +// cfg.Ctx.Stream = &stream + +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) +// outHost.CopyFromDeviceAsync(&out, stream) +// out.FreeAsync(stream) + +// cr.SynchronizeStream(&stream) +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) +// } +// }) +// } +// wg.Wait() +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/main_test.go b/wrappers/golang_v3/curves/bn254/tests/main_test.go index f06c8a890..be9fe8fcd 100644 --- a/wrappers/golang_v3/curves/bn254/tests/main_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/main_test.go @@ -4,10 +4,10 @@ import ( "os" "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" - poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" ) @@ -16,24 +16,26 @@ const ( largestTestSize = 20 ) -func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { +func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() rouIcicle := bn254.ScalarField{} limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) rouIcicle.FromLimbs(limbs) - e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + e := ntt.InitDomain(rouIcicle, cfg) return e } func TestMain(m *testing.M) { - poly.InitPolyBackend() + runtime.LoadBackendFromEnv() + device := runtime.CreateDevice("CUDA", 0) + runtime.SetDevice(&device) // setup domain - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() e := initDomain(largestTestSize, cfg) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + if e != runtime.Success { panic("initDomain failed") } @@ -41,8 +43,8 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) // release domain - e = ntt.ReleaseDomain(cfg.Ctx) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + e = ntt.ReleaseDomain() + if e != runtime.Success { panic("ReleaseDomain failed") } } diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index eab2b0005..f84158077 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -1,8 +1,6 @@ package tests import ( - "fmt" - "sync" "testing" "github.com/stretchr/testify/assert" @@ -12,10 +10,10 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func projectiveToGnarkAffine(p icicleBn254.Projective) bn254.G1Affine { @@ -35,7 +33,7 @@ func projectiveToGnarkAffine(p icicleBn254.Projective) bn254.G1Affine { return bn254.G1Affine{X: *x, Y: *y} } -func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBn254.ScalarField], points core.HostSlice[icicleBn254.Affine], out icicleBn254.Projective) bool { +func testAgainstGnarkCryptoMsm(t *testing.T, scalars core.HostSlice[icicleBn254.ScalarField], points core.HostSlice[icicleBn254.Affine], out icicleBn254.Projective) { scalarsFr := make([]fr.Element, len(scalars)) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -47,10 +45,10 @@ func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBn254.ScalarField], pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) } - return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out) + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsFr, pointsFp, out) } -func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bn254.G1Affine], out icicleBn254.Projective) bool { +func testAgainstGnarkCryptoMsmGnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bn254.G1Affine], out icicleBn254.Projective) { var msmRes bn254.G1Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) @@ -58,7 +56,7 @@ func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Eleme proj := projectiveToGnarkAffine(out) icicleResAsJac.FromAffine(&proj) - return msmRes.Equal(&icicleResAsJac) + assert.True(t, msmRes.Equal(&icicleResAsJac)) } func convertIcicleAffineToG1Affine(iciclePoints []icicleBn254.Affine) []bn254.G1Affine { @@ -81,83 +79,82 @@ func convertIcicleAffineToG1Affine(iciclePoints []icicleBn254.Affine) []bn254.G1 func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5} { size := 1 << power scalars := icicleBn254.GenerateScalars(size) points := icicleBn254.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleBn254.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBn254.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } } -func TestMSMPinnedHostMemory(t *testing.T) { - cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power +// func TestMSMPinnedHostMemory(t *testing.T) { +// cfg := msm.GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power - scalars := icicleBn254.GenerateScalars(size) - points := icicleBn254.GenerateAffinePoints(size) +// scalars := icicleBn254.GenerateScalars(size) +// points := icicleBn254.GenerateAffinePoints(size) - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// pinnable := runtime.GetDeviceAttribute(runtime.CudaDevAttrHostRegisterSupported, 0) +// lockable := runtime.GetDeviceAttribute(runtime.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - pinnableAndLockable := pinnable == 1 && lockable == 0 +// pinnableAndLockable := pinnable == 1 && lockable == 0 - var pinnedPoints core.HostSlice[icicleBn254.Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } +// var pinnedPoints core.HostSlice[icicleBn254.Affine] +// if pinnableAndLockable { +// points.Pin(runtime.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(runtime.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } - var p icicleBn254.Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[icicleBn254.Projective], 1) +// var p icicleBn254.Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[icicleBn254.Projective], 1) - e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") +// e = msm.Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) +// outHost.CopyFromDevice(&out) +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - if pinnableAndLockable { - e = msm.Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") +// if pinnableAndLockable { +// e = msm.Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) +// outHost.CopyFromDevice(&out) +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) - } +// } - out.Free() +// out.Free() - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } func TestMSMGnarkCryptoTypes(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{3} { @@ -177,25 +174,25 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { var p icicleBn254.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true cfg.AreScalarsMontgomeryForm = true e = msm.Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBn254.Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } } func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, power := range []int{5} { + for _, batchSize := range []int{1, 3} { size := 1 << power totalSize := size * batchSize scalars := icicleBn254.GenerateScalars(totalSize) @@ -204,10 +201,10 @@ func TestMSMBatch(t *testing.T) { var p icicleBn254.Projective var out core.DeviceSlice _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBn254.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -216,52 +213,52 @@ func TestMSMBatch(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) } } } } -func TestPrecomputePoints(t *testing.T) { - cfg := msm.GetDefaultMSMConfig() - const precomputeFactor = 8 - cfg.PrecomputeFactor = precomputeFactor - - for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { - size := 1 << power - totalSize := size * batchSize - scalars := icicleBn254.GenerateScalars(totalSize) - points := icicleBn254.GenerateAffinePoints(totalSize) - - var precomputeOut core.DeviceSlice - _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") - - e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") - - var p icicleBn254.Projective - var out core.DeviceSlice - _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") - - e = msm.Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") - outHost := make(core.HostSlice[icicleBn254.Projective], batchSize) - outHost.CopyFromDevice(&out) - out.Free() - precomputeOut.Free() - // Check with gnark-crypto - for i := 0; i < batchSize; i++ { - scalarsSlice := scalars[i*size : (i+1)*size] - pointsSlice := points[i*size : (i+1)*size] - out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) - } - } - } -} +// func TestPrecomputePoints(t *testing.T) { +// cfg := msm.GetDefaultMSMConfig() +// const precomputeFactor = 8 +// cfg.PrecomputeFactor = precomputeFactor + +// for _, power := range []int{10, 16} { +// for _, batchSize := range []int{1, 3} { +// size := 1 << power +// totalSize := size * batchSize +// scalars := icicleBn254.GenerateScalars(totalSize) +// points := icicleBn254.GenerateAffinePoints(totalSize) + +// var precomputeOut core.DeviceSlice +// _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) +// assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + +// e = msm.PrecomputeBases(points, &cfg, precomputeOut) +// assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + +// var p icicleBn254.Projective +// var out core.DeviceSlice +// _, e = out.Malloc(batchSize*p.Size(), p.Size()) +// assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + +// e = msm.Msm(scalars, precomputeOut, &cfg, out) +// assert.Equal(t, runtime.Success, e, "Msm failed") +// outHost := make(core.HostSlice[icicleBn254.Projective], batchSize) +// outHost.CopyFromDevice(&out) +// out.Free() +// precomputeOut.Free() +// // Check with gnark-crypto +// for i := 0; i < batchSize; i++ { +// scalarsSlice := scalars[i*size : (i+1)*size] +// pointsSlice := points[i*size : (i+1)*size] +// out := outHost[i] +// assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) +// } +// } +// } +// } func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() @@ -280,52 +277,52 @@ func TestMSMSkewedDistribution(t *testing.T) { var p icicleBn254.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBn254.Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } } -func TestMSMMultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") - wg := sync.WaitGroup{} - - for i := 0; i < numDevices; i++ { - wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { - defer wg.Done() - cfg := msm.GetDefaultMSMConfig() - cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { - size := 1 << power - scalars := icicleBn254.GenerateScalars(size) - points := icicleBn254.GenerateAffinePoints(size) - - stream, _ := cr.CreateStream() - var p icicleBn254.Projective - var out core.DeviceSlice - _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream - - e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") - outHost := make(core.HostSlice[icicleBn254.Projective], 1) - outHost.CopyFromDeviceAsync(&out, stream) - out.FreeAsync(stream) - - cr.SynchronizeStream(&stream) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - } - }) - } - wg.Wait() -} +// func TestMSMMultiDevice(t *testing.T) { +// numDevices, _ := runtime.GetDeviceCount() +// fmt.Println("There are ", numDevices, " devices available") +// wg := sync.WaitGroup{} + +// for i := 0; i < numDevices; i++ { +// wg.Add(1) +// runtime.RunOnDevice(i, func(args ...any) { +// defer wg.Done() +// cfg := msm.GetDefaultMSMConfig() +// cfg.IsAsync = true +// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { +// size := 1 << power +// scalars := icicleBn254.GenerateScalars(size) +// points := icicleBn254.GenerateAffinePoints(size) + +// stream, _ := runtime.CreateStream() +// var p icicleBn254.Projective +// var out core.DeviceSlice +// _, e := out.MallocAsync(p.Size(), p.Size(), stream) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// cfg.Ctx.Stream = &stream + +// e = msm.Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm failed") +// outHost := make(core.HostSlice[icicleBn254.Projective], 1) +// outHost.CopyFromDeviceAsync(&out, stream) +// out.FreeAsync(stream) + +// runtime.SynchronizeStream(&stream) +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) +// } +// }) +// } +// wg.Wait() +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go index 6e36380df..579871ab6 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go @@ -6,15 +6,15 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" ) -func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bn254.ScalarField], output core.HostSlice[bn254.ScalarField], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNtt(t *testing.T, size int, scalars core.HostSlice[bn254.ScalarField], output core.HostSlice[bn254.ScalarField], order core.Ordering, direction core.NTTDir) { scalarsFr := make([]fr.Element, size) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -26,10 +26,10 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bn254.ScalarFiel outputAsFr[i] = slice64 } - return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) + testAgainstGnarkCryptoNttGnarkTypes(t, size, scalarsFr, outputAsFr, order, direction) } -func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNttGnarkTypes(t *testing.T, size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) { domainWithPrecompute := fft.NewDomain(uint64(size)) // DIT + BitReverse == Ordering.kRR // DIT == Ordering.kRN @@ -51,7 +51,10 @@ func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.E if order == core.KNN || order == core.KRR { fft.BitReverse(scalarsFr) } - return reflect.DeepEqual(scalarsFr, outputAsFr) + // println(scalarsFr[0].String()) + // println(outputAsFr[0].String()) + assert.Equal(t, scalarsFr, outputAsFr) + // return reflect.DeepEqual(scalarsFr, outputAsFr) } func TestNTTGetDefaultConfig(t *testing.T) { actual := ntt.GetDefaultNttConfig() @@ -65,16 +68,22 @@ func TestNTTGetDefaultConfig(t *testing.T) { func TestInitDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) } func TestNtt(t *testing.T) { + runtime.LoadBackendFromEnv() + device := runtime.CreateDevice("CUDA", 0) + cfg := ntt.GetDefaultNttConfig() scalars := bn254.GenerateScalars(1 << largestTestSize) - for _, size := range []int{4, largestTestSize} { + for _, size := range []int{4, 8} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + + runtime.SetDevice(&device) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bn254.ScalarField](scalars[:testSize]) @@ -82,10 +91,11 @@ func TestNtt(t *testing.T) { // run ntt output := make(core.HostSlice[bn254.ScalarField], testSize) - ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + err := ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + assert.Equal(t, runtime.Success, err) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -110,7 +120,7 @@ func TestNttFrElement(t *testing.T) { ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNttGnarkTypes(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -125,11 +135,11 @@ func TestNttDeviceAsync(t *testing.T) { testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bn254.ScalarField](scalars[:testSize]) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() cfg.Ordering = v cfg.IsAsync = true - cfg.Ctx.Stream = &stream + cfg.StreamHandle = stream var deviceInput core.DeviceSlice scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) @@ -141,9 +151,9 @@ func TestNttDeviceAsync(t *testing.T) { output := make(core.HostSlice[bn254.ScalarField], testSize) output.CopyFromDeviceAsync(&deviceOutput, stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, direction) } } } @@ -195,9 +205,8 @@ func TestNttBatch(t *testing.T) { func TestReleaseDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() - e := ntt.ReleaseDomain(cfg.Ctx) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") + e := ntt.ReleaseDomain() + assert.Equal(t, runtime.Success, e, "ReleasDomain failed") } // func TestNttArbitraryCoset(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bn254/tests/polynomial_test.go b/wrappers/golang_v3/curves/bn254/tests/polynomial_test.go index 8eb5efed9..cf2a88473 100644 --- a/wrappers/golang_v3/curves/bn254/tests/polynomial_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/polynomial_test.go @@ -3,11 +3,11 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/polynomial" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/vecOps" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go b/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go index 0564841f0..442757c77 100644 --- a/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go @@ -1,42 +1,42 @@ package tests -import ( - "testing" +// import ( +// "testing" - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/poseidon" -) +// core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" +// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +// bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" +// poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/poseidon" +// ) -func TestPoseidon(t *testing.T) { +// func TestPoseidon(t *testing.T) { - arity := 2 - numberOfStates := 1 +// arity := 2 +// numberOfStates := 1 - cfg := poseidon.GetDefaultPoseidonConfig() - cfg.IsAsync = true - stream, _ := cr.CreateStream() - cfg.Ctx.Stream = &stream +// cfg := poseidon.GetDefaultPoseidonConfig() +// cfg.IsAsync = true +// stream, _ := cr.CreateStream() +// cfg.Ctx.Stream = &stream - var constants core.PoseidonConstants[bn254.ScalarField] +// var constants core.PoseidonConstants[bn254.ScalarField] - poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants +// poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants - scalars := bn254.GenerateScalars(numberOfStates * arity) - scalars[0] = scalars[0].Zero() - scalars[1] = scalars[0].Zero() +// scalars := bn254.GenerateScalars(numberOfStates * arity) +// scalars[0] = scalars[0].Zero() +// scalars[1] = scalars[0].Zero() - scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) +// scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) - var deviceInput core.DeviceSlice - scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) - var deviceOutput core.DeviceSlice - deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) +// var deviceInput core.DeviceSlice +// scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) +// var deviceOutput core.DeviceSlice +// deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) - poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function +// poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function - output := make(core.HostSlice[bn254.ScalarField], numberOfStates) - output.CopyFromDeviceAsync(&deviceOutput, stream) +// output := make(core.HostSlice[bn254.ScalarField], numberOfStates) +// output.CopyFromDeviceAsync(&deviceOutput, stream) -} +// } diff --git a/wrappers/golang_v3/curves/bn254/tests/scalar_field_test.go b/wrappers/golang_v3/curves/bn254/tests/scalar_field_test.go index ed119cda9..5bda6159a 100644 --- a/wrappers/golang_v3/curves/bn254/tests/scalar_field_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/scalar_field_test.go @@ -1,9 +1,9 @@ package tests import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) @@ -100,7 +100,7 @@ func TestBn254GenerateScalars(t *testing.T) { } func TestBn254MongtomeryConversion(t *testing.T) { - size := 1 << 15 + size := 1 << 20 scalars := bn254.GenerateScalars(size) var deviceScalars core.DeviceSlice @@ -108,7 +108,7 @@ func TestBn254MongtomeryConversion(t *testing.T) { bn254.ToMontgomery(&deviceScalars) - scalarsMontHost := bn254.GenerateScalars(size) + scalarsMontHost := make(core.HostSlice[bn254.ScalarField], size) scalarsMontHost.CopyFromDevice(&deviceScalars) assert.NotEqual(t, scalars, scalarsMontHost) diff --git a/wrappers/golang_v3/curves/bn254/tests/vec_ops_test.go b/wrappers/golang_v3/curves/bn254/tests/vec_ops_test.go index 20ed5e4c4..7e67fafba 100644 --- a/wrappers/golang_v3/curves/bn254/tests/vec_ops_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/vec_ops_test.go @@ -3,10 +3,9 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/vecOps" "github.com/stretchr/testify/assert" ) @@ -38,30 +37,27 @@ func TestBn254VecOps(t *testing.T) { func TestBn254Transpose(t *testing.T) { rowSize := 1 << 6 columnSize := 1 << 8 - onDevice := false - isAsync := false matrix := bn254.GenerateScalars(rowSize * columnSize) out := make(core.HostSlice[bn254.ScalarField], rowSize*columnSize) out2 := make(core.HostSlice[bn254.ScalarField], rowSize*columnSize) - ctx, _ := cr.GetDefaultDeviceContext() + cfg := core.DefaultVecOpsConfig() - vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) assert.Equal(t, matrix, out2) var dMatrix, dOut, dOut2 core.DeviceSlice - onDevice = true matrix.CopyToDevice(&dMatrix, true) dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) - vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, cfg) output := make(core.HostSlice[bn254.ScalarField], rowSize*columnSize) output.CopyFromDevice(&dOut2) diff --git a/wrappers/golang_v3/curves/bn254/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/bn254/vecOps/include/vec_ops.h index 5735fce5b..a22c3fe53 100644 --- a/wrappers/golang_v3/curves/bn254/vecOps/include/vec_ops.h +++ b/wrappers/golang_v3/curves/bn254/vecOps/include/vec_ops.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BN254_VEC_OPS_H @@ -12,7 +11,7 @@ typedef struct scalar_t scalar_t; typedef struct VecOpsConfig VecOpsConfig; typedef struct DeviceContext DeviceContext; -cudaError_t bn254_mul_cuda( +int bn254_vector_mul( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -20,7 +19,7 @@ cudaError_t bn254_mul_cuda( scalar_t* result ); -cudaError_t bn254_add_cuda( +int bn254_vector_add( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -28,7 +27,7 @@ cudaError_t bn254_add_cuda( scalar_t* result ); -cudaError_t bn254_sub_cuda( +int bn254_vector_sub( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -36,14 +35,12 @@ cudaError_t bn254_sub_cuda( scalar_t* result ); -cudaError_t bn254_transpose_matrix_cuda( +int bn254_matrix_transpose( scalar_t* mat_in, int row_size, int column_size, - scalar_t* mat_out, - DeviceContext* ctx, - bool on_device, - bool is_async + VecOpsConfig* config, + scalar_t* mat_out ); #ifdef __cplusplus diff --git a/wrappers/golang_v3/curves/bn254/vecOps/vec_ops.go b/wrappers/golang_v3/curves/bn254/vecOps/vec_ops.go index 428f54968..eda97f939 100644 --- a/wrappers/golang_v3/curves/bn254/vecOps/vec_ops.go +++ b/wrappers/golang_v3/curves/bn254/vecOps/vec_ops.go @@ -5,13 +5,11 @@ package vecOps import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - - "unsafe" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) cA := (*C.scalar_t)(aPointer) @@ -22,27 +20,25 @@ func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.V switch op { case core.Sub: - ret = (cr.CudaError)(C.bn254_sub_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bn254_vector_sub(cA, cB, cSize, cConfig, cOut)) case core.Add: - ret = (cr.CudaError)(C.bn254_add_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bn254_vector_add(cA, cB, cSize, cConfig, cOut)) case core.Mul: - ret = (cr.CudaError)(C.bn254_mul_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bn254_vector_mul(cA, cB, cSize, cConfig, cOut)) } return ret } -func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { - core.TransposeCheck(in, out, onDevice) +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, config core.VecOpsConfig) runtime.EIcicleError { + inPointer, _, outPointer, cfgPointer, _ := core.VecOpCheck(in, in, out, &config) - cIn := (*C.scalar_t)(in.AsUnsafePointer()) - cOut := (*C.scalar_t)(out.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cIn := (*C.scalar_t)(inPointer) cRowSize := (C.int)(rowSize) cColumnSize := (C.int)(columnSize) - cOnDevice := (C._Bool)(onDevice) - cIsAsync := (C._Bool)(isAsync) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cOut := (*C.scalar_t)(outPointer) - err := (cr.CudaError)(C.bn254_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) - return core.FromCudaError(err) + err := (C.bn254_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) + return runtime.EIcicleError(err) } diff --git a/wrappers/golang_v3/curves/bw6761/g2/include/scalar_field.h b/wrappers/golang_v3/curves/bw6761/g2/include/scalar_field.h index 4a4800789..29ff19f4e 100644 --- a/wrappers/golang_v3/curves/bw6761/g2/include/scalar_field.h +++ b/wrappers/golang_v3/curves/bw6761/g2/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BW6_761_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void bw6_761_generate_scalars(scalar_t* scalars, int size); -cudaError_t bw6_761_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int bw6_761_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bw6761/include/scalar_field.h b/wrappers/golang_v3/curves/bw6761/include/scalar_field.h index 4a4800789..29ff19f4e 100644 --- a/wrappers/golang_v3/curves/bw6761/include/scalar_field.h +++ b/wrappers/golang_v3/curves/bw6761/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BW6_761_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void bw6_761_generate_scalars(scalar_t* scalars, int size); -cudaError_t bw6_761_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int bw6_761_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bw6761/ntt/include/ntt.h b/wrappers/golang_v3/curves/bw6761/ntt/include/ntt.h index aea1223e4..62f593f86 100644 --- a/wrappers/golang_v3/curves/bw6761/ntt/include/ntt.h +++ b/wrappers/golang_v3/curves/bw6761/ntt/include/ntt.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BW6_761_NTT_H @@ -10,11 +9,12 @@ extern "C" { typedef struct scalar_t scalar_t; typedef struct NTTConfig NTTConfig; -typedef struct DeviceContext DeviceContext; +typedef struct NTTInitDomainConfig NTTInitDomainConfig; -cudaError_t bw6_761_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); -cudaError_t bw6_761_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); -cudaError_t bw6_761_release_domain(DeviceContext* ctx); +int bw6_761_ntt(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +int bw6_761_ntt_init_domain(scalar_t* primitive_root, NTTInitDomainConfig* ctx); +int bw6_761_ntt_release_domain(); +int* bw6_761_get_root_of_unity(size_t size); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bw6761/ntt/ntt.go b/wrappers/golang_v3/curves/bw6761/ntt/ntt.go index 297049e19..1f46b519f 100644 --- a/wrappers/golang_v3/curves/bw6761/ntt/ntt.go +++ b/wrappers/golang_v3/curves/bw6761/ntt/ntt.go @@ -4,17 +4,15 @@ package ntt // #include "ntt.h" import "C" -import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" -) - import ( "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) @@ -23,9 +21,9 @@ func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTCo cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.scalar_t)(resultsPointer) - __ret := C.bw6_761_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.bw6_761_ntt(cScalars, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } func GetDefaultNttConfig() core.NTTConfig[[bw6_761.SCALAR_LIMBS]uint32] { @@ -39,18 +37,23 @@ func GetDefaultNttConfig() core.NTTConfig[[bw6_761.SCALAR_LIMBS]uint32] { return core.GetDefaultNTTConfig(cosetGen) } -func InitDomain(primitiveRoot bw6_761.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { +func GetRootOfUnity(size uint64) bw6_761.ScalarField { + cRes := C.bw6_761_get_root_of_unity((C.size_t)(size)) + var res bw6_761.ScalarField + res.FromLimbs(*(*[]uint32)(unsafe.Pointer(cRes))) + return res +} + +func InitDomain(primitiveRoot bw6_761.ScalarField, cfg core.NTTInitDomainConfig) runtime.EIcicleError { cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cFastTwiddles := (C._Bool)(fastTwiddles) - __ret := C.bw6_761_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + cCfg := (*C.NTTInitDomainConfig)(unsafe.Pointer(&cfg)) + __ret := C.bw6_761_ntt_init_domain(cPrimitiveRoot, cCfg) + err := runtime.EIcicleError(__ret) + return err } -func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - __ret := C.bw6_761_release_domain(cCtx) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) +func ReleaseDomain() runtime.EIcicleError { + __ret := C.bw6_761_ntt_release_domain() + err := runtime.EIcicleError(__ret) + return err } diff --git a/wrappers/golang_v3/curves/bw6761/polynomial/include/polynomial.h b/wrappers/golang_v3/curves/bw6761/polynomial/include/polynomial.h index 2568e51fc..e62424faf 100644 --- a/wrappers/golang_v3/curves/bw6761/polynomial/include/polynomial.h +++ b/wrappers/golang_v3/curves/bw6761/polynomial/include/polynomial.h @@ -12,7 +12,6 @@ typedef struct scalar_t scalar_t; typedef struct PolynomialInst PolynomialInst; typedef struct IntegrityPointer IntegrityPointer; -bool bw6_761_polynomial_init_cuda_backend(); PolynomialInst* bw6_761_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); PolynomialInst* bw6_761_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); PolynomialInst* bw6_761_polynomial_clone(const PolynomialInst* p); diff --git a/wrappers/golang_v3/curves/bw6761/polynomial/polynomial.go b/wrappers/golang_v3/curves/bw6761/polynomial/polynomial.go index 49626f731..f29f5a341 100644 --- a/wrappers/golang_v3/curves/bw6761/polynomial/polynomial.go +++ b/wrappers/golang_v3/curves/bw6761/polynomial/polynomial.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" ) type PolynomialHandle = C.struct_PolynomialInst @@ -17,10 +17,6 @@ type DensePolynomial struct { handle *PolynomialHandle } -func InitPolyBackend() bool { - return (bool)(C.bw6_761_polynomial_init_cuda_backend()) -} - func (up *DensePolynomial) Print() { C.bw6_761_polynomial_print(up.handle) } diff --git a/wrappers/golang_v3/curves/bw6761/scalar_field.go b/wrappers/golang_v3/curves/bw6761/scalar_field.go index d02566f31..811fe0a26 100644 --- a/wrappers/golang_v3/curves/bw6761/scalar_field.go +++ b/wrappers/golang_v3/curves/bw6761/scalar_field.go @@ -6,8 +6,8 @@ import "C" import ( "encoding/binary" "fmt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "unsafe" ) @@ -99,23 +99,20 @@ func GenerateScalars(size int) core.HostSlice[ScalarField] { return scalarSlice } -func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) - cSize := (C.size_t)(scalars.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bw6_761_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*scalars, *scalars, *scalars, &defaultCfg) + cErr := C.bw6_761_scalar_convert_montgomery((*C.scalar_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.scalar_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func ToMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, true) } -func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func FromMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, false) } diff --git a/wrappers/golang_v3/curves/bw6761/tests/base_field_test.go b/wrappers/golang_v3/curves/bw6761/tests/base_field_test.go index 1c340ce3e..81d4be94b 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/base_field_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/base_field_test.go @@ -1,8 +1,8 @@ package tests import ( - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_g2base_field_test.go index 6f4429ff5..3d79fce3d 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_g2base_field_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_g2base_field_test.go @@ -1,8 +1,8 @@ package tests import ( - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/g2" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/curves/bw6761/tests/main_test.go b/wrappers/golang_v3/curves/bw6761/tests/main_test.go index 48d0499fc..afc5f0cb0 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/main_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/main_test.go @@ -4,10 +4,10 @@ import ( "os" "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt" - poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/fft" ) @@ -16,24 +16,26 @@ const ( largestTestSize = 20 ) -func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { +func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() rouIcicle := bw6_761.ScalarField{} limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) rouIcicle.FromLimbs(limbs) - e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + e := ntt.InitDomain(rouIcicle, cfg) return e } func TestMain(m *testing.M) { - poly.InitPolyBackend() + runtime.LoadBackendFromEnv() + device := runtime.CreateDevice("CUDA", 0) + runtime.SetDevice(&device) // setup domain - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() e := initDomain(largestTestSize, cfg) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + if e != runtime.Success { panic("initDomain failed") } @@ -41,8 +43,8 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) // release domain - e = ntt.ReleaseDomain(cfg.Ctx) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + e = ntt.ReleaseDomain() + if e != runtime.Success { panic("ReleaseDomain failed") } } diff --git a/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go b/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go index 3552a2a8b..d0e86317f 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go @@ -6,11 +6,11 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/fft" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" ) @@ -65,7 +65,7 @@ func TestNTTGetDefaultConfig(t *testing.T) { func TestInitDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) } @@ -125,11 +125,11 @@ func TestNttDeviceAsync(t *testing.T) { testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bw6_761.ScalarField](scalars[:testSize]) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() cfg.Ordering = v cfg.IsAsync = true - cfg.Ctx.Stream = &stream + cfg.StreamHandle = stream var deviceInput core.DeviceSlice scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) @@ -141,7 +141,7 @@ func TestNttDeviceAsync(t *testing.T) { output := make(core.HostSlice[bw6_761.ScalarField], testSize) output.CopyFromDeviceAsync(&deviceOutput, stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Compare with gnark-crypto assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) } @@ -195,9 +195,8 @@ func TestNttBatch(t *testing.T) { func TestReleaseDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() - e := ntt.ReleaseDomain(cfg.Ctx) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") + e := ntt.ReleaseDomain() + assert.Equal(t, runtime.Success, e, "ReleasDomain failed") } // func TestNttArbitraryCoset(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bw6761/tests/polynomial_test.go b/wrappers/golang_v3/curves/bw6761/tests/polynomial_test.go index 5bb3f1712..c017ddf56 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/polynomial_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/polynomial_test.go @@ -3,11 +3,11 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/polynomial" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/vecOps" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/curves/bw6761/tests/scalar_field_test.go b/wrappers/golang_v3/curves/bw6761/tests/scalar_field_test.go index 0a8a835e7..5e375ff94 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/scalar_field_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/scalar_field_test.go @@ -1,9 +1,9 @@ package tests import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) @@ -100,7 +100,7 @@ func TestBw6_761GenerateScalars(t *testing.T) { } func TestBw6_761MongtomeryConversion(t *testing.T) { - size := 1 << 15 + size := 1 << 20 scalars := bw6_761.GenerateScalars(size) var deviceScalars core.DeviceSlice @@ -108,7 +108,7 @@ func TestBw6_761MongtomeryConversion(t *testing.T) { bw6_761.ToMontgomery(&deviceScalars) - scalarsMontHost := bw6_761.GenerateScalars(size) + scalarsMontHost := make(core.HostSlice[bw6_761.ScalarField], size) scalarsMontHost.CopyFromDevice(&deviceScalars) assert.NotEqual(t, scalars, scalarsMontHost) diff --git a/wrappers/golang_v3/curves/bw6761/tests/vec_ops_test.go b/wrappers/golang_v3/curves/bw6761/tests/vec_ops_test.go index bd6802809..6f62dcd76 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/vec_ops_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/vec_ops_test.go @@ -3,10 +3,9 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/vecOps" "github.com/stretchr/testify/assert" ) @@ -38,30 +37,27 @@ func TestBw6_761VecOps(t *testing.T) { func TestBw6_761Transpose(t *testing.T) { rowSize := 1 << 6 columnSize := 1 << 8 - onDevice := false - isAsync := false matrix := bw6_761.GenerateScalars(rowSize * columnSize) out := make(core.HostSlice[bw6_761.ScalarField], rowSize*columnSize) out2 := make(core.HostSlice[bw6_761.ScalarField], rowSize*columnSize) - ctx, _ := cr.GetDefaultDeviceContext() + cfg := core.DefaultVecOpsConfig() - vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) assert.Equal(t, matrix, out2) var dMatrix, dOut, dOut2 core.DeviceSlice - onDevice = true matrix.CopyToDevice(&dMatrix, true) dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) - vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, cfg) output := make(core.HostSlice[bw6_761.ScalarField], rowSize*columnSize) output.CopyFromDevice(&dOut2) diff --git a/wrappers/golang_v3/curves/bw6761/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/bw6761/vecOps/include/vec_ops.h index 86bda7e30..a7a2bab74 100644 --- a/wrappers/golang_v3/curves/bw6761/vecOps/include/vec_ops.h +++ b/wrappers/golang_v3/curves/bw6761/vecOps/include/vec_ops.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BW6_761_VEC_OPS_H @@ -12,7 +11,7 @@ typedef struct scalar_t scalar_t; typedef struct VecOpsConfig VecOpsConfig; typedef struct DeviceContext DeviceContext; -cudaError_t bw6_761_mul_cuda( +int bw6_761_vector_mul( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -20,7 +19,7 @@ cudaError_t bw6_761_mul_cuda( scalar_t* result ); -cudaError_t bw6_761_add_cuda( +int bw6_761_vector_add( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -28,7 +27,7 @@ cudaError_t bw6_761_add_cuda( scalar_t* result ); -cudaError_t bw6_761_sub_cuda( +int bw6_761_vector_sub( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -36,14 +35,12 @@ cudaError_t bw6_761_sub_cuda( scalar_t* result ); -cudaError_t bw6_761_transpose_matrix_cuda( +int bw6_761_matrix_transpose( scalar_t* mat_in, int row_size, int column_size, - scalar_t* mat_out, - DeviceContext* ctx, - bool on_device, - bool is_async + VecOpsConfig* config, + scalar_t* mat_out ); #ifdef __cplusplus diff --git a/wrappers/golang_v3/curves/bw6761/vecOps/vec_ops.go b/wrappers/golang_v3/curves/bw6761/vecOps/vec_ops.go index ad40566d8..60b5cdc61 100644 --- a/wrappers/golang_v3/curves/bw6761/vecOps/vec_ops.go +++ b/wrappers/golang_v3/curves/bw6761/vecOps/vec_ops.go @@ -5,13 +5,11 @@ package vecOps import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - - "unsafe" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) cA := (*C.scalar_t)(aPointer) @@ -22,27 +20,25 @@ func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.V switch op { case core.Sub: - ret = (cr.CudaError)(C.bw6_761_sub_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bw6_761_vector_sub(cA, cB, cSize, cConfig, cOut)) case core.Add: - ret = (cr.CudaError)(C.bw6_761_add_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bw6_761_vector_add(cA, cB, cSize, cConfig, cOut)) case core.Mul: - ret = (cr.CudaError)(C.bw6_761_mul_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.bw6_761_vector_mul(cA, cB, cSize, cConfig, cOut)) } return ret } -func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { - core.TransposeCheck(in, out, onDevice) +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, config core.VecOpsConfig) runtime.EIcicleError { + inPointer, _, outPointer, cfgPointer, _ := core.VecOpCheck(in, in, out, &config) - cIn := (*C.scalar_t)(in.AsUnsafePointer()) - cOut := (*C.scalar_t)(out.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cIn := (*C.scalar_t)(inPointer) cRowSize := (C.int)(rowSize) cColumnSize := (C.int)(columnSize) - cOnDevice := (C._Bool)(onDevice) - cIsAsync := (C._Bool)(isAsync) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cOut := (*C.scalar_t)(outPointer) - err := (cr.CudaError)(C.bw6_761_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) - return core.FromCudaError(err) + err := (C.bw6_761_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) + return runtime.EIcicleError(err) } diff --git a/wrappers/golang_v3/curves/grumpkin/include/scalar_field.h b/wrappers/golang_v3/curves/grumpkin/include/scalar_field.h index 90517bfd9..f9708c3db 100644 --- a/wrappers/golang_v3/curves/grumpkin/include/scalar_field.h +++ b/wrappers/golang_v3/curves/grumpkin/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _GRUMPKIN_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void grumpkin_generate_scalars(scalar_t* scalars, int size); -cudaError_t grumpkin_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int grumpkin_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/grumpkin/scalar_field.go b/wrappers/golang_v3/curves/grumpkin/scalar_field.go index cc46f3b9c..b097d093e 100644 --- a/wrappers/golang_v3/curves/grumpkin/scalar_field.go +++ b/wrappers/golang_v3/curves/grumpkin/scalar_field.go @@ -6,8 +6,8 @@ import "C" import ( "encoding/binary" "fmt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "unsafe" ) @@ -99,23 +99,20 @@ func GenerateScalars(size int) core.HostSlice[ScalarField] { return scalarSlice } -func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) - cSize := (C.size_t)(scalars.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.grumpkin_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*scalars, *scalars, *scalars, &defaultCfg) + cErr := C.grumpkin_scalar_convert_montgomery((*C.scalar_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.scalar_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func ToMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, true) } -func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func FromMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, false) } diff --git a/wrappers/golang_v3/curves/grumpkin/tests/base_field_test.go b/wrappers/golang_v3/curves/grumpkin/tests/base_field_test.go index d1f93f654..282240b72 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/base_field_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/base_field_test.go @@ -1,8 +1,8 @@ package tests import ( - grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/curves/grumpkin/tests/main_test.go b/wrappers/golang_v3/curves/grumpkin/tests/main_test.go index 071357d76..309de0833 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/main_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/main_test.go @@ -3,6 +3,8 @@ package tests import ( "os" "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) const ( @@ -10,6 +12,9 @@ const ( ) func TestMain(m *testing.M) { + runtime.LoadBackendFromEnv() + device := runtime.CreateDevice("CUDA", 0) + runtime.SetDevice(&device) // execute tests os.Exit(m.Run()) diff --git a/wrappers/golang_v3/curves/grumpkin/tests/scalar_field_test.go b/wrappers/golang_v3/curves/grumpkin/tests/scalar_field_test.go index 43e328307..152441f05 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/scalar_field_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/scalar_field_test.go @@ -1,9 +1,9 @@ package tests import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) @@ -100,7 +100,7 @@ func TestGrumpkinGenerateScalars(t *testing.T) { } func TestGrumpkinMongtomeryConversion(t *testing.T) { - size := 1 << 15 + size := 1 << 20 scalars := grumpkin.GenerateScalars(size) var deviceScalars core.DeviceSlice @@ -108,7 +108,7 @@ func TestGrumpkinMongtomeryConversion(t *testing.T) { grumpkin.ToMontgomery(&deviceScalars) - scalarsMontHost := grumpkin.GenerateScalars(size) + scalarsMontHost := make(core.HostSlice[grumpkin.ScalarField], size) scalarsMontHost.CopyFromDevice(&deviceScalars) assert.NotEqual(t, scalars, scalarsMontHost) diff --git a/wrappers/golang_v3/curves/grumpkin/tests/vec_ops_test.go b/wrappers/golang_v3/curves/grumpkin/tests/vec_ops_test.go index 9413b0597..50e06dda0 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/vec_ops_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/vec_ops_test.go @@ -3,10 +3,9 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin/vecOps" "github.com/stretchr/testify/assert" ) @@ -38,30 +37,27 @@ func TestGrumpkinVecOps(t *testing.T) { func TestGrumpkinTranspose(t *testing.T) { rowSize := 1 << 6 columnSize := 1 << 8 - onDevice := false - isAsync := false matrix := grumpkin.GenerateScalars(rowSize * columnSize) out := make(core.HostSlice[grumpkin.ScalarField], rowSize*columnSize) out2 := make(core.HostSlice[grumpkin.ScalarField], rowSize*columnSize) - ctx, _ := cr.GetDefaultDeviceContext() + cfg := core.DefaultVecOpsConfig() - vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) assert.Equal(t, matrix, out2) var dMatrix, dOut, dOut2 core.DeviceSlice - onDevice = true matrix.CopyToDevice(&dMatrix, true) dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) - vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, cfg) output := make(core.HostSlice[grumpkin.ScalarField], rowSize*columnSize) output.CopyFromDevice(&dOut2) diff --git a/wrappers/golang_v3/curves/grumpkin/vecOps/include/vec_ops.h b/wrappers/golang_v3/curves/grumpkin/vecOps/include/vec_ops.h index c348dafac..64a6e33a5 100644 --- a/wrappers/golang_v3/curves/grumpkin/vecOps/include/vec_ops.h +++ b/wrappers/golang_v3/curves/grumpkin/vecOps/include/vec_ops.h @@ -1,4 +1,3 @@ -#include #include #ifndef _GRUMPKIN_VEC_OPS_H @@ -12,7 +11,7 @@ typedef struct scalar_t scalar_t; typedef struct VecOpsConfig VecOpsConfig; typedef struct DeviceContext DeviceContext; -cudaError_t grumpkin_mul_cuda( +int grumpkin_vector_mul( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -20,7 +19,7 @@ cudaError_t grumpkin_mul_cuda( scalar_t* result ); -cudaError_t grumpkin_add_cuda( +int grumpkin_vector_add( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -28,7 +27,7 @@ cudaError_t grumpkin_add_cuda( scalar_t* result ); -cudaError_t grumpkin_sub_cuda( +int grumpkin_vector_sub( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -36,14 +35,12 @@ cudaError_t grumpkin_sub_cuda( scalar_t* result ); -cudaError_t grumpkin_transpose_matrix_cuda( +int grumpkin_matrix_transpose( scalar_t* mat_in, int row_size, int column_size, - scalar_t* mat_out, - DeviceContext* ctx, - bool on_device, - bool is_async + VecOpsConfig* config, + scalar_t* mat_out ); #ifdef __cplusplus diff --git a/wrappers/golang_v3/curves/grumpkin/vecOps/vec_ops.go b/wrappers/golang_v3/curves/grumpkin/vecOps/vec_ops.go index 316fe5c0d..f49039f3c 100644 --- a/wrappers/golang_v3/curves/grumpkin/vecOps/vec_ops.go +++ b/wrappers/golang_v3/curves/grumpkin/vecOps/vec_ops.go @@ -5,13 +5,11 @@ package vecOps import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - - "unsafe" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) cA := (*C.scalar_t)(aPointer) @@ -22,27 +20,25 @@ func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.V switch op { case core.Sub: - ret = (cr.CudaError)(C.grumpkin_sub_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.grumpkin_vector_sub(cA, cB, cSize, cConfig, cOut)) case core.Add: - ret = (cr.CudaError)(C.grumpkin_add_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.grumpkin_vector_add(cA, cB, cSize, cConfig, cOut)) case core.Mul: - ret = (cr.CudaError)(C.grumpkin_mul_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.grumpkin_vector_mul(cA, cB, cSize, cConfig, cOut)) } return ret } -func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) { - core.TransposeCheck(in, out, onDevice) +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, config core.VecOpsConfig) runtime.EIcicleError { + inPointer, _, outPointer, cfgPointer, _ := core.VecOpCheck(in, in, out, &config) - cIn := (*C.scalar_t)(in.AsUnsafePointer()) - cOut := (*C.scalar_t)(out.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cIn := (*C.scalar_t)(inPointer) cRowSize := (C.int)(rowSize) cColumnSize := (C.int)(columnSize) - cOnDevice := (C._Bool)(onDevice) - cIsAsync := (C._Bool)(isAsync) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cOut := (*C.scalar_t)(outPointer) - err := (cr.CudaError)(C.grumpkin_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) - return core.FromCudaError(err) + err := (C.grumpkin_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) + return runtime.EIcicleError(err) } diff --git a/wrappers/golang_v3/fields/babybear/extension/extension_field.go b/wrappers/golang_v3/fields/babybear/extension/extension_field.go index ce8768ea6..bea36165f 100644 --- a/wrappers/golang_v3/fields/babybear/extension/extension_field.go +++ b/wrappers/golang_v3/fields/babybear/extension/extension_field.go @@ -6,10 +6,9 @@ import "C" import ( "encoding/binary" "fmt" - "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "unsafe" ) const ( diff --git a/wrappers/golang_v3/fields/babybear/extension/include/scalar_field.h b/wrappers/golang_v3/fields/babybear/extension/include/scalar_field.h index 958b2c6c5..447ac2f1f 100644 --- a/wrappers/golang_v3/fields/babybear/extension/include/scalar_field.h +++ b/wrappers/golang_v3/fields/babybear/extension/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BABYBEAR_EXTENSION_FIELD_H @@ -9,7 +8,6 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; typedef struct VecOpsConfig VecOpsConfig; void babybear_extension_generate_scalars(scalar_t* scalars, int size); diff --git a/wrappers/golang_v3/fields/babybear/extension/ntt/include/ntt.h b/wrappers/golang_v3/fields/babybear/extension/ntt/include/ntt.h index d484687e9..5a9af7b34 100644 --- a/wrappers/golang_v3/fields/babybear/extension/ntt/include/ntt.h +++ b/wrappers/golang_v3/fields/babybear/extension/ntt/include/ntt.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BABYBEAR_EXTENSION_NTT_H diff --git a/wrappers/golang_v3/fields/babybear/extension/vecOps/include/vec_ops.h b/wrappers/golang_v3/fields/babybear/extension/vecOps/include/vec_ops.h index a7860086d..b9029ea7e 100644 --- a/wrappers/golang_v3/fields/babybear/extension/vecOps/include/vec_ops.h +++ b/wrappers/golang_v3/fields/babybear/extension/vecOps/include/vec_ops.h @@ -1,8 +1,7 @@ -#include #include -#ifndef _babybear_extension_VEC_OPS_H -#define _babybear_extension_VEC_OPS_H +#ifndef _BABYBEAR_EXTENSION_VEC_OPS_H +#define _BABYBEAR_EXTENSION_VEC_OPS_H #ifdef __cplusplus extern "C" { diff --git a/wrappers/golang_v3/fields/babybear/include/scalar_field.h b/wrappers/golang_v3/fields/babybear/include/scalar_field.h index c22cd571f..36d1aff10 100644 --- a/wrappers/golang_v3/fields/babybear/include/scalar_field.h +++ b/wrappers/golang_v3/fields/babybear/include/scalar_field.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BABYBEAR_FIELD_H diff --git a/wrappers/golang_v3/fields/babybear/ntt/include/ntt.h b/wrappers/golang_v3/fields/babybear/ntt/include/ntt.h index 4dad1dab3..8df57bf5b 100644 --- a/wrappers/golang_v3/fields/babybear/ntt/include/ntt.h +++ b/wrappers/golang_v3/fields/babybear/ntt/include/ntt.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BABYBEAR_NTT_H diff --git a/wrappers/golang_v3/fields/babybear/scalar_field.go b/wrappers/golang_v3/fields/babybear/scalar_field.go index 4395f97fc..3b8261944 100644 --- a/wrappers/golang_v3/fields/babybear/scalar_field.go +++ b/wrappers/golang_v3/fields/babybear/scalar_field.go @@ -6,10 +6,9 @@ import "C" import ( "encoding/binary" "fmt" - "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "unsafe" ) const ( diff --git a/wrappers/golang_v3/fields/babybear/tests/extension_field_test.go b/wrappers/golang_v3/fields/babybear/tests/extension_field_test.go new file mode 100644 index 000000000..0a669b38e --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/tests/extension_field_test.go @@ -0,0 +1,120 @@ +package tests + +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear_extension "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/extension" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + EXTENSION_LIMBS = babybear_extension.EXTENSION_LIMBS +) + +func TestExtensionFieldFromLimbs(t *testing.T) { + emptyField := babybear_extension.ExtensionField{} + randLimbs := test_helpers.GenerateRandomLimb(int(EXTENSION_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ExtensionField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestExtensionFieldGetLimbs(t *testing.T) { + emptyField := babybear_extension.ExtensionField{} + randLimbs := test_helpers.GenerateRandomLimb(int(EXTENSION_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ExtensionField's limbs") +} + +func TestExtensionFieldOne(t *testing.T) { + var emptyField babybear_extension.ExtensionField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(EXTENSION_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(EXTENSION_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ExtensionField with limbs to field one did not work") +} + +func TestExtensionFieldZero(t *testing.T) { + var emptyField babybear_extension.ExtensionField + emptyField.Zero() + limbsZero := make([]uint32, EXTENSION_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(EXTENSION_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ExtensionField with limbs to field zero failed") +} + +func TestExtensionFieldSize(t *testing.T) { + var emptyField babybear_extension.ExtensionField + randLimbs := test_helpers.GenerateRandomLimb(int(EXTENSION_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestExtensionFieldAsPointer(t *testing.T) { + var emptyField babybear_extension.ExtensionField + randLimbs := test_helpers.GenerateRandomLimb(int(EXTENSION_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestExtensionFieldFromBytes(t *testing.T) { + var emptyField babybear_extension.ExtensionField + bytes, expected := test_helpers.GenerateBytesArray(int(EXTENSION_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestExtensionFieldToBytes(t *testing.T) { + var emptyField babybear_extension.ExtensionField + expected, limbs := test_helpers.GenerateBytesArray(int(EXTENSION_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestBabybear_extensionGenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := babybear_extension.GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := babybear_extension.ExtensionField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestBabybear_extensionMongtomeryConversion(t *testing.T) { + size := 1 << 20 + scalars := babybear_extension.GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + babybear_extension.ToMontgomery(&deviceScalars) + + scalarsMontHost := make(core.HostSlice[babybear_extension.ExtensionField], size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + babybear_extension.FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang_v3/fields/babybear/tests/extension_vec_ops_test.go b/wrappers/golang_v3/fields/babybear/tests/extension_vec_ops_test.go new file mode 100644 index 000000000..fc8e8fab5 --- /dev/null +++ b/wrappers/golang_v3/fields/babybear/tests/extension_vec_ops_test.go @@ -0,0 +1,65 @@ +package tests + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + babybear_extension "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/extension" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/extension/vecOps" + "github.com/stretchr/testify/assert" +) + +func TestBabybear_extensionVecOps(t *testing.T) { + testSize := 1 << 14 + + a := babybear_extension.GenerateScalars(testSize) + b := babybear_extension.GenerateScalars(testSize) + var scalar babybear_extension.ExtensionField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[babybear_extension.ExtensionField], testSize) + out2 := make(core.HostSlice[babybear_extension.ExtensionField], testSize) + out3 := make(core.HostSlice[babybear_extension.ExtensionField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.VecOp(a, b, out, cfg, core.Add) + vecOps.VecOp(out, b, out2, cfg, core.Sub) + + assert.Equal(t, a, out2) + + vecOps.VecOp(a, ones, out3, cfg, core.Mul) + + assert.Equal(t, a, out3) +} + +func TestBabybear_extensionTranspose(t *testing.T) { + rowSize := 1 << 6 + columnSize := 1 << 8 + + matrix := babybear_extension.GenerateScalars(rowSize * columnSize) + + out := make(core.HostSlice[babybear_extension.ExtensionField], rowSize*columnSize) + out2 := make(core.HostSlice[babybear_extension.ExtensionField], rowSize*columnSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) + + assert.Equal(t, matrix, out2) + + var dMatrix, dOut, dOut2 core.DeviceSlice + + matrix.CopyToDevice(&dMatrix, true) + dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) + + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, cfg) + output := make(core.HostSlice[babybear_extension.ExtensionField], rowSize*columnSize) + output.CopyFromDevice(&dOut2) + + assert.Equal(t, matrix, output) +} diff --git a/wrappers/golang_v3/fields/babybear/tests/main_test.go b/wrappers/golang_v3/fields/babybear/tests/main_test.go index 992e3747b..89f915fa1 100644 --- a/wrappers/golang_v3/fields/babybear/tests/main_test.go +++ b/wrappers/golang_v3/fields/babybear/tests/main_test.go @@ -7,8 +7,6 @@ import ( "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/ntt" - - // poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/polynomial" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) diff --git a/wrappers/golang_v3/fields/babybear/tests/polynomial_test.go b/wrappers/golang_v3/fields/babybear/tests/polynomial_test.go index 09f60433b..6851dd182 100644 --- a/wrappers/golang_v3/fields/babybear/tests/polynomial_test.go +++ b/wrappers/golang_v3/fields/babybear/tests/polynomial_test.go @@ -5,7 +5,6 @@ import ( "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" - // "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/ntt" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/polynomial" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear/vecOps" @@ -212,7 +211,7 @@ func TestDivideByVanishing(t *testing.T) { // func TestPolySlice(t *testing.T) { // size := 4 // coeffs := babybear.GenerateScalars(size) -// var f polynomial.DensePolynomial +// var f DensePolynomial // f.CreateFromCoeffecitients(coeffs) // fSlice := f.AsSlice() // assert.True(t, fSlice.IsOnDevice()) diff --git a/wrappers/golang_v3/fields/babybear/tests/scalar_field_test.go b/wrappers/golang_v3/fields/babybear/tests/scalar_field_test.go index 41b9f4c6b..3ae8c001d 100644 --- a/wrappers/golang_v3/fields/babybear/tests/scalar_field_test.go +++ b/wrappers/golang_v3/fields/babybear/tests/scalar_field_test.go @@ -1,12 +1,11 @@ package tests import ( - "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/fields/babybear" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) const ( diff --git a/wrappers/golang_v3/fields/babybear/tests/vec_ops_test.go b/wrappers/golang_v3/fields/babybear/tests/vec_ops_test.go index 29b4b501e..add94730e 100644 --- a/wrappers/golang_v3/fields/babybear/tests/vec_ops_test.go +++ b/wrappers/golang_v3/fields/babybear/tests/vec_ops_test.go @@ -48,7 +48,6 @@ func TestBabybearTranspose(t *testing.T) { vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) - assert.NotEqual(t, matrix, out) assert.Equal(t, matrix, out2) var dMatrix, dOut, dOut2 core.DeviceSlice diff --git a/wrappers/golang_v3/fields/babybear/vecOps/include/vec_ops.h b/wrappers/golang_v3/fields/babybear/vecOps/include/vec_ops.h index 3438ca5b6..585b3fc7c 100644 --- a/wrappers/golang_v3/fields/babybear/vecOps/include/vec_ops.h +++ b/wrappers/golang_v3/fields/babybear/vecOps/include/vec_ops.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BABYBEAR_VEC_OPS_H diff --git a/wrappers/golang_v3/internal/generator/fields/templates/field.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/field.go.tmpl index 47bc7e92f..cf602eb17 100644 --- a/wrappers/golang_v3/internal/generator/fields/templates/field.go.tmpl +++ b/wrappers/golang_v3/internal/generator/fields/templates/field.go.tmpl @@ -9,8 +9,8 @@ import ( "fmt" {{- if .IsScalar}} "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" {{- end}} ) @@ -102,23 +102,20 @@ func GenerateScalars(size int) core.HostSlice[{{.FieldPrefix}}Field] { return scalarSlice } -func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.scalar_t)(scalars.AsUnsafePointer()) - cSize := (C.size_t)(scalars.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.{{.Field}}_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*scalars, *scalars, *scalars, &defaultCfg) + cErr := C.{{.Field}}_scalar_convert_montgomery((*C.scalar_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.scalar_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func ToMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, true) } -func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { +func FromMontgomery(scalars *core.DeviceSlice) runtime.EIcicleError { scalars.CheckDevice() return convertScalarsMontgomery(scalars, false) }{{end}} diff --git a/wrappers/golang_v3/internal/generator/fields/templates/field_test.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/field_test.go.tmpl index 2a10ef24c..0b8efc0e8 100644 --- a/wrappers/golang_v3/internal/generator/fields/templates/field_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/fields/templates/field_test.go.tmpl @@ -1,10 +1,10 @@ package tests import ( - {{- if .IsScalar}} - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"{{end}} - {{if ne .FieldPrefix "G2"}}{{.Field}}{{end}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}{{if eq .FieldPrefix "G2"}}/g2{{end}}" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + {{- if .IsScalar}} + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core"{{end}} + {{if ne .FieldPrefix "G2"}}{{.Field}}{{end}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}{{if eq .FieldPrefix "G2"}}/g2{{end}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) @@ -101,7 +101,7 @@ func Test{{capitalize .Field}}GenerateScalars(t *testing.T) { } func Test{{capitalize .Field}}MongtomeryConversion(t *testing.T) { - size := 1 << 15 + size := 1 << 20 scalars := {{.Field}}.GenerateScalars(size) var deviceScalars core.DeviceSlice @@ -109,7 +109,7 @@ func Test{{capitalize .Field}}MongtomeryConversion(t *testing.T) { {{.Field}}.ToMontgomery(&deviceScalars) - scalarsMontHost := {{.Field}}.GenerateScalars(size) + scalarsMontHost := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], size) scalarsMontHost.CopyFromDevice(&deviceScalars) assert.NotEqual(t, scalars, scalarsMontHost) diff --git a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl index f2ee003e0..f97a377a5 100644 --- a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl +++ b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl @@ -1,4 +1,4 @@ package {{.PackageName}} -// #cgo LDFLAGS: -L${SRCDIR}/../../../../{{.UpDirs}}icicle/build/lib -lingo_field_{{.Field}} -lstdc++ -lm +// #cgo LDFLAGS: -L${SRCDIR}/../../../{{.UpDirs}}icicle_v3/build -licicle_field_{{.Field}} -lstdc++ -Wl,-rpath=${SRCDIR}/../../../{{.UpDirs}}icicle_v3/build import "C" diff --git a/wrappers/golang_v3/internal/generator/fields/templates/scalar_field.h.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/scalar_field.h.tmpl index 2401d0985..74327f47e 100644 --- a/wrappers/golang_v3/internal/generator/fields/templates/scalar_field.h.tmpl +++ b/wrappers/golang_v3/internal/generator/fields/templates/scalar_field.h.tmpl @@ -1,4 +1,3 @@ -#include #include #ifndef _{{toUpper .Field}}_FIELD_H @@ -9,10 +8,10 @@ extern "C" { #endif typedef struct scalar_t scalar_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; void {{.Field}}_generate_scalars(scalar_t* scalars, int size); -cudaError_t {{.Field}}_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); +int {{.Field}}_scalar_convert_montgomery(const scalar_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, scalar_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl index 735111cd8..c65e503a7 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl @@ -5,16 +5,17 @@ package {{.PackageName}} import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func {{.CurvePrefix}}GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func {{.CurvePrefix}}Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { +func {{.CurvePrefix}}Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) @@ -23,41 +24,41 @@ func {{.CurvePrefix}}Msm(scalars core.HostOrDeviceSlice, points core.HostOrDevic cSize := (C.int)(size) cCfg := (*C.MSMConfig)(cfgPointer) - __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } // Deprecated: {{.CurvePrefix}}PrecomputeBases exists for backward compatibility. // It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. // {{.CurvePrefix}}PrecomputePoints should be used instead. -func {{.CurvePrefix}}PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := {{.CurvePrefix}}GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.{{toCName .CurvePrefix}}affine_t)(outputBasesPointer) - - __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) - return err -} +// func {{.CurvePrefix}}PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { +// cfg := {{.CurvePrefix}}GetDefaultMSMConfig() +// cfg.PrecomputeFactor = precomputeFactor +// pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) +// +// cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) +// cPointsLen := (C.int)(points.Len()) +// cPrecomputeFactor := (C.int)(precomputeFactor) +// cC := (C.int)(c) +// cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) +// cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) +// cOutputBases := (*C.{{toCName .CurvePrefix}}affine_t)(outputBasesPointer) +// +// __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) +// err := (cr.CudaError)(__ret) +// return err +// } -func {{.CurvePrefix}}PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { +func {{.CurvePrefix}}PrecomputeBases(points core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cMsmSize := (C.int)(points.Len()) cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.{{toCName .CurvePrefix}}affine_t)(outputBasesPointer) - __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_precompute_bases(cPoints, cMsmSize, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl index cd3520f1f..1a77da3e2 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl @@ -1,4 +1,3 @@ -#include #include #ifndef _{{toUpper .Curve}}_{{.CurvePrefix}}MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct {{toCName .CurvePrefix}}projective_t {{toCName .CurvePrefix}}projective_t; typedef struct {{toCName .CurvePrefix}}affine_t {{toCName .CurvePrefix}}affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_cuda(const scalar_t* scalars,const {{toCName .CurvePrefix}}affine_t* points, int count, MSMConfig* config, {{toCName .CurvePrefix}}projective_t* out); -cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_bases_cuda({{toCName .CurvePrefix}}affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, {{toCName .CurvePrefix}}affine_t* out); -cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_points_cuda({{toCName .CurvePrefix}}affine_t* points, int msm_size, MSMConfig* config, {{toCName .CurvePrefix}}affine_t* out); +cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm(const scalar_t* scalars, const {{toCName .CurvePrefix}}affine_t* points, int count, MSMConfig* config, {{toCName .CurvePrefix}}projective_t* out); +cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_precompute_bases({{toCName .CurvePrefix}}affine_t* input_bases, int bases_size, MSMConfig* config, {{toCName .CurvePrefix}}affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl index 0fb9e6c19..116db3c6a 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl @@ -13,10 +13,10 @@ import ( "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fp" "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr" {{end}} - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicle{{capitalize .Curve}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/{{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + icicle{{capitalize .Curve}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/{{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) {{if ne .GnarkImport "" -}} {{$isBW6 := eq .Curve "bw6_761"}}{{$isG2 := eq .CurvePrefix "G2"}}{{$isG1 := ne .CurvePrefix "G2"}}{{if or $isBW6 $isG1}} @@ -165,20 +165,20 @@ func TestMSM{{.CurvePrefix}}(t *testing.T) { scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) {{if ne .GnarkImport "" -}} // Check with gnark-crypto assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])) @@ -186,60 +186,60 @@ func TestMSM{{.CurvePrefix}}(t *testing.T) { } } -func TestMSM{{.CurvePrefix}}PinnedHostMemory(t *testing.T) { - cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) - points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) - - e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) - {{if ne .GnarkImport "" -}} - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])) - {{end}} - - if pinnableAndLockable { - e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - - outHost.CopyFromDevice(&out) - {{if ne .GnarkImport "" -}} - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, pinnedPoints, outHost[0])) - {{end}} - } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} +// func TestMSM{{.CurvePrefix}}PinnedHostMemory(t *testing.T) { +// cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) +// points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) +// +// e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// {{if ne .GnarkImport "" -}} +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])) +// {{end}} +// +// if pinnableAndLockable { +// e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// {{if ne .GnarkImport "" -}} +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, pinnedPoints, outHost[0])) +// {{end}} +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } {{if ne .GnarkImport "" -}} func TestMSM{{if eq .CurvePrefix "G2"}}G2{{end}}GnarkCryptoTypes(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt.go.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt.go.tmpl index eef062816..1387a714d 100644 --- a/wrappers/golang_v3/internal/generator/ntt/templates/ntt.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt.go.tmpl @@ -5,17 +5,15 @@ package {{.PackageName}} import "C" import ( - {{if .WithDomain}}{{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}"{{end}} - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" -) - -{{if .WithDomain}} -import ( + {{if .WithDomain}} "unsafe" -){{end}} -func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}"{{end}} + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) @@ -24,9 +22,9 @@ func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTCo cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.scalar_t)(resultsPointer) - __ret := C.{{if .WithDomain}}{{.Field}}{{else}}{{.FieldNoDomain}}{{end}}_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.{{if .WithDomain}}{{.Field}}{{else}}{{.FieldNoDomain}}{{end}}_ntt(cScalars, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } {{if .WithDomain}} func GetDefaultNttConfig() core.NTTConfig[[{{.Field}}.{{toConst .FieldPrefix}}LIMBS]uint32] { @@ -40,19 +38,24 @@ func GetDefaultNttConfig() core.NTTConfig[[{{.Field}}.{{toConst .FieldPrefix}}LI return core.GetDefaultNTTConfig(cosetGen) } -func InitDomain(primitiveRoot {{.Field}}.{{.FieldPrefix}}Field, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { +func GetRootOfUnity(size uint64) {{.Field}}.{{.FieldPrefix}}Field { + cRes := C.{{.Field}}_get_root_of_unity((C.size_t)(size)) + var res {{.Field}}.{{.FieldPrefix}}Field + res.FromLimbs(*(*[]uint32)(unsafe.Pointer(cRes))) + return res +} + +func InitDomain(primitiveRoot {{.Field}}.{{.FieldPrefix}}Field, cfg core.NTTInitDomainConfig) runtime.EIcicleError { cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cFastTwiddles := (C._Bool)(fastTwiddles) - __ret := C.{{.Field}}_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + cCfg := (*C.NTTInitDomainConfig)(unsafe.Pointer(&cfg)) + __ret := C.{{.Field}}_ntt_init_domain(cPrimitiveRoot, cCfg) + err := runtime.EIcicleError(__ret) + return err } -func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError { - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - __ret := C.{{.Field}}_release_domain(cCtx) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) +func ReleaseDomain() runtime.EIcicleError { + __ret := C.{{.Field}}_ntt_release_domain() + err := runtime.EIcicleError(__ret) + return err } {{end}} \ No newline at end of file diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt.h.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt.h.tmpl index 76f74bdc0..42e47b470 100644 --- a/wrappers/golang_v3/internal/generator/ntt/templates/ntt.h.tmpl +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt.h.tmpl @@ -1,4 +1,3 @@ -#include #include #ifndef _{{if .WithDomain}}{{toUpper .Field}}{{else}}{{toUpper .FieldNoDomain}}{{end}}_NTT_H @@ -10,12 +9,13 @@ extern "C" { typedef struct scalar_t scalar_t; typedef struct NTTConfig NTTConfig; -{{if .WithDomain}}typedef struct DeviceContext DeviceContext;{{end}} +{{if .WithDomain}}typedef struct NTTInitDomainConfig NTTInitDomainConfig;{{end}} -cudaError_t {{if .WithDomain}}{{.Field}}{{else}}{{.FieldNoDomain}}{{end}}_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +int {{if .WithDomain}}{{.Field}}{{else}}{{.FieldNoDomain}}{{end}}_ntt(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); {{if .WithDomain -}} -cudaError_t {{.Field}}_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); -cudaError_t {{.Field}}_release_domain(DeviceContext* ctx);{{end}} +int {{.Field}}_ntt_init_domain(scalar_t* primitive_root, NTTInitDomainConfig* ctx); +int {{.Field}}_ntt_release_domain(); +int* {{.Field}}_get_root_of_unity(size_t size);{{end}} #ifdef __cplusplus } diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_no_domain_test.go.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_no_domain_test.go.tmpl index 0317695b2..dc0e0fe19 100644 --- a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_no_domain_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_no_domain_test.go.tmpl @@ -6,10 +6,10 @@ import ( {{end -}} "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - {{.FieldNoDomain}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPathNoDomain}}" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + {{.FieldNoDomain}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPathNoDomain}}" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/ntt" ) func TestNttNoDomain(t *testing.T) { @@ -40,11 +40,11 @@ func TestNttDeviceAsyncNoDomain(t *testing.T) { testSize := 1 << size scalarsCopy := core.HostSliceFromElements[{{.FieldNoDomain}}.{{.FieldNoDomainPrefix}}Field](scalars[:testSize]) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() cfg.Ordering = v cfg.IsAsync = true - cfg.Ctx.Stream = &stream + cfg.StreamHandle = stream var deviceInput core.DeviceSlice scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) @@ -56,7 +56,7 @@ func TestNttDeviceAsyncNoDomain(t *testing.T) { output := make(core.HostSlice[{{.FieldNoDomain}}.{{.FieldNoDomainPrefix}}Field], testSize) output.CopyFromDeviceAsync(&deviceOutput, stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) } } } diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl index 19b324902..22d3788f1 100644 --- a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl @@ -6,11 +6,11 @@ import ( {{end -}} "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/ntt" {{if ne .GnarkImport "" -}} "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr" "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr/fft" @@ -72,7 +72,7 @@ func TestNTTGetDefaultConfig(t *testing.T) { func TestInitDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) } @@ -135,11 +135,11 @@ func TestNttDeviceAsync(t *testing.T) { testSize := 1 << size scalarsCopy := core.HostSliceFromElements[{{.Field}}.{{.FieldPrefix}}Field](scalars[:testSize]) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() cfg.Ordering = v cfg.IsAsync = true - cfg.Ctx.Stream = &stream + cfg.StreamHandle = stream var deviceInput core.DeviceSlice scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) @@ -151,7 +151,7 @@ func TestNttDeviceAsync(t *testing.T) { output := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], testSize) output.CopyFromDeviceAsync(&deviceOutput, stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) {{if ne .GnarkImport "" -}} // Compare with gnark-crypto assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) @@ -209,9 +209,8 @@ func TestNttBatch(t *testing.T) { func TestReleaseDomain(t *testing.T) { t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function") - cfg := ntt.GetDefaultNttConfig() - e := ntt.ReleaseDomain(cfg.Ctx) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed") + e := ntt.ReleaseDomain() + assert.Equal(t, runtime.Success, e, "ReleasDomain failed") } // func TestNttArbitraryCoset(t *testing.T) { diff --git a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.go.tmpl b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.go.tmpl index 6a523ac19..56728249b 100644 --- a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.go.tmpl +++ b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.go.tmpl @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" ) type PolynomialHandle = C.struct_PolynomialInst @@ -17,10 +17,6 @@ type DensePolynomial struct { handle *PolynomialHandle } -func InitPolyBackend() bool { - return (bool)(C.{{.Field}}_polynomial_init_cuda_backend()) -} - func (up *DensePolynomial) Print() { C.{{.Field}}_polynomial_print(up.handle) } diff --git a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.h.tmpl b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.h.tmpl index 4c3c3dedd..7182a907c 100644 --- a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.h.tmpl +++ b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial.h.tmpl @@ -12,7 +12,6 @@ typedef struct scalar_t scalar_t; typedef struct PolynomialInst PolynomialInst; typedef struct IntegrityPointer IntegrityPointer; -bool {{.Field}}_polynomial_init_cuda_backend(); PolynomialInst* {{.Field}}_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size); PolynomialInst* {{.Field}}_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size); PolynomialInst* {{.Field}}_polynomial_clone(const PolynomialInst* p); diff --git a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial_test.go.tmpl b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial_test.go.tmpl index b2adefa47..1b69c9d17 100644 --- a/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/polynomial/templates/polynomial_test.go.tmpl @@ -3,11 +3,11 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" - // "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/polynomial" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/vecOps" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" + // "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/polynomial" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/vecOps" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/internal/generator/poseidon/generate.go b/wrappers/golang_v3/internal/generator/poseidon/generate.go index 3b20149b5..e867a6359 100644 --- a/wrappers/golang_v3/internal/generator/poseidon/generate.go +++ b/wrappers/golang_v3/internal/generator/poseidon/generate.go @@ -1,32 +1,26 @@ package poseidon -import ( - "path" - - generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/internal/generator/generator_utils" -) - -var poseidonTemplates = map[string]string{ - "src": "poseidon/templates/poseidon.go.tmpl", - "test": "poseidon/templates/poseidon_test.go.tmpl", - "header": "poseidon/templates/poseidon.h.tmpl", -} +// var poseidonTemplates = map[string]string{ +// "src": "poseidon/templates/poseidon.go.tmpl", +// "test": "poseidon/templates/poseidon_test.go.tmpl", +// "header": "poseidon/templates/poseidon.h.tmpl", +// } func Generate(baseDir, additionalDirPath, field, fieldPrefix string) { - data := struct { - PackageName string - Field string - FieldPrefix string - BaseImportPath string - }{ - "poseidon", - field, - fieldPrefix, - baseDir, - } + // data := struct { + // PackageName string + // Field string + // FieldPrefix string + // BaseImportPath string + // }{ + // "poseidon", + // field, + // fieldPrefix, + // baseDir, + // } - generator.GenerateFile(poseidonTemplates["src"], path.Join(baseDir, additionalDirPath, "poseidon"), "", "", data) - generator.GenerateFile(poseidonTemplates["header"], path.Join(baseDir, additionalDirPath, "poseidon", "include"), "", "", data) - generator.GenerateFile(poseidonTemplates["test"], path.Join(baseDir, "tests"), "", "", data) + // generator.GenerateFile(poseidonTemplates["src"], path.Join(baseDir, additionalDirPath, "poseidon"), "", "", data) + // generator.GenerateFile(poseidonTemplates["header"], path.Join(baseDir, additionalDirPath, "poseidon", "include"), "", "", data) + // generator.GenerateFile(poseidonTemplates["test"], path.Join(baseDir, "tests"), "", "", data) } diff --git a/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl b/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl index 1ecfca605..ee46dcd74 100644 --- a/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl @@ -5,12 +5,11 @@ import ( "testing" {{if or .SupportsNTT .SupportsPoly -}} - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}"{{end}} + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}"{{end}} {{if .SupportsNTT -}} - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt"{{end}} - {{if .SupportsPoly -}} - poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/polynomial"{{end}} + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/ntt"{{end}} + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" {{if ne .GnarkImport "" -}} "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr/fft" @@ -21,7 +20,7 @@ const ( largestTestSize = 20 ) {{if or .SupportsNTT .SupportsPoly -}} -func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError { +func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { {{if ne .GnarkImport "" -}} rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() @@ -33,17 +32,19 @@ func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleEr rouIcicle := {{.Field}}.{{.FieldPrefix}}Field{} rouIcicle.FromUint32({{.ROU}}) {{end -}} - e := ntt.InitDomain(rouIcicle, cfg.Ctx, false) + e := ntt.InitDomain(rouIcicle, cfg) return e }{{end}} func TestMain(m *testing.M) { - {{if .SupportsPoly -}}poly.InitPolyBackend(){{end}} + runtime.LoadBackendFromEnv() + device := runtime.CreateDevice("CUDA", 0) + runtime.SetDevice(&device) {{if or .SupportsNTT .SupportsPoly -}}// setup domain - cfg := ntt.GetDefaultNttConfig() + cfg := core.GetDefaultNTTInitDomainConfig() e := initDomain(largestTestSize, cfg) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + if e != runtime.Success { panic("initDomain failed") }{{end}} @@ -51,8 +52,8 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) {{if or .SupportsNTT .SupportsPoly -}}// release domain - e = ntt.ReleaseDomain(cfg.Ctx) - if e.IcicleErrorCode != core.IcicleErrorCode(0) { + e = ntt.ReleaseDomain() + if e != runtime.Success { panic("ReleaseDomain failed") }{{end}} } diff --git a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.go.tmpl b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.go.tmpl index 4377bc012..9b5952142 100644 --- a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.go.tmpl +++ b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.go.tmpl @@ -5,44 +5,41 @@ package {{.PackageName}} import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - - "unsafe" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) { +func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) cA := (*C.scalar_t)(aPointer) - cB := (*C.scalar_t)(bPointer) + cB := (*C.scalar_t)(bPointer) cOut := (*C.scalar_t)(outPointer) cConfig := (*C.VecOpsConfig)(cfgPointer) cSize := (C.int)(size) switch op { case core.Sub: - ret = (cr.CudaError)(C.{{.Field}}_sub_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.{{.Field}}_vector_sub(cA, cB, cSize, cConfig, cOut)) case core.Add: - ret = (cr.CudaError)(C.{{.Field}}_add_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.{{.Field}}_vector_add(cA, cB, cSize, cConfig, cOut)) case core.Mul: - ret = (cr.CudaError)(C.{{.Field}}_mul_cuda(cA, cB, cSize, cConfig, cOut)) + ret = (runtime.EIcicleError)(C.{{.Field}}_vector_mul(cA, cB, cSize, cConfig, cOut)) } return ret } -func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError){ - core.TransposeCheck(in, out, onDevice) - - cIn := (*C.scalar_t)(in.AsUnsafePointer()) - cOut := (*C.scalar_t)(out.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) +func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, config core.VecOpsConfig) runtime.EIcicleError { + inPointer, _, outPointer, cfgPointer, _ := core.VecOpCheck(in, in, out, &config) + + cIn := (*C.scalar_t)(inPointer) cRowSize := (C.int)(rowSize) cColumnSize := (C.int)(columnSize) - cOnDevice := (C._Bool)(onDevice) - cIsAsync := (C._Bool)(isAsync) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cOut := (*C.scalar_t)(outPointer) + + err := (C.{{.Field}}_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) + return runtime.EIcicleError(err) +} - err := (cr.CudaError)(C.{{.Field}}_transpose_matrix_cuda( cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync)) - return core.FromCudaError(err) -} diff --git a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.h.tmpl b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.h.tmpl index 9f3c9eff0..c4dad5266 100644 --- a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.h.tmpl +++ b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops.h.tmpl @@ -1,4 +1,3 @@ -#include #include #ifndef _{{toUpper .Field}}_VEC_OPS_H @@ -12,7 +11,7 @@ typedef struct scalar_t scalar_t; typedef struct VecOpsConfig VecOpsConfig; typedef struct DeviceContext DeviceContext; -cudaError_t {{.Field}}_mul_cuda( +int {{.Field}}_vector_mul( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -20,7 +19,7 @@ cudaError_t {{.Field}}_mul_cuda( scalar_t* result ); -cudaError_t {{.Field}}_add_cuda( +int {{.Field}}_vector_add( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -28,7 +27,7 @@ cudaError_t {{.Field}}_add_cuda( scalar_t* result ); -cudaError_t {{.Field}}_sub_cuda( +int {{.Field}}_vector_sub( scalar_t* vec_a, scalar_t* vec_b, int n, @@ -36,14 +35,12 @@ cudaError_t {{.Field}}_sub_cuda( scalar_t* result ); -cudaError_t {{.Field}}_transpose_matrix_cuda( +int {{.Field}}_matrix_transpose( scalar_t* mat_in, int row_size, int column_size, - scalar_t* mat_out, - DeviceContext* ctx, - bool on_device, - bool is_async + VecOpsConfig* config, + scalar_t* mat_out ); #ifdef __cplusplus diff --git a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops_test.go.tmpl b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops_test.go.tmpl index 817a5dba6..b476cb476 100644 --- a/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/vecOps/templates/vec_ops_test.go.tmpl @@ -3,10 +3,9 @@ package tests import ( "testing" - {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/vecOps" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/vecOps" "github.com/stretchr/testify/assert" ) @@ -38,30 +37,28 @@ func Test{{capitalize .Field}}VecOps(t *testing.T) { func Test{{capitalize .Field}}Transpose(t *testing.T) { rowSize := 1 << 6 columnSize := 1 << 8 - onDevice := false - isAsync := false matrix := {{.Field}}.GenerateScalars(rowSize * columnSize) out := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], rowSize*columnSize) out2 := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], rowSize*columnSize) - ctx, _ := cr.GetDefaultDeviceContext() + cfg := core.DefaultVecOpsConfig() + + vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(out, out2, rowSize, columnSize, cfg) - vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync) assert.Equal(t, matrix, out2) var dMatrix, dOut, dOut2 core.DeviceSlice - onDevice = true matrix.CopyToDevice(&dMatrix, true) dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement()) - vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync) - vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync) + vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, cfg) + vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, cfg) output := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], rowSize*columnSize) output.CopyFromDevice(&dOut2) From 7476f6f2abc6c29c0ea7635cdc5ff7ea40dd97f0 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Tue, 23 Jul 2024 07:55:14 +0000 Subject: [PATCH 19/38] msm tests --- wrappers/golang_v3/README.md | 8 +- wrappers/golang_v3/core/msm.go | 3 + wrappers/golang_v3/curves/bls12377/curve.go | 4 +- .../golang_v3/curves/bls12377/ecntt/ecntt.go | 4 +- .../golang_v3/curves/bls12377/g2/curve.go | 4 +- wrappers/golang_v3/curves/bls12377/g2/msm.go | 5 +- wrappers/golang_v3/curves/bls12377/msm/msm.go | 5 +- .../curves/bls12377/poseidon/poseidon.go | 4 +- .../curves/bls12377/tests/curve_test.go | 7 +- .../curves/bls12377/tests/ecntt_test.go | 8 +- .../curves/bls12377/tests/g2_curve_test.go | 7 +- .../curves/bls12377/tests/g2_msm_test.go | 10 +- .../curves/bls12377/tests/msm_test.go | 10 +- .../curves/bls12377/tests/poseidon_test.go | 8 +- wrappers/golang_v3/curves/bls12381/curve.go | 4 +- .../golang_v3/curves/bls12381/ecntt/ecntt.go | 4 +- .../golang_v3/curves/bls12381/g2/curve.go | 4 +- wrappers/golang_v3/curves/bls12381/g2/msm.go | 5 +- wrappers/golang_v3/curves/bls12381/msm/msm.go | 5 +- .../curves/bls12381/poseidon/poseidon.go | 4 +- .../curves/bls12381/tests/curve_test.go | 7 +- .../curves/bls12381/tests/ecntt_test.go | 8 +- .../curves/bls12381/tests/g2_curve_test.go | 7 +- .../curves/bls12381/tests/g2_msm_test.go | 10 +- .../curves/bls12381/tests/msm_test.go | 10 +- .../curves/bls12381/tests/poseidon_test.go | 9 +- .../golang_v3/curves/bn254/ecntt/ecntt.go | 12 +- .../curves/bn254/ecntt/include/ecntt.h | 2 +- wrappers/golang_v3/curves/bn254/g2/curve.go | 4 +- wrappers/golang_v3/curves/bn254/g2/msm.go | 4 +- wrappers/golang_v3/curves/bn254/main.go | 3 +- wrappers/golang_v3/curves/bn254/msm/msm.go | 6 +- .../curves/bn254/poseidon/include/poseidon.h | 25 --- .../curves/bn254/poseidon/poseidon.go | 57 ----- .../curves/bn254/tests/curve_test.go | 203 ++++++++--------- .../curves/bn254/tests/ecntt_test.go | 60 ++--- .../curves/bn254/tests/g2_curve_test.go | 4 +- .../curves/bn254/tests/g2_msm_test.go | 8 +- .../golang_v3/curves/bn254/tests/main_test.go | 8 +- .../golang_v3/curves/bn254/tests/msm_test.go | 205 +++++++++++------- .../golang_v3/curves/bn254/tests/ntt_test.go | 6 + .../curves/bn254/tests/poseidon_test.go | 42 ---- wrappers/golang_v3/curves/bw6761/curve.go | 4 +- .../golang_v3/curves/bw6761/ecntt/ecntt.go | 4 +- wrappers/golang_v3/curves/bw6761/g2/curve.go | 4 +- wrappers/golang_v3/curves/bw6761/g2/msm.go | 5 +- wrappers/golang_v3/curves/bw6761/msm/msm.go | 5 +- .../curves/bw6761/poseidon/poseidon.go | 4 +- .../curves/bw6761/tests/curve_test.go | 7 +- .../curves/bw6761/tests/ecntt_test.go | 8 +- .../curves/bw6761/tests/g2_curve_test.go | 7 +- .../curves/bw6761/tests/g2_msm_test.go | 10 +- .../golang_v3/curves/bw6761/tests/msm_test.go | 10 +- .../curves/bw6761/tests/poseidon_test.go | 8 +- wrappers/golang_v3/curves/grumpkin/curve.go | 4 +- wrappers/golang_v3/curves/grumpkin/msm/msm.go | 5 +- .../curves/grumpkin/poseidon/poseidon.go | 4 +- .../curves/grumpkin/tests/curve_test.go | 7 +- .../curves/grumpkin/tests/msm_test.go | 8 +- .../curves/grumpkin/tests/poseidon_test.go | 8 +- wrappers/golang_v3/hash/keccak/hasher.go | 88 -------- .../golang_v3/hash/keccak/include/keccak.h | 20 -- wrappers/golang_v3/hash/keccak/main.go | 4 - .../hash/keccak/tests/hasher_test.go | 66 ------ .../generator/curves/templates/curve.go.tmpl | 4 +- .../curves/templates/curve_test.go.tmpl | 4 +- .../generator/ecntt/templates/ecntt.go.tmpl | 4 +- .../ecntt/templates/ecntt_test.go.tmpl | 8 +- .../generator/generator_utils/generate.go | 2 +- .../poseidon/templates/poseidon.go.tmpl | 4 +- .../poseidon/templates/poseidon_test.go.tmpl | 8 +- wrappers/golang_v3/runtime/device.go | 6 +- wrappers/golang_v3/runtime/runtime.go | 62 ++++++ 73 files changed, 518 insertions(+), 687 deletions(-) delete mode 100644 wrappers/golang_v3/curves/bn254/poseidon/include/poseidon.h delete mode 100644 wrappers/golang_v3/curves/bn254/poseidon/poseidon.go delete mode 100644 wrappers/golang_v3/curves/bn254/tests/poseidon_test.go delete mode 100644 wrappers/golang_v3/hash/keccak/hasher.go delete mode 100644 wrappers/golang_v3/hash/keccak/include/keccak.h delete mode 100644 wrappers/golang_v3/hash/keccak/main.go delete mode 100644 wrappers/golang_v3/hash/keccak/tests/hasher_test.go diff --git a/wrappers/golang_v3/README.md b/wrappers/golang_v3/README.md index dbd50cb6d..5f3c2ea0e 100644 --- a/wrappers/golang_v3/README.md +++ b/wrappers/golang_v3/README.md @@ -53,7 +53,7 @@ If you wish to build for a specific curve, for example bn254, without G2 or ECNT To run the tests for curve bn254. ```sh -go test ./wrappers/golang/curves/bn254/tests -count=1 -v +go test ./wrappers/golang_v3/curves/bn254/tests -count=1 -v ``` To run all the tests in the golang bindings @@ -106,9 +106,9 @@ This is normally fixed by exporting the path to the shared library location in t ### cuda_runtime.h: No such file or directory ```sh -# github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381 -In file included from wrappers/golang/curves/bls12381/curve.go:5: -wrappers/golang/curves/bls12381/include/curve.h:1:10: fatal error: cuda_runtime.h: No such file or directory +# github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381 +In file included from wrappers/golang_v3/curves/bls12381/curve.go:5: +wrappers/golang_v3/curves/bls12381/include/curve.h:1:10: fatal error: cuda_runtime.h: No such file or directory 1 | #include | ^~~~~~~~~~~~~~~~ compilation terminated. diff --git a/wrappers/golang_v3/core/msm.go b/wrappers/golang_v3/core/msm.go index 7b136a732..882db708d 100644 --- a/wrappers/golang_v3/core/msm.go +++ b/wrappers/golang_v3/core/msm.go @@ -79,6 +79,8 @@ func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfi panic(errorString) } + cfg.basesSize = int32(pointsLength) + cfg.batchSize = int32(resultsLength) cfg.areScalarsOnDevice = scalars.IsOnDevice() cfg.areBasesOnDevice = points.IsOnDevice() cfg.areResultsOnDevice = results.IsOnDevice() @@ -116,6 +118,7 @@ func PrecomputePointsCheck(points HostOrDeviceSlice, cfg *MSMConfig, outputBases cfg.basesSize = int32(pointsLength) cfg.areBasesOnDevice = points.IsOnDevice() + cfg.areResultsOnDevice = points.IsOnDevice() return points.AsUnsafePointer(), outputBases.AsUnsafePointer() } diff --git a/wrappers/golang_v3/curves/bls12377/curve.go b/wrappers/golang_v3/curves/bls12377/curve.go index e21dd5808..4b08ed1eb 100644 --- a/wrappers/golang_v3/curves/bls12377/curve.go +++ b/wrappers/golang_v3/curves/bls12377/curve.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) type Projective struct { diff --git a/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go b/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go index 0fe75abdf..4bf130b51 100644 --- a/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go +++ b/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go @@ -5,8 +5,8 @@ package ecntt import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { diff --git a/wrappers/golang_v3/curves/bls12377/g2/curve.go b/wrappers/golang_v3/curves/bls12377/g2/curve.go index 50ac2a110..31247a7e6 100644 --- a/wrappers/golang_v3/curves/bls12377/g2/curve.go +++ b/wrappers/golang_v3/curves/bls12377/g2/curve.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) type G2Projective struct { diff --git a/wrappers/golang_v3/curves/bls12377/g2/msm.go b/wrappers/golang_v3/curves/bls12377/g2/msm.go index bf47b86da..1a46b3c98 100644 --- a/wrappers/golang_v3/curves/bls12377/g2/msm.go +++ b/wrappers/golang_v3/curves/bls12377/g2/msm.go @@ -5,9 +5,10 @@ package g2 import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func G2GetDefaultMSMConfig() core.MSMConfig { diff --git a/wrappers/golang_v3/curves/bls12377/msm/msm.go b/wrappers/golang_v3/curves/bls12377/msm/msm.go index 34861acc2..01fc11867 100644 --- a/wrappers/golang_v3/curves/bls12377/msm/msm.go +++ b/wrappers/golang_v3/curves/bls12377/msm/msm.go @@ -5,9 +5,10 @@ package msm import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultMSMConfig() core.MSMConfig { diff --git a/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go b/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go index 5b452827b..68538731f 100644 --- a/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go +++ b/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultPoseidonConfig() core.PoseidonConfig { diff --git a/wrappers/golang_v3/curves/bls12377/tests/curve_test.go b/wrappers/golang_v3/curves/bls12377/tests/curve_test.go index be176bbe0..065b44cd0 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/curve_test.go @@ -1,10 +1,11 @@ package tests import ( - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" "testing" + + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go b/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go index 696f6d43b..7ad4cbb9b 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go @@ -3,10 +3,10 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ecntt" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/ntt" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go index 64fd2fd85..25a32b56d 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go @@ -1,10 +1,11 @@ package tests import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" ) func TestG2AffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go index 86bd50f8a..80fb58ddb 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark-crypto/ecc/bls12-377" + bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleBls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + icicleBls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/g2" ) func projectiveToGnarkAffineG2(p g2.G2Projective) bls12377.G2Affine { diff --git a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go index 1c74cc1bc..c04cb10bc 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark-crypto/ecc/bls12-377" + bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleBls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + icicleBls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/msm" ) func projectiveToGnarkAffine(p icicleBls12_377.Projective) bls12377.G1Affine { diff --git a/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go b/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go index b768fa291..f4e30ad29 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go @@ -3,10 +3,10 @@ package tests import ( "testing" - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/poseidon" + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/poseidon" ) func TestPoseidon(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12381/curve.go b/wrappers/golang_v3/curves/bls12381/curve.go index d376c5c21..ce3bd9800 100644 --- a/wrappers/golang_v3/curves/bls12381/curve.go +++ b/wrappers/golang_v3/curves/bls12381/curve.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) type Projective struct { diff --git a/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go b/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go index 943ef8146..032ae3ecb 100644 --- a/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go +++ b/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go @@ -5,8 +5,8 @@ package ecntt import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { diff --git a/wrappers/golang_v3/curves/bls12381/g2/curve.go b/wrappers/golang_v3/curves/bls12381/g2/curve.go index 2b8caa002..7b27b39ab 100644 --- a/wrappers/golang_v3/curves/bls12381/g2/curve.go +++ b/wrappers/golang_v3/curves/bls12381/g2/curve.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) type G2Projective struct { diff --git a/wrappers/golang_v3/curves/bls12381/g2/msm.go b/wrappers/golang_v3/curves/bls12381/g2/msm.go index 05c407147..b491e40b4 100644 --- a/wrappers/golang_v3/curves/bls12381/g2/msm.go +++ b/wrappers/golang_v3/curves/bls12381/g2/msm.go @@ -5,9 +5,10 @@ package g2 import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func G2GetDefaultMSMConfig() core.MSMConfig { diff --git a/wrappers/golang_v3/curves/bls12381/msm/msm.go b/wrappers/golang_v3/curves/bls12381/msm/msm.go index b9cbabb70..7170c7336 100644 --- a/wrappers/golang_v3/curves/bls12381/msm/msm.go +++ b/wrappers/golang_v3/curves/bls12381/msm/msm.go @@ -5,9 +5,10 @@ package msm import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultMSMConfig() core.MSMConfig { diff --git a/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go b/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go index 1f99b2b51..f3d814d92 100644 --- a/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go +++ b/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultPoseidonConfig() core.PoseidonConfig { diff --git a/wrappers/golang_v3/curves/bls12381/tests/curve_test.go b/wrappers/golang_v3/curves/bls12381/tests/curve_test.go index ad33d17b8..34513d096 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/curve_test.go @@ -1,10 +1,11 @@ package tests import ( - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" "testing" + + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go b/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go index 24837aabc..7ceb4af10 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go @@ -3,10 +3,10 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ecntt" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/ntt" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go index e804b7607..dd21ccf4f 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go @@ -1,10 +1,11 @@ package tests import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/g2" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" ) func TestG2AffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go index 424e064b5..1021298dc 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark-crypto/ecc/bls12-381" + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleBls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + icicleBls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/g2" ) func projectiveToGnarkAffineG2(p g2.G2Projective) bls12381.G2Affine { diff --git a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go index 196371a24..2434f7d97 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark-crypto/ecc/bls12-381" + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleBls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + icicleBls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/msm" ) func projectiveToGnarkAffine(p icicleBls12_381.Projective) bls12381.G1Affine { diff --git a/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go b/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go index 915e89574..e36b0d41b 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go @@ -3,12 +3,13 @@ package tests import ( "testing" - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/poseidon" + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/poseidon" "fmt" + "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go b/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go index feda5f2d9..d76f5c33e 100644 --- a/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go +++ b/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go @@ -5,11 +5,11 @@ package ecntt import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) cr.EIcicleError { pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) cPoints := (*C.projective_t)(pointsPointer) @@ -18,7 +18,7 @@ func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTC cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.projective_t)(resultsPointer) - __ret := C.bn254_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.bn254_ecntt(cPoints, cSize, cDir, cCfg, cResults) + err := (cr.EIcicleError)(__ret) + return err } diff --git a/wrappers/golang_v3/curves/bn254/ecntt/include/ecntt.h b/wrappers/golang_v3/curves/bn254/ecntt/include/ecntt.h index da61fb915..7809610c7 100644 --- a/wrappers/golang_v3/curves/bn254/ecntt/include/ecntt.h +++ b/wrappers/golang_v3/curves/bn254/ecntt/include/ecntt.h @@ -10,7 +10,7 @@ extern "C" { typedef struct NTTConfig NTTConfig; typedef struct projective_t projective_t; -cudaError_t bn254_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); +int bn254_ecntt(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/g2/curve.go b/wrappers/golang_v3/curves/bn254/g2/curve.go index 77bb2aa49..e9a1fd7be 100644 --- a/wrappers/golang_v3/curves/bn254/g2/curve.go +++ b/wrappers/golang_v3/curves/bn254/g2/curve.go @@ -7,8 +7,8 @@ package g2 // import ( // "unsafe" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" -// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" +// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" // ) // type G2Projective struct { diff --git a/wrappers/golang_v3/curves/bn254/g2/msm.go b/wrappers/golang_v3/curves/bn254/g2/msm.go index 9a01ee6d8..b3a4538a5 100644 --- a/wrappers/golang_v3/curves/bn254/g2/msm.go +++ b/wrappers/golang_v3/curves/bn254/g2/msm.go @@ -5,8 +5,8 @@ package g2 // import "C" // import ( -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" -// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" +// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" // "unsafe" // ) diff --git a/wrappers/golang_v3/curves/bn254/main.go b/wrappers/golang_v3/curves/bn254/main.go index 3acfd384b..721fdf90a 100644 --- a/wrappers/golang_v3/curves/bn254/main.go +++ b/wrappers/golang_v3/curves/bn254/main.go @@ -1,4 +1,5 @@ package bn254 -// #cgo LDFLAGS: -L${SRCDIR}/../../../icicle_v3/build -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../icicle_v3/build +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bn254 -lingo_field_bn254 -lstdc++ -lm import "C" diff --git a/wrappers/golang_v3/curves/bn254/msm/msm.go b/wrappers/golang_v3/curves/bn254/msm/msm.go index 42014c94d..a08e6ea73 100644 --- a/wrappers/golang_v3/curves/bn254/msm/msm.go +++ b/wrappers/golang_v3/curves/bn254/msm/msm.go @@ -50,15 +50,15 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor // return err // } -func PrecomputeBases(points core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { +func PrecomputeBases(points core.HostOrDeviceSlice, size int, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) cPoints := (*C.affine_t)(pointsPointer) - cMsmSize := (C.int)(points.Len()) + cSize := (C.int)(size) cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.affine_t)(outputBasesPointer) - __ret := C.bn254_msm_precompute_bases(cPoints, cMsmSize, cCfg, cOutputBases) + __ret := C.bn254_msm_precompute_bases(cPoints, cSize, cCfg, cOutputBases) err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bn254/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/bn254/poseidon/include/poseidon.h deleted file mode 100644 index 5d63920d6..000000000 --- a/wrappers/golang_v3/curves/bn254/poseidon/include/poseidon.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#ifndef _BN254_POSEIDON_H -#define _BN254_POSEIDON_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct scalar_t scalar_t; -typedef struct PoseidonConfig PoseidonConfig; -typedef struct DeviceContext DeviceContext; -typedef struct PoseidonConstants PoseidonConstants; - - -cudaError_t bn254_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); -cudaError_t bn254_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); -cudaError_t bn254_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bn254/poseidon/poseidon.go b/wrappers/golang_v3/curves/bn254/poseidon/poseidon.go deleted file mode 100644 index e5724e80f..000000000 --- a/wrappers/golang_v3/curves/bn254/poseidon/poseidon.go +++ /dev/null @@ -1,57 +0,0 @@ -package poseidon - -// #cgo CFLAGS: -I./include/ -// #include "poseidon.h" -import "C" - -import ( - "unsafe" - - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" -) - -func GetDefaultPoseidonConfig() core.PoseidonConfig { - return core.GetDefaultPoseidonConfig() -} - -func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { - scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) - - cScalars := (*C.scalar_t)(scalarsPointer) - cResults := (*C.scalar_t)(resultsPointer) - cNumberOfStates := (C.int)(numberOfStates) - cArity := (C.int)(constants.Arity) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - cCfg := (*C.PoseidonConfig)(cfgPointer) - - __ret := C.bn254_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) - - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cFullRoundsHalfs := (C.int)(fullRoundsHalfs) - cPartialRounds := (C.int)(partialRounds) - cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) - - __ret := C.bn254_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - - __ret := C.bn254_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} diff --git a/wrappers/golang_v3/curves/bn254/tests/curve_test.go b/wrappers/golang_v3/curves/bn254/tests/curve_test.go index 92c3a3519..128d3680c 100644 --- a/wrappers/golang_v3/curves/bn254/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/curve_test.go @@ -1,103 +1,104 @@ package tests -// import ( -// bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" -// "github.com/stretchr/testify/assert" -// "testing" -// ) - -// func TestAffineZero(t *testing.T) { -// var fieldZero = bn254.BaseField{} - -// var affineZero bn254.Affine -// assert.Equal(t, affineZero.X, fieldZero) -// assert.Equal(t, affineZero.Y, fieldZero) - -// x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// var affine bn254.Affine -// affine.FromLimbs(x, y) - -// affine.Zero() -// assert.Equal(t, affine.X, fieldZero) -// assert.Equal(t, affine.Y, fieldZero) -// } - -// func TestAffineFromLimbs(t *testing.T) { -// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - -// var affine bn254.Affine -// affine.FromLimbs(randLimbs, randLimbs2) - -// assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) -// assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) -// } - -// func TestAffineToProjective(t *testing.T) { -// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// var fieldOne bn254.BaseField -// fieldOne.One() - -// var expected bn254.Projective -// expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) - -// var affine bn254.Affine -// affine.FromLimbs(randLimbs, randLimbs2) - -// projectivePoint := affine.ToProjective() -// assert.Equal(t, expected, projectivePoint) -// } - -// func TestProjectiveZero(t *testing.T) { -// var projectiveZero bn254.Projective -// projectiveZero.Zero() -// var fieldZero = bn254.BaseField{} -// var fieldOne bn254.BaseField -// fieldOne.One() - -// assert.Equal(t, projectiveZero.X, fieldZero) -// assert.Equal(t, projectiveZero.Y, fieldOne) -// assert.Equal(t, projectiveZero.Z, fieldZero) - -// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// var projective bn254.Projective -// projective.FromLimbs(randLimbs, randLimbs, randLimbs) - -// projective.Zero() -// assert.Equal(t, projective.X, fieldZero) -// assert.Equal(t, projective.Y, fieldOne) -// assert.Equal(t, projective.Z, fieldZero) -// } - -// func TestProjectiveFromLimbs(t *testing.T) { -// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) - -// var projective bn254.Projective -// projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) - -// assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) -// assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) -// assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) -// } - -// func TestProjectiveFromAffine(t *testing.T) { -// randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) -// var fieldOne bn254.BaseField -// fieldOne.One() - -// var expected bn254.Projective -// expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) - -// var affine bn254.Affine -// affine.FromLimbs(randLimbs, randLimbs2) - -// var projectivePoint bn254.Projective -// projectivePoint.FromAffine(affine) -// assert.Equal(t, expected, projectivePoint) -// } +import ( + "testing" + + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = bn254.BaseField{} + + var affineZero bn254.Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var affine bn254.Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var affine bn254.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bn254.BaseField + fieldOne.One() + + var expected bn254.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bn254.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero bn254.Projective + projectiveZero.Zero() + var fieldZero = bn254.BaseField{} + var fieldOne bn254.BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var projective bn254.Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + + var projective bn254.Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS)) + var fieldOne bn254.BaseField + fieldOne.One() + + var expected bn254.Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine bn254.Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint bn254.Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go index 77182d9dd..b4cca0042 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go @@ -1,30 +1,34 @@ package tests -// import ( -// "testing" - -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" -// bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" -// ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ecntt" -// ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt" -// "github.com/stretchr/testify/assert" -// ) - -// func TestECNtt(t *testing.T) { -// cfg := ntt.GetDefaultNttConfig() -// points := bn254.GenerateProjectivePoints(1 << largestTestSize) - -// for _, size := range []int{4, 5, 6, 7, 8} { -// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { -// testSize := 1 << size - -// pointsCopy := core.HostSliceFromElements[bn254.Projective](points[:testSize]) -// cfg.Ordering = v -// cfg.NttAlgorithm = core.Radix2 - -// output := make(core.HostSlice[bn254.Projective], testSize) -// e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) -// assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") -// } -// } -// } +import ( + "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/stretchr/testify/assert" +) + +func TestECNtt(t *testing.T) { + cfg := ntt.GetDefaultNttConfig() + points := bn254.GenerateProjectivePoints(1 << largestTestSize) + + for _, size := range []int{4, 5, 6, 7, 8} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + + runtime.SetDevice(&MAIN_DEVICE) + + testSize := 1 << size + + pointsCopy := core.HostSliceFromElements[bn254.Projective](points[:testSize]) + cfg.Ordering = v + // cfg. = core.Radix2 + + output := make(core.HostSlice[bn254.Projective], testSize) + e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) + assert.Equal(t, runtime.Success, e, "ECNtt failed") + } + } +} diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go index 9f1cd6bbb..a36364085 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go @@ -1,8 +1,8 @@ package tests // import ( -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" // "github.com/stretchr/testify/assert" // "testing" // ) diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go index 24feb123a..914039b37 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go @@ -12,10 +12,10 @@ package tests // "github.com/consensys/gnark-crypto/ecc/bn254/fp" // "github.com/consensys/gnark-crypto/ecc/bn254/fr" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" -// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" -// icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" +// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" +// icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" +// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" // ) // func projectiveToGnarkAffineG2(p g2.G2Projective) bn254.G2Affine { diff --git a/wrappers/golang_v3/curves/bn254/tests/main_test.go b/wrappers/golang_v3/curves/bn254/tests/main_test.go index be9fe8fcd..40763bac5 100644 --- a/wrappers/golang_v3/curves/bn254/tests/main_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/main_test.go @@ -13,9 +13,11 @@ import ( ) const ( - largestTestSize = 20 + largestTestSize = 5 ) +var MAIN_DEVICE runtime.Device + func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() @@ -29,8 +31,8 @@ func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcic func TestMain(m *testing.M) { runtime.LoadBackendFromEnv() - device := runtime.CreateDevice("CUDA", 0) - runtime.SetDevice(&device) + MAIN_DEVICE = runtime.CreateDevice("CUDA", 0) + runtime.SetDevice(&MAIN_DEVICE) // setup domain cfg := core.GetDefaultNTTInitDomainConfig() diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index f84158077..89191f602 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -1,6 +1,8 @@ package tests import ( + "fmt" + "sync" "testing" "github.com/stretchr/testify/assert" @@ -14,6 +16,10 @@ import ( icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/msm" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + + coreV2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v2/core" + crV2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v2/cuda_runtime" + msmV2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v2/curves/bn254/msm" ) func projectiveToGnarkAffine(p icicleBn254.Projective) bn254.G1Affine { @@ -52,11 +58,12 @@ func testAgainstGnarkCryptoMsmGnarkCryptoTypes(t *testing.T, scalarsFr core.Host var msmRes bn254.G1Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - var icicleResAsJac bn254.G1Jac - proj := projectiveToGnarkAffine(out) - icicleResAsJac.FromAffine(&proj) + var msmResAffine bn254.G1Affine + msmResAffine.FromJacobian(&msmRes) + + icicleResAffine := projectiveToGnarkAffine(out) - assert.True(t, msmRes.Equal(&icicleResAsJac)) + assert.Equal(t, msmResAffine, icicleResAffine) } func convertIcicleAffineToG1Affine(iciclePoints []icicleBn254.Affine) []bn254.G1Affine { @@ -79,7 +86,8 @@ func convertIcicleAffineToG1Affine(iciclePoints []icicleBn254.Affine) []bn254.G1 func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5} { + for _, power := range []int{2, 3, 4, 5, 10} { + runtime.SetDevice(&MAIN_DEVICE) size := 1 << power scalars := icicleBn254.GenerateScalars(size) @@ -158,12 +166,13 @@ func TestMSM(t *testing.T) { func TestMSMGnarkCryptoTypes(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{3} { + runtime.SetDevice(&MAIN_DEVICE) size := 1 << power scalars := make([]fr.Element, size) var x fr.Element for i := 0; i < size; i++ { - x.SetRandom() + x.SetInt64(int64(10000 * (i + 1))) scalars[i] = x } scalarsHost := (core.HostSlice[fr.Element])(scalars) @@ -184,6 +193,19 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { outHost.CopyFromDevice(&out) out.Free() + cfgV2 := coreV2.GetDefaultMSMConfig() + cfgV2.ArePointsMontgomeryForm = true + cfgV2.AreScalarsMontgomeryForm = true + + scalarsHostV2 := (coreV2.HostSlice[fr.Element])(scalars) + pointsHostV2 := (coreV2.HostSlice[bn254.G1Affine])(pointsGnark) + + outHostV2 := make(coreV2.HostSlice[icicleBn254.Projective], 1) + + eV2 := msmV2.Msm(scalarsHostV2, pointsHostV2, &cfgV2, outHostV2) + assert.Equal(t, crV2.CudaSuccess, eV2) + + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, (core.HostSlice[fr.Element])(scalarsHostV2), (core.HostSlice[bn254.G1Affine])(pointsHostV2), outHostV2[0]) // Check with gnark-crypto testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } @@ -193,6 +215,7 @@ func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{5} { for _, batchSize := range []int{1, 3} { + runtime.SetDevice(&MAIN_DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicleBn254.GenerateScalars(totalSize) @@ -219,50 +242,54 @@ func TestMSMBatch(t *testing.T) { } } -// func TestPrecomputePoints(t *testing.T) { -// cfg := msm.GetDefaultMSMConfig() -// const precomputeFactor = 8 -// cfg.PrecomputeFactor = precomputeFactor - -// for _, power := range []int{10, 16} { -// for _, batchSize := range []int{1, 3} { -// size := 1 << power -// totalSize := size * batchSize -// scalars := icicleBn254.GenerateScalars(totalSize) -// points := icicleBn254.GenerateAffinePoints(totalSize) - -// var precomputeOut core.DeviceSlice -// _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) -// assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - -// e = msm.PrecomputeBases(points, &cfg, precomputeOut) -// assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") - -// var p icicleBn254.Projective -// var out core.DeviceSlice -// _, e = out.Malloc(batchSize*p.Size(), p.Size()) -// assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") - -// e = msm.Msm(scalars, precomputeOut, &cfg, out) -// assert.Equal(t, runtime.Success, e, "Msm failed") -// outHost := make(core.HostSlice[icicleBn254.Projective], batchSize) -// outHost.CopyFromDevice(&out) -// out.Free() -// precomputeOut.Free() -// // Check with gnark-crypto -// for i := 0; i < batchSize; i++ { -// scalarsSlice := scalars[i*size : (i+1)*size] -// pointsSlice := points[i*size : (i+1)*size] -// out := outHost[i] -// assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) -// } -// } -// } -// } +func TestPrecomputePoints(t *testing.T) { + cfg := core.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3} { + runtime.SetDevice(&MAIN_DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := icicleBn254.GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputeBases(points, size, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p icicleBn254.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) + } + } + } +} func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&MAIN_DEVICE) + size := 1 << power scalars := icicleBn254.GenerateScalars(size) @@ -289,40 +316,52 @@ func TestMSMSkewedDistribution(t *testing.T) { } } -// func TestMSMMultiDevice(t *testing.T) { -// numDevices, _ := runtime.GetDeviceCount() -// fmt.Println("There are ", numDevices, " devices available") -// wg := sync.WaitGroup{} - -// for i := 0; i < numDevices; i++ { -// wg.Add(1) -// runtime.RunOnDevice(i, func(args ...any) { -// defer wg.Done() -// cfg := msm.GetDefaultMSMConfig() -// cfg.IsAsync = true -// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { -// size := 1 << power -// scalars := icicleBn254.GenerateScalars(size) -// points := icicleBn254.GenerateAffinePoints(size) - -// stream, _ := runtime.CreateStream() -// var p icicleBn254.Projective -// var out core.DeviceSlice -// _, e := out.MallocAsync(p.Size(), p.Size(), stream) -// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") -// cfg.Ctx.Stream = &stream - -// e = msm.Msm(scalars, points, &cfg, out) -// assert.Equal(t, e, runtime.Success, "Msm failed") -// outHost := make(core.HostSlice[icicleBn254.Projective], 1) -// outHost.CopyFromDeviceAsync(&out, stream) -// out.FreeAsync(stream) - -// runtime.SynchronizeStream(&stream) -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) -// } -// }) -// } -// wg.Wait() -// } +func TestMSMMultiDevice(t *testing.T) { + deviceTypes, _ := runtime.GetRegisteredDevices() + for _, deviceType := range deviceTypes { + device := runtime.CreateDevice(deviceType, 0) + runtime.SetDevice(&device) + runtime.GetDeviceCount() + + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", deviceType, " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: device.DeviceType, Id: i} + wg.Add(1) + runtime.RunOnDevice(¤tDevice, func(args ...any) { + defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5} { + size := 1 << power + scalars := icicleBn254.GenerateScalars(size) + points := icicleBn254.GenerateAffinePoints(size) + + stream, _ := runtime.CreateStream() + var p icicleBn254.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, runtime.Success, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + runtime.SynchronizeStream(stream) + // Check with gnark-crypto + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) + } + }) + } + wg.Wait() + } + +} diff --git a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go index 579871ab6..c053f119c 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go @@ -110,6 +110,8 @@ func TestNttFrElement(t *testing.T) { for _, size := range []int{4} { for _, v := range [1]core.Ordering{core.KNN} { + runtime.SetDevice(&MAIN_DEVICE) + testSize := size scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) @@ -132,6 +134,8 @@ func TestNttDeviceAsync(t *testing.T) { for _, size := range []int{1, 10, largestTestSize} { for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&MAIN_DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bn254.ScalarField](scalars[:testSize]) @@ -167,6 +171,8 @@ func TestNttBatch(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, batchSize := range []int{2, 16, largestBatchSize} { + runtime.SetDevice(&MAIN_DEVICE) + testSize := 1 << size totalSize := testSize * batchSize diff --git a/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go b/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go deleted file mode 100644 index 442757c77..000000000 --- a/wrappers/golang_v3/curves/bn254/tests/poseidon_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package tests - -// import ( -// "testing" - -// core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" -// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" -// bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254" -// poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/poseidon" -// ) - -// func TestPoseidon(t *testing.T) { - -// arity := 2 -// numberOfStates := 1 - -// cfg := poseidon.GetDefaultPoseidonConfig() -// cfg.IsAsync = true -// stream, _ := cr.CreateStream() -// cfg.Ctx.Stream = &stream - -// var constants core.PoseidonConstants[bn254.ScalarField] - -// poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants - -// scalars := bn254.GenerateScalars(numberOfStates * arity) -// scalars[0] = scalars[0].Zero() -// scalars[1] = scalars[0].Zero() - -// scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) - -// var deviceInput core.DeviceSlice -// scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) -// var deviceOutput core.DeviceSlice -// deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) - -// poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function - -// output := make(core.HostSlice[bn254.ScalarField], numberOfStates) -// output.CopyFromDeviceAsync(&deviceOutput, stream) - -// } diff --git a/wrappers/golang_v3/curves/bw6761/curve.go b/wrappers/golang_v3/curves/bw6761/curve.go index 907971405..13cd1a3aa 100644 --- a/wrappers/golang_v3/curves/bw6761/curve.go +++ b/wrappers/golang_v3/curves/bw6761/curve.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) type Projective struct { diff --git a/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go b/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go index 4bf2db434..76fa366e0 100644 --- a/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go +++ b/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go @@ -5,8 +5,8 @@ package ecntt import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { diff --git a/wrappers/golang_v3/curves/bw6761/g2/curve.go b/wrappers/golang_v3/curves/bw6761/g2/curve.go index 4167674ef..8a8bf37e7 100644 --- a/wrappers/golang_v3/curves/bw6761/g2/curve.go +++ b/wrappers/golang_v3/curves/bw6761/g2/curve.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) type G2Projective struct { diff --git a/wrappers/golang_v3/curves/bw6761/g2/msm.go b/wrappers/golang_v3/curves/bw6761/g2/msm.go index 8a7a57cb0..7daae627d 100644 --- a/wrappers/golang_v3/curves/bw6761/g2/msm.go +++ b/wrappers/golang_v3/curves/bw6761/g2/msm.go @@ -5,9 +5,10 @@ package g2 import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func G2GetDefaultMSMConfig() core.MSMConfig { diff --git a/wrappers/golang_v3/curves/bw6761/msm/msm.go b/wrappers/golang_v3/curves/bw6761/msm/msm.go index 5fd9e0c76..8da18f78f 100644 --- a/wrappers/golang_v3/curves/bw6761/msm/msm.go +++ b/wrappers/golang_v3/curves/bw6761/msm/msm.go @@ -5,9 +5,10 @@ package msm import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultMSMConfig() core.MSMConfig { diff --git a/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go b/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go index 3ffe21ea2..aaa5c4bb2 100644 --- a/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go +++ b/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultPoseidonConfig() core.PoseidonConfig { diff --git a/wrappers/golang_v3/curves/bw6761/tests/curve_test.go b/wrappers/golang_v3/curves/bw6761/tests/curve_test.go index 0f90cf2d7..f862281ab 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/curve_test.go @@ -1,10 +1,11 @@ package tests import ( - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" "testing" + + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go b/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go index 0a90035c9..dcc89caff 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go @@ -3,10 +3,10 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ecntt" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/ntt" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go index e64a3ca45..9df68cb59 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go @@ -1,10 +1,11 @@ package tests import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/g2" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" "testing" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" ) func TestG2AffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go index 8a886d767..bfea6cee0 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark-crypto/ecc/bw6-761" + bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleBw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + icicleBw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/g2" ) func projectiveToGnarkAffineG2(p g2.G2Projective) bw6761.G2Affine { diff --git a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go index 4169eb250..f4099b88c 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark-crypto/ecc/bw6-761" + bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleBw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + icicleBw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/msm" ) func projectiveToGnarkAffine(p icicleBw6_761.Projective) bw6761.G1Affine { diff --git a/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go b/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go index b1ab540ca..ae47cdfdd 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go @@ -3,10 +3,10 @@ package tests import ( "testing" - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/poseidon" + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/poseidon" ) func TestPoseidon(t *testing.T) { diff --git a/wrappers/golang_v3/curves/grumpkin/curve.go b/wrappers/golang_v3/curves/grumpkin/curve.go index 653cbc8ed..677fd5fa5 100644 --- a/wrappers/golang_v3/curves/grumpkin/curve.go +++ b/wrappers/golang_v3/curves/grumpkin/curve.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) type Projective struct { diff --git a/wrappers/golang_v3/curves/grumpkin/msm/msm.go b/wrappers/golang_v3/curves/grumpkin/msm/msm.go index b0c4fa86b..48f20e1e5 100644 --- a/wrappers/golang_v3/curves/grumpkin/msm/msm.go +++ b/wrappers/golang_v3/curves/grumpkin/msm/msm.go @@ -5,9 +5,10 @@ package msm import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultMSMConfig() core.MSMConfig { diff --git a/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go b/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go index 037207530..d62b7dbf6 100644 --- a/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go +++ b/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultPoseidonConfig() core.PoseidonConfig { diff --git a/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go b/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go index 29c6c90d0..66b6b3d90 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go @@ -1,10 +1,11 @@ package tests import ( - grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" - "github.com/stretchr/testify/assert" "testing" + + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go index 2efd2e92f..506ad754c 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go @@ -7,10 +7,10 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - icicleGrumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + icicleGrumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin/msm" ) func TestMSM(t *testing.T) { diff --git a/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go b/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go index 92f9e5efe..ba5d187ed 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go @@ -3,10 +3,10 @@ package tests import ( "testing" - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin/poseidon" + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin/poseidon" ) func TestPoseidon(t *testing.T) { diff --git a/wrappers/golang_v3/hash/keccak/hasher.go b/wrappers/golang_v3/hash/keccak/hasher.go deleted file mode 100644 index 304342a8f..000000000 --- a/wrappers/golang_v3/hash/keccak/hasher.go +++ /dev/null @@ -1,88 +0,0 @@ -package keccak - -// #cgo CFLAGS: -I./include/ -// #include "keccak.h" -import "C" - -import ( - "fmt" - "unsafe" - - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" -) - -type HashSize int - -const ( - Hash256 HashSize = 256 - Hash512 HashSize = 512 -) - -type KeccakConfig struct { - Ctx cr.DeviceContext - areInputsOnDevice bool - areOutputsOnDevice bool - IsAsync bool -} - -func GetDefaultKeccakConfig() KeccakConfig { - ctx, _ := cr.GetDefaultDeviceContext() - return KeccakConfig{ - ctx, - false, - false, - false, - } -} - -func keccakCheck(input core.HostOrDeviceSlice, output core.HostOrDeviceSlice, cfg *KeccakConfig, hashSize HashSize, numberOfBlocks int32) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) { - cfg.areInputsOnDevice = input.IsOnDevice() - cfg.areOutputsOnDevice = output.IsOnDevice() - - if input.IsOnDevice() { - input.(core.DeviceSlice).CheckDevice() - } - - if output.IsOnDevice() { - output.(core.DeviceSlice).CheckDevice() - } - - if output.Cap() < int(hashSize)/8*int(numberOfBlocks) { - errorString := fmt.Sprintf( - "Output capacity %d isn't enough for hashSize %d and numberOfBlocks %d", - output.Cap(), - hashSize, - numberOfBlocks, - ) - panic(errorString) - } - - return input.AsUnsafePointer(), output.AsUnsafePointer(), unsafe.Pointer(cfg) -} - -func keccak(input core.HostOrDeviceSlice, inputBlockSize, numberOfBlocks int32, output core.HostOrDeviceSlice, config *KeccakConfig, hashSize HashSize) (ret core.IcicleError) { - inputPointer, outputPointer, cfgPointer := keccakCheck(input, output, config, hashSize, numberOfBlocks) - cInput := (*C.uint8_t)(inputPointer) - cOutput := (*C.uint8_t)(outputPointer) - cInputBlockSize := (C.int)(inputBlockSize) - cNumberOfBlocks := (C.int)(numberOfBlocks) - cConfig := (*C.KeccakConfig)(cfgPointer) - - switch hashSize { - case Hash256: - ret = core.FromCudaError((cr.CudaError)(C.keccak256_cuda(cInput, cInputBlockSize, cNumberOfBlocks, cOutput, cConfig))) - case Hash512: - ret = core.FromCudaError((cr.CudaError)(C.keccak512_cuda(cInput, cInputBlockSize, cNumberOfBlocks, cOutput, cConfig))) - } - - return ret -} - -func Keccak256(input core.HostOrDeviceSlice, inputBlockSize, numberOfBlocks int32, output core.HostOrDeviceSlice, config *KeccakConfig) core.IcicleError { - return keccak(input, inputBlockSize, numberOfBlocks, output, config, Hash256) -} - -func Keccak512(input core.HostOrDeviceSlice, inputBlockSize, numberOfBlocks int32, output core.HostOrDeviceSlice, config *KeccakConfig) core.IcicleError { - return keccak(input, inputBlockSize, numberOfBlocks, output, config, Hash512) -} diff --git a/wrappers/golang_v3/hash/keccak/include/keccak.h b/wrappers/golang_v3/hash/keccak/include/keccak.h deleted file mode 100644 index e2202e768..000000000 --- a/wrappers/golang_v3/hash/keccak/include/keccak.h +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -#ifndef _KECCAK_HASH_H -#define _KECCAK_HASH_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct KeccakConfig KeccakConfig; - -cudaError_t keccak256_cuda(uint8_t* input, int input_block_size, int number_of_blocks, uint8_t* output, KeccakConfig* config); -cudaError_t keccak512_cuda(uint8_t* input, int input_block_size, int number_of_blocks, uint8_t* output, KeccakConfig* config); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/wrappers/golang_v3/hash/keccak/main.go b/wrappers/golang_v3/hash/keccak/main.go deleted file mode 100644 index 2f342c8e3..000000000 --- a/wrappers/golang_v3/hash/keccak/main.go +++ /dev/null @@ -1,4 +0,0 @@ -package keccak - -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_hash -lstdc++ -lm -import "C" diff --git a/wrappers/golang_v3/hash/keccak/tests/hasher_test.go b/wrappers/golang_v3/hash/keccak/tests/hasher_test.go deleted file mode 100644 index 040715bed..000000000 --- a/wrappers/golang_v3/hash/keccak/tests/hasher_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package tests - -import ( - "encoding/hex" - "testing" - - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/hash/keccak" - - "github.com/stretchr/testify/assert" -) - -func createHostSliceFromHexString(hexString string) core.HostSlice[uint8] { - byteArray, err := hex.DecodeString(hexString) - if err != nil { - panic("Not a hex string") - } - return core.HostSliceFromElements([]uint8(byteArray)) -} - -func TestSimpleHash256(t *testing.T) { - input := createHostSliceFromHexString("1725b6679911bfe75ad7e248fbeec4a01034feace99aca43cd95d338a37db8d04b4aa5d83c8f8f5bdb8f7f98cec9a658f7f8061a6de07dcfd61db169cc7e666e1971adb4c7e97c43361c9a9eed8bb7b5c33cfe576a383a7440803996fd28148b") - outHost := make(core.HostSlice[uint8], 32) - - cfg := keccak.GetDefaultKeccakConfig() - e := keccak.Keccak256(input, int32(input.Len()), 1, outHost, &cfg) - assert.Equal(t, e.CudaErrorCode, cr.CudaSuccess, "Hashing failed") - t.Log(outHost) - assert.Equal(t, outHost, createHostSliceFromHexString("10fd4a3df6046e32f282cad3ac78e1566304339e7a6696826af023a55ab42048")) -} - -func TestBatchHash256(t *testing.T) { - input := createHostSliceFromHexString("1725b6679911bfe75ad7e248fbeec4a01034feace99aca43cd95d338a37db8d04b4aa5d83c8f8f5bdb8f7f98cec9a658f7f8061a6de07dcfd61db169cc7e666e1971adb4c7e97c43361c9a9eed8bb7b5c33cfe576a383a7440803996fd28148b") - outHost := make(core.HostSlice[uint8], 32*2) - - cfg := keccak.GetDefaultKeccakConfig() - e := keccak.Keccak256(input, int32(input.Len()/2), 2, outHost, &cfg) - assert.Equal(t, e.CudaErrorCode, cr.CudaSuccess, "Hashing failed") - t.Log(outHost) - assert.Equal(t, outHost[:32], createHostSliceFromHexString("7983fbc4cb4539cc90731205c44f74ca74e0a49ad1032a7a1429b1e443e66f45")) - assert.Equal(t, outHost[32:64], createHostSliceFromHexString("2952c2491c75338d28943231a492e9ab684a6820e4af1d74c8c1976759f7bf4b")) -} - -func TestSimpleHash512(t *testing.T) { - input := createHostSliceFromHexString("1725b6679911bfe75ad7e248fbeec4a01034feace99aca43cd95d338a37db8d04b4aa5d83c8f8f5bdb8f7f98cec9a658f7f8061a6de07dcfd61db169cc7e666e1971adb4c7e97c43361c9a9eed8bb7b5c33cfe576a383a7440803996fd28148b") - outHost := make(core.HostSlice[uint8], 64) - - cfg := keccak.GetDefaultKeccakConfig() - e := keccak.Keccak512(input, int32(input.Len()), 1, outHost, &cfg) - assert.Equal(t, e.CudaErrorCode, cr.CudaSuccess, "Hashing failed") - t.Log(outHost) - assert.Equal(t, outHost, createHostSliceFromHexString("1da4e0264dc755bc0b3a3318d2496e11c72322104693b68dbddfa66aa6e8b95526e95a7684a55ea831202f475f3d6a322ed86360d7e0e80f4a129f15d59dd403")) -} - -func TestBatchHash512(t *testing.T) { - input := createHostSliceFromHexString("1725b6679911bfe75ad7e248fbeec4a01034feace99aca43cd95d338a37db8d04b4aa5d83c8f8f5bdb8f7f98cec9a658f7f8061a6de07dcfd61db169cc7e666e1971adb4c7e97c43361c9a9eed8bb7b5c33cfe576a383a7440803996fd28148b") - outHost := make(core.HostSlice[uint8], 64*2) - - cfg := keccak.GetDefaultKeccakConfig() - e := keccak.Keccak512(input, int32(input.Len()/2), 2, outHost, &cfg) - assert.Equal(t, e.CudaErrorCode, cr.CudaSuccess, "Hashing failed") - t.Log(outHost) - assert.Equal(t, outHost[:64], createHostSliceFromHexString("709974f0dc1df1461fcbc2275e968fcb510c947d38837d577d661b6b40249c6b348e33092e4795faad7d2829403bd70fe860207f40a84a23e03c4610ca7927a9")) - assert.Equal(t, outHost[64:128], createHostSliceFromHexString("b8e46caa6cf7fbe6858deb28d4d9e58b768333b1260f5386656c0ae0d0850262bf6aa00293ef0979c37903fb5d2b784a02a4a227725a2b091df182abda03231d")) -} diff --git a/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl index e6bd59d55..22c5ce5ad 100644 --- a/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) {{end}} type {{.CurvePrefix}}Projective struct { diff --git a/wrappers/golang_v3/internal/generator/curves/templates/curve_test.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/curve_test.go.tmpl index 8a5cf3825..0b2ca3832 100644 --- a/wrappers/golang_v3/internal/generator/curves/templates/curve_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/curves/templates/curve_test.go.tmpl @@ -1,8 +1,8 @@ package tests import ( - {{if ne .CurvePrefix "G2"}}{{.Curve}}{{end}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers" + {{if ne .CurvePrefix "G2"}}{{.Curve}}{{end}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" "testing" ) diff --git a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl index 2e4e98d5e..cb02a7fc2 100644 --- a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl @@ -5,8 +5,8 @@ package ecntt import "C" import ( - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { diff --git a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl index ac9f96271..7cc06f08b 100644 --- a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl @@ -3,10 +3,10 @@ package tests import ( "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - {{.Curve}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" - ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ecntt" - ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + {{.Curve}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" + ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/ecntt" + ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/ntt" "github.com/stretchr/testify/assert" ) diff --git a/wrappers/golang_v3/internal/generator/generator_utils/generate.go b/wrappers/golang_v3/internal/generator/generator_utils/generate.go index 902fc9d36..0046ead86 100644 --- a/wrappers/golang_v3/internal/generator/generator_utils/generate.go +++ b/wrappers/golang_v3/internal/generator/generator_utils/generate.go @@ -13,7 +13,7 @@ import ( const ( // Since path.Join joins from the cwd we only need to go up two directories - // from wrappers/golang/internal/generator/main.go to get to wrappers/golang + // from wrappers/golang_v3/internal/generator/main.go to get to wrappers/golang GOLANG_WRAPPER_ROOT_DIR = "../../" ) diff --git a/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.go.tmpl b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.go.tmpl index ca83d4bbd..b2ce7a679 100644 --- a/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.go.tmpl +++ b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon.go.tmpl @@ -7,8 +7,8 @@ import "C" import ( "unsafe" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" ) func GetDefaultPoseidonConfig() core.PoseidonConfig { diff --git a/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon_test.go.tmpl b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon_test.go.tmpl index 13aeedc2e..e4c9c84eb 100644 --- a/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/poseidon/templates/poseidon_test.go.tmpl @@ -3,10 +3,10 @@ package tests import ( "testing" - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime" - {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/poseidon" + core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" + poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/poseidon" {{if eq .Field "bls12_381"}} "fmt" diff --git a/wrappers/golang_v3/runtime/device.go b/wrappers/golang_v3/runtime/device.go index 2a3f69d3b..f59fe0e05 100644 --- a/wrappers/golang_v3/runtime/device.go +++ b/wrappers/golang_v3/runtime/device.go @@ -7,7 +7,7 @@ const MAX_TYPE_SIZE = 64 type Device struct { DeviceType [MAX_TYPE_SIZE]C.char - Id C.int + Id int } type DeviceProperties struct { @@ -16,7 +16,7 @@ type DeviceProperties struct { SupportsPinnedMemory bool } -func CreateDevice(deviceType string, id int32) Device { +func CreateDevice(deviceType string, id int) Device { var cDeviceType [MAX_TYPE_SIZE]C.char for i, v := range deviceType { if i >= MAX_TYPE_SIZE { @@ -28,7 +28,7 @@ func CreateDevice(deviceType string, id int32) Device { if len(deviceType) >= MAX_TYPE_SIZE { cDeviceType[MAX_TYPE_SIZE-1] = C.char(0) } - return Device{DeviceType: cDeviceType, Id: C.int(id)} + return Device{DeviceType: cDeviceType, Id: id} } func (self *Device) GetDeviceType() string { diff --git a/wrappers/golang_v3/runtime/runtime.go b/wrappers/golang_v3/runtime/runtime.go index ed90f034b..580e2182d 100644 --- a/wrappers/golang_v3/runtime/runtime.go +++ b/wrappers/golang_v3/runtime/runtime.go @@ -5,6 +5,7 @@ package runtime import "C" import ( "os" + "runtime" "strings" "unsafe" ) @@ -114,3 +115,64 @@ func IsActiveDeviceMemory(ptr unsafe.Pointer) bool { cErr := C.icicle_is_active_device_memory(ptr) return EIcicleError(cErr) == Success } + +// RunOnDevice forces the provided function to run all GPU related calls within it +// on the same host thread and therefore the same GPU device. +// +// NOTE: Goroutines launched within funcToRun are not bound to the +// same host thread as funcToRun and therefore not to the same GPU device. +// If that is a requirement, RunOnDevice should be called for each with the +// same deviceId as the original call. +// +// As an example: +// +// cr.RunOnDevice(i, func(args ...any) { +// defer wg.Done() +// cfg := GetDefaultMSMConfig() +// stream, _ := cr.CreateStream() +// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { +// size := 1 << power + +// // This will always print "Inner goroutine device: 0" +// // go func () { +// // device, _ := cr.GetDevice() +// // fmt.Println("Inner goroutine device: ", device) +// // }() +// // To force the above goroutine to same device as the wrapping function: +// // RunOnDevice(i, func(arg ...any) { +// // device, _ := cr.GetDevice() +// // fmt.Println("Inner goroutine device: ", device) +// // }) + +// scalars := GenerateScalars(size) +// points := GenerateAffinePoints(size) + +// var p Projective +// var out core.DeviceSlice +// _, e := out.MallocAsync(p.Size(), p.Size(), stream) +// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") +// cfg.Ctx.Stream = &stream +// cfg.IsAsync = true + +// e = Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + +// outHost := make(core.HostSlice[Projective], 1) + +// cr.SynchronizeStream(&stream) +// outHost.CopyFromDevice(&out) +// out.Free() +// // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) +// } +// }, i) +func RunOnDevice(device *Device, funcToRun func(args ...any), args ...any) { + go func(id *Device) { + defer runtime.UnlockOSThread() + runtime.LockOSThread() + originalDevice, _ := GetActiveDevice() + SetDevice(id) + funcToRun(args...) + SetDevice(originalDevice) + }(device) +} From 572aa23caef88d5212dee32b06a1d1d15a574460 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Thu, 25 Jul 2024 07:24:19 +0000 Subject: [PATCH 20/38] bn254 tests pass --- icicle_v3/backend/cpu/src/curve/cpu_msm.cpp | 2 +- wrappers/golang_v3/core/msm.go | 84 +++++---- wrappers/golang_v3/core/msm_test.go | 32 ++-- wrappers/golang_v3/core/ntt.go | 3 + wrappers/golang_v3/curves/bn254/main.go | 1 - wrappers/golang_v3/curves/bn254/msm/msm.go | 19 +- .../curves/bn254/tests/ecntt_test.go | 7 +- .../golang_v3/curves/bn254/tests/main_test.go | 46 +++-- .../golang_v3/curves/bn254/tests/msm_test.go | 163 +++++++++-------- .../golang_v3/curves/bn254/tests/ntt_test.go | 37 ++-- wrappers/golang_v3/runtime/config.go | 5 +- wrappers/golang_v3/runtime/runtime.go | 1 - wrappers/rust_v3/icicle-core/src/msm/mod.rs | 18 +- wrappers/rust_v3/icicle-core/src/msm/tests.rs | 167 ++++++++++++++++++ 14 files changed, 416 insertions(+), 169 deletions(-) diff --git a/icicle_v3/backend/cpu/src/curve/cpu_msm.cpp b/icicle_v3/backend/cpu/src/curve/cpu_msm.cpp index 03c93d3bc..3b116d1f8 100644 --- a/icicle_v3/backend/cpu/src/curve/cpu_msm.cpp +++ b/icicle_v3/backend/cpu/src/curve/cpu_msm.cpp @@ -18,7 +18,7 @@ cpu_msm(const Device& device, const S* scalars, const A* bases, int msm_size, co const S* batch_scalars = scalars + msm_size * batch_idx; const A* batch_bases = config.are_bases_shared ? bases : bases + msm_size * batch_idx; for (auto i = 0; i < msm_size; ++i) { - res = res + P::from_affine(batch_bases[i]) * batch_scalars[i]; + res = res + P::from_affine(config.are_points_montgomery_form ? A::from_montgomery(batch_bases[i]) : batch_bases[i]) * (config.are_scalars_montgomery_form ? S::from_montgomery(batch_scalars[i]) : batch_scalars[i]); } results[batch_idx] = res; } diff --git a/wrappers/golang_v3/core/msm.go b/wrappers/golang_v3/core/msm.go index 882db708d..0c023d59d 100644 --- a/wrappers/golang_v3/core/msm.go +++ b/wrappers/golang_v3/core/msm.go @@ -9,8 +9,6 @@ import ( type MSMConfig struct { StreamHandle runtime.Stream - basesSize int32 - /// The number of extra bases to pre-compute for each point. See the `precompute_bases` function, `precompute_factor` passed /// there needs to be equal to the one used here. Larger values decrease the number of computations /// to make, on-line memory footprint, but increase the static memory footprint. Default value: 1 (i.e. don't pre-compute). @@ -28,7 +26,8 @@ type MSMConfig struct { /// (better) upper bound is known, it should be reflected in this variable. Default value: 0 (set to the bitsize of scalar field). Bitsize int32 - batchSize int32 + BatchSize int32 + AreBasesShared bool areScalarsOnDevice bool AreScalarsMontgomeryForm bool areBasesOnDevice bool @@ -44,28 +43,36 @@ type MSMConfig struct { func GetDefaultMSMConfig() MSMConfig { return MSMConfig{ - nil, // StreamHandle - 0, // basesSize - 1, // PrecomputeFactor - 0, // C - 0, // Bitsize - 1, // batchSize - false, // areScalarsOnDevice - false, // AreScalarsMontgomeryForm - false, // areBasesOnDevice - false, // AreBasesMontgomeryForm - false, // areResultsOnDevice - false, // IsAsync - nil, // Ext + StreamHandle: nil, + PrecomputeFactor: 1, + C: 0, + Bitsize: 0, + BatchSize: 1, + AreBasesShared: true, + areScalarsOnDevice: false, + AreScalarsMontgomeryForm: false, + areBasesOnDevice: false, + AreBasesMontgomeryForm: false, + areResultsOnDevice: false, + IsAsync: false, + Ext: nil, } } -func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfig, results HostOrDeviceSlice) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, int, unsafe.Pointer) { - scalarsLength, pointsLength, resultsLength := scalars.Len(), points.Len()/int(cfg.PrecomputeFactor), results.Len() - if scalarsLength%pointsLength != 0 { +func MsmCheck(scalars HostOrDeviceSlice, bases HostOrDeviceSlice, cfg *MSMConfig, results HostOrDeviceSlice) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, int) { + if bases.Len()%int(cfg.PrecomputeFactor) != 0 { + errorString := fmt.Sprintf( + "Precompute factor %d does not divide the number of bases %d", + cfg.PrecomputeFactor, + bases.Len(), + ) + panic(errorString) + } + scalarsLength, basesLength, resultsLength := scalars.Len(), bases.Len()/int(cfg.PrecomputeFactor), results.Len() + if scalarsLength%basesLength != 0 { errorString := fmt.Sprintf( - "Number of points %d does not divide the number of scalars %d", - pointsLength, + "Number of bases %d does not divide the number of scalars %d", + basesLength, scalarsLength, ) panic(errorString) @@ -79,18 +86,19 @@ func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfi panic(errorString) } - cfg.basesSize = int32(pointsLength) - cfg.batchSize = int32(resultsLength) + // cfg.basesSize = int32(basesLength) + cfg.AreBasesShared = basesLength < scalarsLength + cfg.BatchSize = int32(resultsLength) cfg.areScalarsOnDevice = scalars.IsOnDevice() - cfg.areBasesOnDevice = points.IsOnDevice() + cfg.areBasesOnDevice = bases.IsOnDevice() cfg.areResultsOnDevice = results.IsOnDevice() if scalars.IsOnDevice() { scalars.(DeviceSlice).CheckDevice() } - if points.IsOnDevice() { - points.(DeviceSlice).CheckDevice() + if bases.IsOnDevice() { + bases.(DeviceSlice).CheckDevice() } if results.IsOnDevice() { @@ -98,27 +106,29 @@ func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfi } size := scalars.Len() / results.Len() - return scalars.AsUnsafePointer(), points.AsUnsafePointer(), results.AsUnsafePointer(), size, unsafe.Pointer(cfg) + return scalars.AsUnsafePointer(), bases.AsUnsafePointer(), results.AsUnsafePointer(), size } -func PrecomputePointsCheck(points HostOrDeviceSlice, cfg *MSMConfig, outputBases DeviceSlice) (unsafe.Pointer, unsafe.Pointer) { - outputBasesLength, pointsLength := outputBases.Len(), points.Len() - if outputBasesLength != pointsLength*int(cfg.PrecomputeFactor) { +func PrecomputeBasesCheck(bases HostOrDeviceSlice, cfg *MSMConfig, outputBases DeviceSlice) (unsafe.Pointer, unsafe.Pointer) { + outputBasesLength, basesLength := outputBases.Len(), bases.Len() + if outputBasesLength != basesLength*int(cfg.PrecomputeFactor) { errorString := fmt.Sprintf( "Precompute factor is probably incorrect: expected %d but got %d", - outputBasesLength/pointsLength, + outputBasesLength/basesLength, cfg.PrecomputeFactor, ) panic(errorString) } - if points.IsOnDevice() { - points.(DeviceSlice).CheckDevice() + if bases.IsOnDevice() { + bases.(DeviceSlice).CheckDevice() } + outputBases.CheckDevice() - cfg.basesSize = int32(pointsLength) - cfg.areBasesOnDevice = points.IsOnDevice() - cfg.areResultsOnDevice = points.IsOnDevice() + // cfg.basesSize = int32(basesLength) + // cfg.areBasesShared = cfg.BatchSize > 1 + cfg.areBasesOnDevice = bases.IsOnDevice() + cfg.areResultsOnDevice = bases.IsOnDevice() - return points.AsUnsafePointer(), outputBases.AsUnsafePointer() + return bases.AsUnsafePointer(), outputBases.AsUnsafePointer() } diff --git a/wrappers/golang_v3/core/msm_test.go b/wrappers/golang_v3/core/msm_test.go index 881d4960c..a71b314a8 100644 --- a/wrappers/golang_v3/core/msm_test.go +++ b/wrappers/golang_v3/core/msm_test.go @@ -2,7 +2,6 @@ package core import ( "testing" - "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core/internal" "github.com/stretchr/testify/assert" @@ -11,21 +10,20 @@ import ( func TestMSMDefaultConfig(t *testing.T) { actual := GetDefaultMSMConfig() - stream := unsafe.Pointer(nil) expected := MSMConfig{ - stream, // Ctx - 0, // basesSize - 1, // PrecomputeFactor - 0, // C - 0, // Bitsize - 1, // batchSize - false, // areScalarsOnDevice - false, // AreScalarsMontgomeryForm - false, // areBasesOnDevice - false, // AreBasesMontgomeryForm - false, // areResultsOnDevice - false, // IsAsync - actual.Ext, // Ext + StreamHandle: nil, + PrecomputeFactor: 1, + C: 0, + Bitsize: 0, + BatchSize: 1, + AreBasesShared: true, + areScalarsOnDevice: false, + AreScalarsMontgomeryForm: false, + areBasesOnDevice: false, + AreBasesMontgomeryForm: false, + areResultsOnDevice: false, + IsAsync: false, + Ext: actual.Ext, } assert.EqualValues(t, expected, actual) @@ -58,7 +56,7 @@ func TestMSMCheckHostSlices(t *testing.T) { assert.False(t, cfg.areScalarsOnDevice) assert.False(t, cfg.areBasesOnDevice) assert.False(t, cfg.areResultsOnDevice) - assert.Equal(t, int32(1), cfg.batchSize) + assert.Equal(t, int32(1), cfg.BatchSize) output2 := make(HostSlice[internal.MockProjective], 3) assert.Panics(t, func() { MsmCheck(scalars, points, &cfg, output2) }) @@ -95,7 +93,7 @@ func TestMSMCheckDeviceSlices(t *testing.T) { assert.True(t, cfg.areScalarsOnDevice) assert.True(t, cfg.areBasesOnDevice) assert.False(t, cfg.areResultsOnDevice) - assert.Equal(t, int32(1), cfg.batchSize) + assert.Equal(t, int32(1), cfg.BatchSize) output2 := make(HostSlice[internal.MockProjective], 3) assert.Panics(t, func() { MsmCheck(scalarsOnDevice, pointsOnDevice, &cfg, output2) }) diff --git a/wrappers/golang_v3/core/ntt.go b/wrappers/golang_v3/core/ntt.go index 0105b9810..1e1157438 100644 --- a/wrappers/golang_v3/core/ntt.go +++ b/wrappers/golang_v3/core/ntt.go @@ -33,6 +33,9 @@ const ( MixedRadix ) +const CUDA_NTT_FAST_TWIDDLES_MODE = "fast_twiddles" +const CUDA_NTT_ALGORITHM = "ntt_algorithm" + type NTTConfig[T any] struct { /// Details related to the device such as its id and stream id. See [DeviceContext](@ref device_context::DeviceContext). StreamHandle runtime.Stream diff --git a/wrappers/golang_v3/curves/bn254/main.go b/wrappers/golang_v3/curves/bn254/main.go index 721fdf90a..92fc43dd3 100644 --- a/wrappers/golang_v3/curves/bn254/main.go +++ b/wrappers/golang_v3/curves/bn254/main.go @@ -1,5 +1,4 @@ package bn254 // #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bn254 -lingo_field_bn254 -lstdc++ -lm import "C" diff --git a/wrappers/golang_v3/curves/bn254/msm/msm.go b/wrappers/golang_v3/curves/bn254/msm/msm.go index a08e6ea73..4c90f1c53 100644 --- a/wrappers/golang_v3/curves/bn254/msm/msm.go +++ b/wrappers/golang_v3/curves/bn254/msm/msm.go @@ -16,13 +16,13 @@ func GetDefaultMSMConfig() core.MSMConfig { } func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.affine_t)(pointsPointer) cResults := (*C.projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) __ret := C.bn254_msm(cScalars, cPoints, cSize, cCfg, cResults) err := runtime.EIcicleError(__ret) @@ -50,15 +50,20 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor // return err // } -func PrecomputeBases(points core.HostOrDeviceSlice, size int, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.affine_t)(pointsPointer) - cSize := (C.int)(size) + cBases := (*C.affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.affine_t)(outputBasesPointer) - __ret := C.bn254_msm_precompute_bases(cPoints, cSize, cCfg, cOutputBases) + __ret := C.bn254_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go index b4cca0042..28dbf2920 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go @@ -13,18 +13,21 @@ import ( func TestECNtt(t *testing.T) { cfg := ntt.GetDefaultNttConfig() + ext := runtime.CreateConfigExtension() + ext.SetInt(core.CUDA_NTT_ALGORITHM, int(core.Radix2)) + cfg.Ext = ext.AsUnsafePointer() + points := bn254.GenerateProjectivePoints(1 << largestTestSize) for _, size := range []int{4, 5, 6, 7, 8} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { - runtime.SetDevice(&MAIN_DEVICE) + runtime.SetDevice(&DEVICE) testSize := 1 << size pointsCopy := core.HostSliceFromElements[bn254.Projective](points[:testSize]) cfg.Ordering = v - // cfg. = core.Radix2 output := make(core.HostSlice[bn254.Projective], testSize) e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) diff --git a/wrappers/golang_v3/curves/bn254/tests/main_test.go b/wrappers/golang_v3/curves/bn254/tests/main_test.go index 40763bac5..7df490853 100644 --- a/wrappers/golang_v3/curves/bn254/tests/main_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/main_test.go @@ -1,7 +1,7 @@ package tests import ( - "os" + "fmt" "testing" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" @@ -13,10 +13,10 @@ import ( ) const ( - largestTestSize = 5 + largestTestSize = 20 ) -var MAIN_DEVICE runtime.Device +var DEVICE runtime.Device func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) @@ -31,22 +31,36 @@ func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcic func TestMain(m *testing.M) { runtime.LoadBackendFromEnv() - MAIN_DEVICE = runtime.CreateDevice("CUDA", 0) - runtime.SetDevice(&MAIN_DEVICE) - - // setup domain - cfg := core.GetDefaultNTTInitDomainConfig() - e := initDomain(largestTestSize, cfg) + devices, e := runtime.GetRegisteredDevices() if e != runtime.Success { - panic("initDomain failed") + panic("Failed to load registered devices") } + for _, deviceType := range devices { + DEVICE = runtime.CreateDevice(deviceType, 0) + runtime.SetDevice(&DEVICE) - // execute tests - os.Exit(m.Run()) + // setup domain + cfg := core.GetDefaultNTTInitDomainConfig() + e = initDomain(largestTestSize, cfg) + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("initDomain is not implemented for ", deviceType, " device type") + } else { + panic("initDomain failed") + } + } - // release domain - e = ntt.ReleaseDomain() - if e != runtime.Success { - panic("ReleaseDomain failed") + // execute tests + m.Run() + + // release domain + e = ntt.ReleaseDomain() + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("ReleaseDomain is not implemented for ", deviceType, " device type") + } else { + panic("ReleaseDomain failed") + } + } } } diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index 89191f602..21d252c8c 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -16,10 +16,6 @@ import ( icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/msm" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" - - coreV2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v2/core" - crV2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v2/cuda_runtime" - msmV2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v2/curves/bn254/msm" ) func projectiveToGnarkAffine(p icicleBn254.Projective) bn254.G1Affine { @@ -87,17 +83,19 @@ func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 10} { - runtime.SetDevice(&MAIN_DEVICE) + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicleBn254.GenerateScalars(size) points := icicleBn254.GenerateAffinePoints(size) stream, _ := runtime.CreateStream() + defer runtime.DestroyStream(stream) var p icicleBn254.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) @@ -166,7 +164,7 @@ func TestMSM(t *testing.T) { func TestMSMGnarkCryptoTypes(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{3} { - runtime.SetDevice(&MAIN_DEVICE) + runtime.SetDevice(&DEVICE) size := 1 << power scalars := make([]fr.Element, size) @@ -189,23 +187,11 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { e = msm.Msm(scalarsHost, pointsHost, &cfg, out) assert.Equal(t, e, runtime.Success, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBn254.Projective], 1) outHost.CopyFromDevice(&out) out.Free() - cfgV2 := coreV2.GetDefaultMSMConfig() - cfgV2.ArePointsMontgomeryForm = true - cfgV2.AreScalarsMontgomeryForm = true - - scalarsHostV2 := (coreV2.HostSlice[fr.Element])(scalars) - pointsHostV2 := (coreV2.HostSlice[bn254.G1Affine])(pointsGnark) - - outHostV2 := make(coreV2.HostSlice[icicleBn254.Projective], 1) - - eV2 := msmV2.Msm(scalarsHostV2, pointsHostV2, &cfgV2, outHostV2) - assert.Equal(t, crV2.CudaSuccess, eV2) - - testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, (core.HostSlice[fr.Element])(scalarsHostV2), (core.HostSlice[bn254.G1Affine])(pointsHostV2), outHostV2[0]) // Check with gnark-crypto testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } @@ -215,7 +201,7 @@ func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{5} { for _, batchSize := range []int{1, 3} { - runtime.SetDevice(&MAIN_DEVICE) + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicleBn254.GenerateScalars(totalSize) @@ -247,9 +233,9 @@ func TestPrecomputePoints(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3} { - runtime.SetDevice(&MAIN_DEVICE) + for _, power := range []int{10} { + for _, batchSize := range []int{1, 3, 5, 16} { + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -260,7 +246,9 @@ func TestPrecomputePoints(t *testing.T) { _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = msm.PrecomputeBases(points, size, &cfg, precomputeOut) + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = msm.PrecomputeBases(points, &cfg, precomputeOut) assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p icicleBn254.Projective @@ -284,11 +272,53 @@ func TestPrecomputePoints(t *testing.T) { } } } +func TestPrecomputePointsSharedBases(t *testing.T) { + cfg := core.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10} { + for _, batchSize := range []int{1, 3, 5, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := icicleBn254.GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p icicleBn254.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0:size] + out := outHost[i] + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) + } + } + } +} func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { - runtime.SetDevice(&MAIN_DEVICE) + runtime.SetDevice(&DEVICE) size := 1 << power @@ -317,51 +347,44 @@ func TestMSMSkewedDistribution(t *testing.T) { } func TestMSMMultiDevice(t *testing.T) { - deviceTypes, _ := runtime.GetRegisteredDevices() - for _, deviceType := range deviceTypes { - device := runtime.CreateDevice(deviceType, 0) - runtime.SetDevice(&device) - runtime.GetDeviceCount() - - numDevices, _ := runtime.GetDeviceCount() - fmt.Println("There are ", numDevices, " ", deviceType, " devices available") - wg := sync.WaitGroup{} - - for i := 0; i < numDevices; i++ { - currentDevice := runtime.Device{DeviceType: device.DeviceType, Id: i} - wg.Add(1) - runtime.RunOnDevice(¤tDevice, func(args ...any) { - defer wg.Done() - - fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") - - cfg := msm.GetDefaultMSMConfig() - cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5} { - size := 1 << power - scalars := icicleBn254.GenerateScalars(size) - points := icicleBn254.GenerateAffinePoints(size) - - stream, _ := runtime.CreateStream() - var p icicleBn254.Projective - var out core.DeviceSlice - _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") - cfg.StreamHandle = stream - - e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, runtime.Success, "Msm failed") - outHost := make(core.HostSlice[icicleBn254.Projective], 1) - outHost.CopyFromDeviceAsync(&out, stream) - out.FreeAsync(stream) - - runtime.SynchronizeStream(stream) - // Check with gnark-crypto - testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) - } - }) - } - wg.Wait() + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: i} + wg.Add(1) + runtime.RunOnDevice(¤tDevice, func(args ...any) { + defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + + cfg := msm.GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5} { + size := 1 << power + scalars := icicleBn254.GenerateScalars(size) + points := icicleBn254.GenerateAffinePoints(size) + + stream, _ := runtime.CreateStream() + var p icicleBn254.Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream + + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, runtime.Success, "Msm failed") + outHost := make(core.HostSlice[icicleBn254.Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + runtime.SynchronizeStream(stream) + // Check with gnark-crypto + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) + } + }) } + wg.Wait() } diff --git a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go index c053f119c..6f226d254 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go @@ -73,16 +73,12 @@ func TestInitDomain(t *testing.T) { } func TestNtt(t *testing.T) { - runtime.LoadBackendFromEnv() - device := runtime.CreateDevice("CUDA", 0) - cfg := ntt.GetDefaultNttConfig() scalars := bn254.GenerateScalars(1 << largestTestSize) for _, size := range []int{4, 8} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { - - runtime.SetDevice(&device) + runtime.SetDevice(&DEVICE) testSize := 1 << size @@ -92,6 +88,9 @@ func TestNtt(t *testing.T) { // run ntt output := make(core.HostSlice[bn254.ScalarField], testSize) err := ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + if err == runtime.ApiNotImplemented { + t.Skipf("NTT is not implemented for %s device type. Skipping test", DEVICE.GetDeviceType()) + } assert.Equal(t, runtime.Success, err) // Compare with gnark-crypto @@ -110,7 +109,7 @@ func TestNttFrElement(t *testing.T) { for _, size := range []int{4} { for _, v := range [1]core.Ordering{core.KNN} { - runtime.SetDevice(&MAIN_DEVICE) + runtime.SetDevice(&DEVICE) testSize := size @@ -119,7 +118,11 @@ func TestNttFrElement(t *testing.T) { // run ntt output := make(core.HostSlice[fr.Element], testSize) - ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + err := ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + if err == runtime.ApiNotImplemented { + t.Skipf("NTT is not implemented for %s device type. Skipping test", DEVICE.GetDeviceType()) + } + assert.Equal(t, runtime.Success, err) // Compare with gnark-crypto testAgainstGnarkCryptoNttGnarkTypes(t, testSize, scalarsCopy, output, v, core.KForward) @@ -134,30 +137,38 @@ func TestNttDeviceAsync(t *testing.T) { for _, size := range []int{1, 10, largestTestSize} { for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { - runtime.SetDevice(&MAIN_DEVICE) + runtime.SetDevice(&DEVICE) testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bn254.ScalarField](scalars[:testSize]) stream, _ := runtime.CreateStream() + defer runtime.DestroyStream(stream) cfg.Ordering = v cfg.IsAsync = true cfg.StreamHandle = stream var deviceInput core.DeviceSlice + defer deviceInput.FreeAsync(stream) scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) var deviceOutput core.DeviceSlice + defer deviceOutput.FreeAsync(stream) deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) // run ntt - ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + err := ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) + if err == runtime.ApiNotImplemented { + t.Skipf("NTT is not implemented for %s device type. Skipping test", DEVICE.GetDeviceType()) + } + assert.Equal(t, runtime.Success, err) output := make(core.HostSlice[bn254.ScalarField], testSize) output.CopyFromDeviceAsync(&deviceOutput, stream) runtime.SynchronizeStream(stream) // Compare with gnark-crypto testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, direction) + } } } @@ -171,7 +182,7 @@ func TestNttBatch(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, batchSize := range []int{2, 16, largestBatchSize} { - runtime.SetDevice(&MAIN_DEVICE) + runtime.SetDevice(&DEVICE) testSize := 1 << size totalSize := testSize * batchSize @@ -182,7 +193,11 @@ func TestNttBatch(t *testing.T) { cfg.BatchSize = int32(batchSize) // run ntt output := make(core.HostSlice[bn254.ScalarField], totalSize) - ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + err := ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) + if err == runtime.ApiNotImplemented { + t.Skip("NTT is not implemented for ", DEVICE.GetDeviceType(), " device type. Skipping test") + } + assert.Equal(t, runtime.Success, err) // Compare with gnark-crypto domainWithPrecompute := fft.NewDomain(uint64(testSize)) diff --git a/wrappers/golang_v3/runtime/config.go b/wrappers/golang_v3/runtime/config.go index 0890381fd..b4ee38226 100644 --- a/wrappers/golang_v3/runtime/config.go +++ b/wrappers/golang_v3/runtime/config.go @@ -4,7 +4,6 @@ package runtime // #include "config_extension.h" import "C" import ( - "runtime" "unsafe" ) @@ -16,7 +15,7 @@ type ConfigExtension struct { func CreateConfigExtension() *ConfigExtension { ext := &ConfigExtension{handler: C.create_config_extension()} - runtime.SetFinalizer(ext, Delete) + // runtime.SetFinalizer(ext, Delete) return ext } @@ -46,6 +45,6 @@ func (ext *ConfigExtension) GetBool(key string) bool { return C.config_extension_get_bool(ext.handler, cKey) == C._Bool(true) } -func (ext *ConfigExtension) AsUnsafePointer() unsafe.Pointer { +func (ext ConfigExtension) AsUnsafePointer() unsafe.Pointer { return ext.handler } diff --git a/wrappers/golang_v3/runtime/runtime.go b/wrappers/golang_v3/runtime/runtime.go index 580e2182d..a0a7e04a1 100644 --- a/wrappers/golang_v3/runtime/runtime.go +++ b/wrappers/golang_v3/runtime/runtime.go @@ -19,7 +19,6 @@ func LoadBackend(path string, isRecursive bool) EIcicleError { func LoadBackendFromEnv() EIcicleError { path := os.Getenv("DEFAULT_BACKEND_INSTALL_DIR") - path = "/home/administrator/users/Timur/Projects/icicle/icicle_v3/build" return LoadBackend(path, true) } diff --git a/wrappers/rust_v3/icicle-core/src/msm/mod.rs b/wrappers/rust_v3/icicle-core/src/msm/mod.rs index 86833ab6d..ea7af722c 100644 --- a/wrappers/rust_v3/icicle-core/src/msm/mod.rs +++ b/wrappers/rust_v3/icicle-core/src/msm/mod.rs @@ -32,8 +32,8 @@ pub struct MSMConfig { /// (better) upper bound is known, it should be reflected in this variable. Default value: 0 (set to the bitsize of scalar field). pub bitsize: i32, - batch_size: i32, - are_bases_shared: bool, /// MSMs in batch share the bases. If false, expecting #bases==#scalars + pub batch_size: i32, + pub are_bases_shared: bool, /// MSMs in batch share the bases. If false, expecting #bases==#scalars are_scalars_on_device: bool, pub are_scalars_montgomery_form: bool, are_bases_on_device: bool, @@ -246,7 +246,7 @@ macro_rules! impl_msm { unsafe { $curve_prefix_ident::precompute_bases_ffi( points.as_ptr(), - points.len() as i32, + points.len() as i32 / config.batch_size, config, output_bases.as_mut_ptr(), ) @@ -280,6 +280,18 @@ macro_rules! impl_msm_tests { check_msm_batch::<$curve>() } + #[test] + fn test_msm_batch_shared() { + initialize(); + check_msm_batch_shared::<$curve>() + } + + #[test] + fn test_msm_batch_not_shared() { + initialize(); + check_msm_batch_not_shared::<$curve>() + } + #[test] fn test_msm_skewed_distributions() { initialize(); diff --git a/wrappers/rust_v3/icicle-core/src/msm/tests.rs b/wrappers/rust_v3/icicle-core/src/msm/tests.rs index 136bce5b0..f0ca66e01 100644 --- a/wrappers/rust_v3/icicle-core/src/msm/tests.rs +++ b/wrappers/rust_v3/icicle-core/src/msm/tests.rs @@ -7,6 +7,7 @@ use icicle_runtime::{ runtime, stream::IcicleStream, }; +use icicle_runtime::memory::HostOrDeviceSlice; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rand::thread_rng; @@ -178,6 +179,172 @@ where .unwrap(); } +pub fn check_msm_batch_shared>() +where +::Config: GenerateRandom, +{ + // let test_sizes = [1000, 1 << 16]; //TODO - uncomment this line after implementing fast msm + let test_sizes = [100]; + // let batch_sizes = [1, 3, 1 << 4]; + let batch_sizes = [1, 3]; //TODO - uncomment this line after implementing fast msm + let mut stream = IcicleStream::create().unwrap(); + let precompute_factor = 8; + let mut cfg = MSMConfig::default(); + cfg.stream_handle = *stream; + cfg.is_async = true; + cfg.ext + .set_int(LARGE_BUCKET_FACTOR, 5); + cfg.c = 4; + runtime::warmup(&stream).unwrap(); + stream + .synchronize() + .unwrap(); + for test_size in test_sizes { + // (1) compute MSM with and w/o precompute on main device + test_utilities::test_set_main_device(); + cfg.precompute_factor = precompute_factor; + let points = generate_random_affine_points_with_zeroes::(test_size, 10); + let mut precomputed_points_d = + DeviceVec::>::device_malloc(cfg.precompute_factor as usize * test_size).unwrap(); + precompute_bases(HostSlice::from_slice(&points), &cfg, &mut precomputed_points_d).unwrap(); + for batch_size in batch_sizes { + let scalars = ::Config::generate_random(test_size * batch_size); + // a version of batched msm without using `cfg.points_size`, requires copying bases + // let points_cloned: Vec> = std::iter::repeat(points.clone()) + // .take(batch_size) + // .flatten() + // .collect(); + let scalars_h = HostSlice::from_slice(&scalars); + + let mut msm_results_1 = DeviceVec::>::device_malloc(batch_size).unwrap(); + let mut msm_results_2 = DeviceVec::>::device_malloc(batch_size).unwrap(); + let mut points_d = DeviceVec::>::device_malloc(test_size).unwrap(); + points_d + .copy_from_host_async(HostSlice::from_slice(&points), &stream) + .unwrap(); + + cfg.precompute_factor = precompute_factor; + msm(scalars_h, &precomputed_points_d[..], &cfg, &mut msm_results_1[..]).unwrap(); + cfg.precompute_factor = 1; + msm(scalars_h, &points_d[..], &cfg, &mut msm_results_2[..]).unwrap(); + + let mut msm_host_result_1 = vec![Projective::::zero(); batch_size]; + let mut msm_host_result_2 = vec![Projective::::zero(); batch_size]; + msm_results_1 + .copy_to_host_async(HostSlice::from_mut_slice(&mut msm_host_result_1), &stream) + .unwrap(); + msm_results_2 + .copy_to_host_async(HostSlice::from_mut_slice(&mut msm_host_result_2), &stream) + .unwrap(); + stream + .synchronize() + .unwrap(); + + // (2) compute on ref device and compare to both cases (with or w/o precompute) + test_utilities::test_set_ref_device(); + let mut msm_ref_result = vec![Projective::::zero(); batch_size]; + let mut ref_msm_config = MSMConfig::default(); + ref_msm_config.c = 4; + msm( + scalars_h, + HostSlice::from_slice(&points), + &MSMConfig::default(), + HostSlice::from_mut_slice(&mut msm_ref_result), + ) + .unwrap(); + + assert_eq!(msm_host_result_1, msm_ref_result); + assert_eq!(msm_host_result_2, msm_ref_result); + } + } + stream + .destroy() + .unwrap(); +} + +pub fn check_msm_batch_not_shared>() +where +::Config: GenerateRandom, +{ + // let test_sizes = [1000, 1 << 16]; //TODO - uncomment this line after implementing fast msm + let test_sizes = [100]; + // let batch_sizes = [1, 3, 1 << 4]; + let batch_sizes = [3, 5]; //TODO - uncomment this line after implementing fast msm + let mut stream = IcicleStream::create().unwrap(); + let precompute_factor = 8; + let mut cfg = MSMConfig::default(); + cfg.stream_handle = *stream; + cfg.is_async = true; + cfg.ext + .set_int(LARGE_BUCKET_FACTOR, 5); + cfg.c = 4; + runtime::warmup(&stream).unwrap(); + stream + .synchronize() + .unwrap(); + for test_size in test_sizes { + // (1) compute MSM with and w/o precompute on main device + test_utilities::test_set_main_device(); + for batch_size in batch_sizes { + cfg.precompute_factor = precompute_factor; + let scalars = ::Config::generate_random(test_size * batch_size); + let scalars_h = HostSlice::from_slice(&scalars); + + let points = generate_random_affine_points_with_zeroes::(test_size * batch_size, 10); + println!("points len: {}", points.len()); + let mut precomputed_points_d = + DeviceVec::>::device_malloc(cfg.precompute_factor as usize * test_size * batch_size).unwrap(); + cfg.batch_size = batch_size as i32; + cfg.are_bases_shared = false; + precompute_bases(HostSlice::from_slice(&points), &cfg, &mut precomputed_points_d).unwrap(); + println!("precomputed points len: {}", (precomputed_points_d).len()); + + let mut msm_results_1 = DeviceVec::>::device_malloc(batch_size).unwrap(); + let mut msm_results_2 = DeviceVec::>::device_malloc(batch_size).unwrap(); + let mut points_d = DeviceVec::>::device_malloc(test_size * batch_size).unwrap(); + points_d + .copy_from_host_async(HostSlice::from_slice(&points), &stream) + .unwrap(); + + cfg.precompute_factor = precompute_factor; + msm(scalars_h, &precomputed_points_d[..], &cfg, &mut msm_results_1[..]).unwrap(); + cfg.precompute_factor = 1; + msm(scalars_h, &points_d[..], &cfg, &mut msm_results_2[..]).unwrap(); + + let mut msm_host_result_1 = vec![Projective::::zero(); batch_size]; + let mut msm_host_result_2 = vec![Projective::::zero(); batch_size]; + msm_results_1 + .copy_to_host_async(HostSlice::from_mut_slice(&mut msm_host_result_1), &stream) + .unwrap(); + msm_results_2 + .copy_to_host_async(HostSlice::from_mut_slice(&mut msm_host_result_2), &stream) + .unwrap(); + stream + .synchronize() + .unwrap(); + + // (2) compute on ref device and compare to both cases (with or w/o precompute) + test_utilities::test_set_ref_device(); + let mut msm_ref_result = vec![Projective::::zero(); batch_size]; + let mut ref_msm_config = MSMConfig::default(); + ref_msm_config.c = 4; + msm( + scalars_h, + HostSlice::from_slice(&points), + &MSMConfig::default(), + HostSlice::from_mut_slice(&mut msm_ref_result), + ) + .unwrap(); + + assert_eq!(msm_host_result_1, msm_ref_result); + assert_eq!(msm_host_result_2, msm_ref_result); + } + } + stream + .destroy() + .unwrap(); +} + pub fn check_msm_skewed_distributions>() where ::Config: GenerateRandom, From 43dc99d26bf0fe220fa6333632ca56a04eb3be33 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Thu, 25 Jul 2024 15:59:26 +0000 Subject: [PATCH 21/38] test generators --- wrappers/golang_v3/core/vec_ops_test.go | 8 +- wrappers/golang_v3/curves/bls12377/curve.go | 36 +- .../golang_v3/curves/bls12377/ecntt/ecntt.go | 10 +- .../curves/bls12377/ecntt/include/ecntt.h | 2 +- .../golang_v3/curves/bls12377/g2/curve.go | 36 +- .../curves/bls12377/g2/include/curve.h | 7 +- .../curves/bls12377/g2/include/msm.h | 7 +- wrappers/golang_v3/curves/bls12377/g2/msm.go | 50 +- .../golang_v3/curves/bls12377/include/curve.h | 7 +- wrappers/golang_v3/curves/bls12377/main.go | 2 +- .../curves/bls12377/msm/include/msm.h | 7 +- wrappers/golang_v3/curves/bls12377/msm/msm.go | 50 +- .../bls12377/poseidon/include/poseidon.h | 25 - .../curves/bls12377/poseidon/poseidon.go | 57 -- .../curves/bls12377/tests/curve_test.go | 3 +- .../curves/bls12377/tests/ecntt_test.go | 10 +- .../curves/bls12377/tests/g2_curve_test.go | 3 +- .../curves/bls12377/tests/g2_msm_test.go | 241 ++++-- .../curves/bls12377/tests/main_test.go | 44 +- .../curves/bls12377/tests/msm_test.go | 241 ++++-- .../curves/bls12377/tests/ntt_test.go | 22 +- .../curves/bls12377/tests/poseidon_test.go | 42 - wrappers/golang_v3/curves/bls12381/curve.go | 36 +- .../golang_v3/curves/bls12381/ecntt/ecntt.go | 10 +- .../curves/bls12381/ecntt/include/ecntt.h | 2 +- .../golang_v3/curves/bls12381/g2/curve.go | 36 +- .../curves/bls12381/g2/include/curve.h | 7 +- .../curves/bls12381/g2/include/msm.h | 7 +- wrappers/golang_v3/curves/bls12381/g2/msm.go | 50 +- .../golang_v3/curves/bls12381/include/curve.h | 7 +- wrappers/golang_v3/curves/bls12381/main.go | 2 +- .../curves/bls12381/msm/include/msm.h | 7 +- wrappers/golang_v3/curves/bls12381/msm/msm.go | 50 +- .../bls12381/poseidon/include/poseidon.h | 25 - .../curves/bls12381/poseidon/poseidon.go | 57 -- .../curves/bls12381/tests/curve_test.go | 3 +- .../curves/bls12381/tests/ecntt_test.go | 10 +- .../curves/bls12381/tests/g2_curve_test.go | 3 +- .../curves/bls12381/tests/g2_msm_test.go | 241 ++++-- .../curves/bls12381/tests/main_test.go | 44 +- .../curves/bls12381/tests/msm_test.go | 241 ++++-- .../curves/bls12381/tests/ntt_test.go | 22 +- .../curves/bls12381/tests/poseidon_test.go | 56 -- .../golang_v3/curves/bn254/ecntt/ecntt.go | 6 +- wrappers/golang_v3/curves/bn254/g2/curve.go | 340 ++++---- .../golang_v3/curves/bn254/g2/g2base_field.go | 164 ++-- .../golang_v3/curves/bn254/g2/include/curve.h | 7 +- .../golang_v3/curves/bn254/g2/include/msm.h | 7 +- wrappers/golang_v3/curves/bn254/g2/msm.go | 107 +-- .../golang_v3/curves/bn254/include/curve.h | 5 +- .../golang_v3/curves/bn254/msm/include/msm.h | 4 +- wrappers/golang_v3/curves/bn254/msm/msm.go | 21 - .../curves/bn254/tests/curve_test.go | 3 +- .../curves/bn254/tests/ecntt_test.go | 1 - .../curves/bn254/tests/g2_curve_test.go | 202 ++--- .../bn254/tests/g2_g2base_field_test.go | 172 ++-- .../curves/bn254/tests/g2_msm_test.go | 795 ++++++++++-------- .../golang_v3/curves/bn254/tests/msm_test.go | 118 ++- .../golang_v3/curves/bn254/tests/ntt_test.go | 33 +- wrappers/golang_v3/curves/bw6761/curve.go | 36 +- .../golang_v3/curves/bw6761/ecntt/ecntt.go | 10 +- .../curves/bw6761/ecntt/include/ecntt.h | 2 +- wrappers/golang_v3/curves/bw6761/g2/curve.go | 36 +- .../curves/bw6761/g2/include/curve.h | 7 +- .../golang_v3/curves/bw6761/g2/include/msm.h | 7 +- wrappers/golang_v3/curves/bw6761/g2/msm.go | 50 +- .../golang_v3/curves/bw6761/include/curve.h | 7 +- wrappers/golang_v3/curves/bw6761/main.go | 2 +- .../golang_v3/curves/bw6761/msm/include/msm.h | 7 +- wrappers/golang_v3/curves/bw6761/msm/msm.go | 50 +- .../curves/bw6761/poseidon/include/poseidon.h | 25 - .../curves/bw6761/poseidon/poseidon.go | 57 -- .../curves/bw6761/tests/curve_test.go | 3 +- .../curves/bw6761/tests/ecntt_test.go | 10 +- .../curves/bw6761/tests/g2_curve_test.go | 3 +- .../curves/bw6761/tests/g2_msm_test.go | 241 ++++-- .../curves/bw6761/tests/main_test.go | 44 +- .../golang_v3/curves/bw6761/tests/msm_test.go | 241 ++++-- .../golang_v3/curves/bw6761/tests/ntt_test.go | 22 +- .../curves/bw6761/tests/poseidon_test.go | 42 - wrappers/golang_v3/curves/grumpkin/curve.go | 36 +- .../golang_v3/curves/grumpkin/include/curve.h | 7 +- wrappers/golang_v3/curves/grumpkin/main.go | 2 +- .../curves/grumpkin/msm/include/msm.h | 7 +- wrappers/golang_v3/curves/grumpkin/msm/msm.go | 50 +- .../grumpkin/poseidon/include/poseidon.h | 25 - .../curves/grumpkin/poseidon/poseidon.go | 57 -- .../curves/grumpkin/tests/curve_test.go | 3 +- .../curves/grumpkin/tests/main_test.go | 17 +- .../curves/grumpkin/tests/msm_test.go | 184 ++-- .../curves/grumpkin/tests/poseidon_test.go | 42 - .../fields/babybear/tests/main_test.go | 48 +- .../fields/babybear/tests/ntt_test.go | 6 + .../generator/curves/templates/curve.go.tmpl | 36 +- .../generator/curves/templates/curve.h.tmpl | 7 +- .../generator/curves/templates/main.go.tmpl | 2 +- .../generator/ecntt/templates/ecntt.go.tmpl | 10 +- .../generator/ecntt/templates/ecntt.h.tmpl | 2 +- .../ecntt/templates/ecntt_test.go.tmpl | 10 +- wrappers/golang_v3/internal/generator/main.go | 2 +- .../generator/msm/templates/msm.go.tmpl | 40 +- .../generator/msm/templates/msm.h.tmpl | 4 +- .../generator/msm/templates/msm_test.go.tmpl | 131 ++- .../generator/ntt/templates/ntt_test.go.tmpl | 22 +- .../tests/templates/main_test.go.tmpl | 52 +- wrappers/golang_v3/runtime/device.go | 4 +- 106 files changed, 2689 insertions(+), 2830 deletions(-) delete mode 100644 wrappers/golang_v3/curves/bls12377/poseidon/include/poseidon.h delete mode 100644 wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go delete mode 100644 wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go delete mode 100644 wrappers/golang_v3/curves/bls12381/poseidon/include/poseidon.h delete mode 100644 wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go delete mode 100644 wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go delete mode 100644 wrappers/golang_v3/curves/bw6761/poseidon/include/poseidon.h delete mode 100644 wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go delete mode 100644 wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go delete mode 100644 wrappers/golang_v3/curves/grumpkin/poseidon/include/poseidon.h delete mode 100644 wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go delete mode 100644 wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go diff --git a/wrappers/golang_v3/core/vec_ops_test.go b/wrappers/golang_v3/core/vec_ops_test.go index 1abee4894..e7dec49a2 100644 --- a/wrappers/golang_v3/core/vec_ops_test.go +++ b/wrappers/golang_v3/core/vec_ops_test.go @@ -10,10 +10,10 @@ func TestVecOpsDefaultConfig(t *testing.T) { actual := DefaultVecOpsConfig() expected := VecOpsConfig{ actual.StreamHandle, // Ctx - true, // isAOnDevice - true, // isBOnDevice - true, // isResultOnDevice - true, // IsAsync + false, // isAOnDevice + false, // isBOnDevice + false, // isResultOnDevice + false, // IsAsync actual.Ext, // Ext } diff --git a/wrappers/golang_v3/curves/bls12377/curve.go b/wrappers/golang_v3/curves/bls12377/curve.go index 4b08ed1eb..50a0346f2 100644 --- a/wrappers/golang_v3/curves/bls12377/curve.go +++ b/wrappers/golang_v3/curves/bls12377/curve.go @@ -8,7 +8,7 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) type Projective struct { @@ -134,44 +134,38 @@ func GenerateAffinePoints(size int) core.HostSlice[Affine] { return pointsSlice } -func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_377_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bls12_377_affine_convert_montgomery((*C.affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, true) } -func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, false) } -func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_377_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bls12_377_projective_convert_montgomery((*C.projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, true) } -func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go b/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go index 4bf130b51..d00e29702 100644 --- a/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go +++ b/wrappers/golang_v3/curves/bls12377/ecntt/ecntt.go @@ -6,10 +6,10 @@ import "C" import ( "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) cPoints := (*C.projective_t)(pointsPointer) @@ -18,7 +18,7 @@ func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTC cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.projective_t)(resultsPointer) - __ret := C.bls12_377_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.bls12_377_ecntt(cPoints, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } diff --git a/wrappers/golang_v3/curves/bls12377/ecntt/include/ecntt.h b/wrappers/golang_v3/curves/bls12377/ecntt/include/ecntt.h index 2561e2600..b54ac83d2 100644 --- a/wrappers/golang_v3/curves/bls12377/ecntt/include/ecntt.h +++ b/wrappers/golang_v3/curves/bls12377/ecntt/include/ecntt.h @@ -10,7 +10,7 @@ extern "C" { typedef struct NTTConfig NTTConfig; typedef struct projective_t projective_t; -cudaError_t bls12_377_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); +int bls12_377_ecntt(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12377/g2/curve.go b/wrappers/golang_v3/curves/bls12377/g2/curve.go index 31247a7e6..8a568b9d9 100644 --- a/wrappers/golang_v3/curves/bls12377/g2/curve.go +++ b/wrappers/golang_v3/curves/bls12377/g2/curve.go @@ -8,7 +8,7 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) type G2Projective struct { @@ -134,44 +134,38 @@ func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { return pointsSlice } -func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_377_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bls12_377_g2_affine_convert_montgomery((*C.g2_affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.g2_affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2AffinePointsMontgomery(points, true) } -func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2AffinePointsMontgomery(points, false) } -func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_377_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bls12_377_g2_projective_convert_montgomery((*C.g2_projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.g2_projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2ProjectivePointsMontgomery(points, true) } -func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2ProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/curves/bls12377/g2/include/curve.h b/wrappers/golang_v3/curves/bls12377/g2/include/curve.h index b136de9a8..759adbd7a 100644 --- a/wrappers/golang_v3/curves/bls12377/g2/include/curve.h +++ b/wrappers/golang_v3/curves/bls12377/g2/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_377_G2CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct g2_projective_t g2_projective_t; typedef struct g2_affine_t g2_affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool bls12_377_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bls12_377_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); void bls12_377_g2_generate_projective_points(g2_projective_t* points, int size); void bls12_377_g2_generate_affine_points(g2_affine_t* points, int size); -cudaError_t bls12_377_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t bls12_377_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int bls12_377_g2_affine_convert_montgomery(const g2_affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, g2_affine_t* d_out); +int bls12_377_g2_projective_convert_montgomery(const g2_projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, g2_projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12377/g2/include/msm.h b/wrappers/golang_v3/curves/bls12377/g2/include/msm.h index 0c1ebed7c..b94d8e0af 100644 --- a/wrappers/golang_v3/curves/bls12377/g2/include/msm.h +++ b/wrappers/golang_v3/curves/bls12377/g2/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_377_G2MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct g2_projective_t g2_projective_t; typedef struct g2_affine_t g2_affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t bls12_377_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); -cudaError_t bls12_377_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out); -cudaError_t bls12_377_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out); +int bls12_377_g2_msm(const scalar_t* scalars, const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); +int bls12_377_g2_msm_precompute_bases(g2_affine_t* input_bases, int bases_size, MSMConfig* config, g2_affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12377/g2/msm.go b/wrappers/golang_v3/curves/bls12377/g2/msm.go index 1a46b3c98..3dfd47f1a 100644 --- a/wrappers/golang_v3/curves/bls12377/g2/msm.go +++ b/wrappers/golang_v3/curves/bls12377/g2/msm.go @@ -8,57 +8,41 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func G2GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.g2_affine_t)(pointsPointer) cResults := (*C.g2_projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) - - __ret := C.bls12_377_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) - return err -} - -// Deprecated: G2PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// G2PrecomputePoints should be used instead. -func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := G2GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.g2_affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) - __ret := C.bls12_377_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bls12_377_g2_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } -func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func G2PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.g2_affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cBases := (*C.g2_affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.g2_affine_t)(outputBasesPointer) - __ret := C.bls12_377_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bls12_377_g2_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bls12377/include/curve.h b/wrappers/golang_v3/curves/bls12377/include/curve.h index 87a0229b6..63719e238 100644 --- a/wrappers/golang_v3/curves/bls12377/include/curve.h +++ b/wrappers/golang_v3/curves/bls12377/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_377_CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct projective_t projective_t; typedef struct affine_t affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool bls12_377_eq(projective_t* point1, projective_t* point2); void bls12_377_to_affine(projective_t* point, affine_t* point_out); void bls12_377_generate_projective_points(projective_t* points, int size); void bls12_377_generate_affine_points(affine_t* points, int size); -cudaError_t bls12_377_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t bls12_377_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int bls12_377_affine_convert_montgomery(const affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, affine_t* d_out); +int bls12_377_projective_convert_montgomery(const projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12377/main.go b/wrappers/golang_v3/curves/bls12377/main.go index fa60eb5f2..3e87e611e 100644 --- a/wrappers/golang_v3/curves/bls12377/main.go +++ b/wrappers/golang_v3/curves/bls12377/main.go @@ -1,4 +1,4 @@ package bls12377 -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bls12_377 -lingo_field_bls12_377 -lstdc++ -lm +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bls12_377 -licicle_curve_bls12_377 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build import "C" diff --git a/wrappers/golang_v3/curves/bls12377/msm/include/msm.h b/wrappers/golang_v3/curves/bls12377/msm/include/msm.h index b6ba320fb..fa9604cbf 100644 --- a/wrappers/golang_v3/curves/bls12377/msm/include/msm.h +++ b/wrappers/golang_v3/curves/bls12377/msm/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_377_MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct projective_t projective_t; typedef struct affine_t affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t bls12_377_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); -cudaError_t bls12_377_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); -cudaError_t bls12_377_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); +int bls12_377_msm(const scalar_t* scalars, const affine_t* points, int count, MSMConfig* config, projective_t* out); +int bls12_377_msm_precompute_bases(affine_t* input_bases, int bases_size, MSMConfig* config, affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12377/msm/msm.go b/wrappers/golang_v3/curves/bls12377/msm/msm.go index 01fc11867..2492645ba 100644 --- a/wrappers/golang_v3/curves/bls12377/msm/msm.go +++ b/wrappers/golang_v3/curves/bls12377/msm/msm.go @@ -8,57 +8,41 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.affine_t)(pointsPointer) cResults := (*C.projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) - - __ret := C.bls12_377_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) - return err -} - -// Deprecated: PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// PrecomputePoints should be used instead. -func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.affine_t)(outputBasesPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) - __ret := C.bls12_377_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bls12_377_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } -func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cBases := (*C.affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.affine_t)(outputBasesPointer) - __ret := C.bls12_377_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bls12_377_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bls12377/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/bls12377/poseidon/include/poseidon.h deleted file mode 100644 index 625f4f189..000000000 --- a/wrappers/golang_v3/curves/bls12377/poseidon/include/poseidon.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#ifndef _BLS12_377_POSEIDON_H -#define _BLS12_377_POSEIDON_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct scalar_t scalar_t; -typedef struct PoseidonConfig PoseidonConfig; -typedef struct DeviceContext DeviceContext; -typedef struct PoseidonConstants PoseidonConstants; - - -cudaError_t bls12_377_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); -cudaError_t bls12_377_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); -cudaError_t bls12_377_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go b/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go deleted file mode 100644 index 68538731f..000000000 --- a/wrappers/golang_v3/curves/bls12377/poseidon/poseidon.go +++ /dev/null @@ -1,57 +0,0 @@ -package poseidon - -// #cgo CFLAGS: -I./include/ -// #include "poseidon.h" -import "C" - -import ( - "unsafe" - - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" -) - -func GetDefaultPoseidonConfig() core.PoseidonConfig { - return core.GetDefaultPoseidonConfig() -} - -func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { - scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) - - cScalars := (*C.scalar_t)(scalarsPointer) - cResults := (*C.scalar_t)(resultsPointer) - cNumberOfStates := (C.int)(numberOfStates) - cArity := (C.int)(constants.Arity) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - cCfg := (*C.PoseidonConfig)(cfgPointer) - - __ret := C.bls12_377_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) - - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cFullRoundsHalfs := (C.int)(fullRoundsHalfs) - cPartialRounds := (C.int)(partialRounds) - cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) - - __ret := C.bls12_377_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - - __ret := C.bls12_377_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} diff --git a/wrappers/golang_v3/curves/bls12377/tests/curve_test.go b/wrappers/golang_v3/curves/bls12377/tests/curve_test.go index 065b44cd0..b894dbe39 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/curve_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go b/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go index 7ad4cbb9b..8ebb3cb37 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/ecntt_test.go @@ -7,24 +7,30 @@ import ( bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/ecntt" ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "github.com/stretchr/testify/assert" ) func TestECNtt(t *testing.T) { cfg := ntt.GetDefaultNttConfig() + ext := runtime.CreateConfigExtension() + ext.SetInt(core.CUDA_NTT_ALGORITHM, int(core.Radix2)) + cfg.Ext = ext.AsUnsafePointer() + points := bls12_377.GenerateProjectivePoints(1 << largestTestSize) for _, size := range []int{4, 5, 6, 7, 8} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size pointsCopy := core.HostSliceFromElements[bls12_377.Projective](points[:testSize]) cfg.Ordering = v - cfg.NttAlgorithm = core.Radix2 output := make(core.HostSlice[bls12_377.Projective], testSize) e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + assert.Equal(t, runtime.Success, e, "ECNtt failed") } } } diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go index 25a32b56d..ef17b15d9 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_curve_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/g2" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) func TestG2AffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go index 80fb58ddb..644834221 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377" + "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" icicleBls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func projectiveToGnarkAffineG2(p g2.G2Projective) bls12377.G2Affine { @@ -62,7 +62,7 @@ func projectiveToGnarkAffineG2(p g2.G2Projective) bls12377.G2Affine { return *g2Affine.FromJacobian(&g2Jac) } -func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBls12_377.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { +func testAgainstGnarkCryptoMsmG2(t *testing.T, scalars core.HostSlice[icicleBls12_377.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) { scalarsFr := make([]fr.Element, len(scalars)) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -74,18 +74,19 @@ func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBls12_377.ScalarFi pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) } - return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) + testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t, scalarsFr, pointsFp, out) } -func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12377.G2Affine], out g2.G2Projective) bool { +func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12377.G2Affine], out g2.G2Projective) { var msmRes bls12377.G2Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - var icicleResAsJac bls12377.G2Jac - proj := projectiveToGnarkAffineG2(out) - icicleResAsJac.FromAffine(&proj) + var msmResAffine bls12377.G2Affine + msmResAffine.FromJacobian(&msmRes) - return msmRes.Equal(&icicleResAsJac) + icicleResAffine := projectiveToGnarkAffineG2(out) + + assert.Equal(t, msmResAffine, icicleResAffine) } func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bls12377.G2Affine { @@ -122,85 +123,87 @@ func TestMSMG2(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicleBls12_377.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p g2.G2Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } } -func TestMSMG2PinnedHostMemory(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicleBls12_377.GenerateScalars(size) - points := g2.G2GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[g2.G2Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[g2.G2Projective], 1) - - e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - - if pinnableAndLockable { - e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) - - } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} +// func TestMSMG2PinnedHostMemory(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleBls12_377.GenerateScalars(size) +// points := g2.G2GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[g2.G2Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) +// +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) +// +// +// if pinnableAndLockable { +// e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) +// +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } func TestMSMG2GnarkCryptoTypes(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{3} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := make([]fr.Element, size) @@ -217,18 +220,18 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true cfg.AreScalarsMontgomeryForm = true e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } } @@ -236,6 +239,7 @@ func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicleBls12_377.GenerateScalars(totalSize) @@ -244,10 +248,10 @@ func TestMSMG2Batch(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -256,7 +260,7 @@ func TestMSMG2Batch(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) } } } @@ -269,6 +273,8 @@ func TestPrecomputePointsG2(t *testing.T) { for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicleBls12_377.GenerateScalars(totalSize) @@ -276,18 +282,20 @@ func TestPrecomputePointsG2(t *testing.T) { var precomputeOut core.DeviceSlice _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = g2.G2PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p g2.G2Projective var out core.DeviceSlice _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -297,7 +305,50 @@ func TestPrecomputePointsG2(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestPrecomputePointsSharedBasesG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_377.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = g2.G2PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0:size] + out := outHost[i] + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) } } } @@ -306,6 +357,8 @@ func TestPrecomputePointsG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power scalars := icicleBls12_377.GenerateScalars(size) @@ -320,27 +373,31 @@ func TestMSMG2SkewedDistribution(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } } func TestMSMG2MultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { + runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { @@ -348,22 +405,22 @@ func TestMSMG2MultiDevice(t *testing.T) { scalars := icicleBls12_377.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p g2.G2Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } }) } diff --git a/wrappers/golang_v3/curves/bls12377/tests/main_test.go b/wrappers/golang_v3/curves/bls12377/tests/main_test.go index dc593ca78..3402658db 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/main_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/main_test.go @@ -1,7 +1,7 @@ package tests import ( - "os" + "fmt" "testing" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" @@ -16,6 +16,8 @@ const ( largestTestSize = 20 ) +var DEVICE runtime.Device + func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() @@ -29,22 +31,36 @@ func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcic func TestMain(m *testing.M) { runtime.LoadBackendFromEnv() - device := runtime.CreateDevice("CUDA", 0) - runtime.SetDevice(&device) - - // setup domain - cfg := core.GetDefaultNTTInitDomainConfig() - e := initDomain(largestTestSize, cfg) + devices, e := runtime.GetRegisteredDevices() if e != runtime.Success { - panic("initDomain failed") + panic("Failed to load registered devices") } + for _, deviceType := range devices { + DEVICE = runtime.CreateDevice(deviceType, 0) + runtime.SetDevice(&DEVICE) - // execute tests - os.Exit(m.Run()) + // setup domain + cfg := core.GetDefaultNTTInitDomainConfig() + e = initDomain(largestTestSize, cfg) + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("initDomain is not implemented for ", deviceType, " device type") + } else { + panic("initDomain failed") + } + } - // release domain - e = ntt.ReleaseDomain() - if e != runtime.Success { - panic("ReleaseDomain failed") + // execute tests + m.Run() + + // release domain + e = ntt.ReleaseDomain() + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("ReleaseDomain is not implemented for ", deviceType, " device type") + } else { + panic("ReleaseDomain failed") + } + } } } diff --git a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go index c04cb10bc..91cde4e80 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377" + "github.com/consensys/gnark-crypto/ecc/bls12-377" "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" icicleBls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func projectiveToGnarkAffine(p icicleBls12_377.Projective) bls12377.G1Affine { @@ -35,7 +35,7 @@ func projectiveToGnarkAffine(p icicleBls12_377.Projective) bls12377.G1Affine { return bls12377.G1Affine{X: *x, Y: *y} } -func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBls12_377.ScalarField], points core.HostSlice[icicleBls12_377.Affine], out icicleBls12_377.Projective) bool { +func testAgainstGnarkCryptoMsm(t *testing.T, scalars core.HostSlice[icicleBls12_377.ScalarField], points core.HostSlice[icicleBls12_377.Affine], out icicleBls12_377.Projective) { scalarsFr := make([]fr.Element, len(scalars)) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -47,18 +47,19 @@ func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBls12_377.ScalarFiel pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) } - return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out) + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsFr, pointsFp, out) } -func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12377.G1Affine], out icicleBls12_377.Projective) bool { +func testAgainstGnarkCryptoMsmGnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12377.G1Affine], out icicleBls12_377.Projective) { var msmRes bls12377.G1Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - var icicleResAsJac bls12377.G1Jac - proj := projectiveToGnarkAffine(out) - icicleResAsJac.FromAffine(&proj) + var msmResAffine bls12377.G1Affine + msmResAffine.FromJacobian(&msmRes) - return msmRes.Equal(&icicleResAsJac) + icicleResAffine := projectiveToGnarkAffine(out) + + assert.Equal(t, msmResAffine, icicleResAffine) } func convertIcicleAffineToG1Affine(iciclePoints []icicleBls12_377.Affine) []bls12377.G1Affine { @@ -82,85 +83,87 @@ func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicleBls12_377.GenerateScalars(size) points := icicleBls12_377.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleBls12_377.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } } -func TestMSMPinnedHostMemory(t *testing.T) { - cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicleBls12_377.GenerateScalars(size) - points := icicleBls12_377.GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[icicleBls12_377.Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p icicleBls12_377.Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) - - e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - - if pinnableAndLockable { - e = msm.Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) - - } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} +// func TestMSMPinnedHostMemory(t *testing.T) { +// cfg := msm.GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleBls12_377.GenerateScalars(size) +// points := icicleBls12_377.GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[icicleBls12_377.Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p icicleBls12_377.Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) +// +// e = msm.Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) +// +// +// if pinnableAndLockable { +// e = msm.Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) +// +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } func TestMSMGnarkCryptoTypes(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{3} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := make([]fr.Element, size) @@ -177,18 +180,18 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { var p icicleBls12_377.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true cfg.AreScalarsMontgomeryForm = true e = msm.Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } } @@ -196,6 +199,7 @@ func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicleBls12_377.GenerateScalars(totalSize) @@ -204,10 +208,10 @@ func TestMSMBatch(t *testing.T) { var p icicleBls12_377.Projective var out core.DeviceSlice _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_377.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -216,7 +220,7 @@ func TestMSMBatch(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) } } } @@ -229,6 +233,8 @@ func TestPrecomputePoints(t *testing.T) { for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicleBls12_377.GenerateScalars(totalSize) @@ -236,18 +242,20 @@ func TestPrecomputePoints(t *testing.T) { var precomputeOut core.DeviceSlice _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p icicleBls12_377.Projective var out core.DeviceSlice _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[icicleBls12_377.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -257,7 +265,50 @@ func TestPrecomputePoints(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestPrecomputePointsSharedBases(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_377.GenerateScalars(totalSize) + points := icicleBls12_377.GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p icicleBls12_377.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_377.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0:size] + out := outHost[i] + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) } } } @@ -266,6 +317,8 @@ func TestPrecomputePoints(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power scalars := icicleBls12_377.GenerateScalars(size) @@ -280,27 +333,31 @@ func TestMSMSkewedDistribution(t *testing.T) { var p icicleBls12_377.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } } func TestMSMMultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { + runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { @@ -308,22 +365,22 @@ func TestMSMMultiDevice(t *testing.T) { scalars := icicleBls12_377.GenerateScalars(size) points := icicleBls12_377.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleBls12_377.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_377.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } }) } diff --git a/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go b/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go index d8fb84e05..34b0a4de5 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" ) -func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bls12_377.ScalarField], output core.HostSlice[bls12_377.ScalarField], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNtt(t *testing.T, size int, scalars core.HostSlice[bls12_377.ScalarField], output core.HostSlice[bls12_377.ScalarField], order core.Ordering, direction core.NTTDir) { scalarsFr := make([]fr.Element, size) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -26,10 +26,10 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bls12_377.Scalar outputAsFr[i] = slice64 } - return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) + testAgainstGnarkCryptoNttGnarkTypes(t, size, scalarsFr, outputAsFr, order, direction) } -func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNttGnarkTypes(t *testing.T, size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) { domainWithPrecompute := fft.NewDomain(uint64(size)) // DIT + BitReverse == Ordering.kRR // DIT == Ordering.kRN @@ -51,7 +51,7 @@ func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.E if order == core.KNN || order == core.KRR { fft.BitReverse(scalarsFr) } - return reflect.DeepEqual(scalarsFr, outputAsFr) + assert.Equal(t, scalarsFr, outputAsFr) } func TestNTTGetDefaultConfig(t *testing.T) { actual := ntt.GetDefaultNttConfig() @@ -75,6 +75,8 @@ func TestNtt(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:testSize]) @@ -85,7 +87,7 @@ func TestNtt(t *testing.T) { ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -100,6 +102,8 @@ func TestNttFrElement(t *testing.T) { for _, size := range []int{4} { for _, v := range [1]core.Ordering{core.KNN} { + runtime.SetDevice(&DEVICE) + testSize := size scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) @@ -110,7 +114,7 @@ func TestNttFrElement(t *testing.T) { ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNttGnarkTypes(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -122,6 +126,8 @@ func TestNttDeviceAsync(t *testing.T) { for _, size := range []int{1, 10, largestTestSize} { for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:testSize]) @@ -143,7 +149,7 @@ func TestNttDeviceAsync(t *testing.T) { runtime.SynchronizeStream(stream) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, direction) } } } @@ -157,6 +163,8 @@ func TestNttBatch(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, batchSize := range []int{2, 16, largestBatchSize} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size totalSize := testSize * batchSize diff --git a/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go b/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go deleted file mode 100644 index f4e30ad29..000000000 --- a/wrappers/golang_v3/curves/bls12377/tests/poseidon_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package tests - -import ( - "testing" - - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" - bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12377/poseidon" -) - -func TestPoseidon(t *testing.T) { - - arity := 2 - numberOfStates := 1 - - cfg := poseidon.GetDefaultPoseidonConfig() - cfg.IsAsync = true - stream, _ := cr.CreateStream() - cfg.Ctx.Stream = &stream - - var constants core.PoseidonConstants[bls12_377.ScalarField] - - poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants - - scalars := bls12_377.GenerateScalars(numberOfStates * arity) - scalars[0] = scalars[0].Zero() - scalars[1] = scalars[0].Zero() - - scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) - - var deviceInput core.DeviceSlice - scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) - var deviceOutput core.DeviceSlice - deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) - - poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function - - output := make(core.HostSlice[bls12_377.ScalarField], numberOfStates) - output.CopyFromDeviceAsync(&deviceOutput, stream) - -} diff --git a/wrappers/golang_v3/curves/bls12381/curve.go b/wrappers/golang_v3/curves/bls12381/curve.go index ce3bd9800..ea1c4e88a 100644 --- a/wrappers/golang_v3/curves/bls12381/curve.go +++ b/wrappers/golang_v3/curves/bls12381/curve.go @@ -8,7 +8,7 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) type Projective struct { @@ -134,44 +134,38 @@ func GenerateAffinePoints(size int) core.HostSlice[Affine] { return pointsSlice } -func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_381_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bls12_381_affine_convert_montgomery((*C.affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, true) } -func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, false) } -func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_381_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bls12_381_projective_convert_montgomery((*C.projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, true) } -func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go b/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go index 032ae3ecb..ad0794d14 100644 --- a/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go +++ b/wrappers/golang_v3/curves/bls12381/ecntt/ecntt.go @@ -6,10 +6,10 @@ import "C" import ( "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) cPoints := (*C.projective_t)(pointsPointer) @@ -18,7 +18,7 @@ func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTC cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.projective_t)(resultsPointer) - __ret := C.bls12_381_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.bls12_381_ecntt(cPoints, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } diff --git a/wrappers/golang_v3/curves/bls12381/ecntt/include/ecntt.h b/wrappers/golang_v3/curves/bls12381/ecntt/include/ecntt.h index 033af4664..8a0ce0971 100644 --- a/wrappers/golang_v3/curves/bls12381/ecntt/include/ecntt.h +++ b/wrappers/golang_v3/curves/bls12381/ecntt/include/ecntt.h @@ -10,7 +10,7 @@ extern "C" { typedef struct NTTConfig NTTConfig; typedef struct projective_t projective_t; -cudaError_t bls12_381_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); +int bls12_381_ecntt(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12381/g2/curve.go b/wrappers/golang_v3/curves/bls12381/g2/curve.go index 7b27b39ab..6abe81b79 100644 --- a/wrappers/golang_v3/curves/bls12381/g2/curve.go +++ b/wrappers/golang_v3/curves/bls12381/g2/curve.go @@ -8,7 +8,7 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) type G2Projective struct { @@ -134,44 +134,38 @@ func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { return pointsSlice } -func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_381_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bls12_381_g2_affine_convert_montgomery((*C.g2_affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.g2_affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2AffinePointsMontgomery(points, true) } -func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2AffinePointsMontgomery(points, false) } -func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bls12_381_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bls12_381_g2_projective_convert_montgomery((*C.g2_projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.g2_projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2ProjectivePointsMontgomery(points, true) } -func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2ProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/curves/bls12381/g2/include/curve.h b/wrappers/golang_v3/curves/bls12381/g2/include/curve.h index b7710244d..09f334012 100644 --- a/wrappers/golang_v3/curves/bls12381/g2/include/curve.h +++ b/wrappers/golang_v3/curves/bls12381/g2/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_381_G2CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct g2_projective_t g2_projective_t; typedef struct g2_affine_t g2_affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool bls12_381_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bls12_381_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); void bls12_381_g2_generate_projective_points(g2_projective_t* points, int size); void bls12_381_g2_generate_affine_points(g2_affine_t* points, int size); -cudaError_t bls12_381_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t bls12_381_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int bls12_381_g2_affine_convert_montgomery(const g2_affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, g2_affine_t* d_out); +int bls12_381_g2_projective_convert_montgomery(const g2_projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, g2_projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12381/g2/include/msm.h b/wrappers/golang_v3/curves/bls12381/g2/include/msm.h index 71c3ce984..37067ca11 100644 --- a/wrappers/golang_v3/curves/bls12381/g2/include/msm.h +++ b/wrappers/golang_v3/curves/bls12381/g2/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_381_G2MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct g2_projective_t g2_projective_t; typedef struct g2_affine_t g2_affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t bls12_381_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); -cudaError_t bls12_381_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out); -cudaError_t bls12_381_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out); +int bls12_381_g2_msm(const scalar_t* scalars, const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); +int bls12_381_g2_msm_precompute_bases(g2_affine_t* input_bases, int bases_size, MSMConfig* config, g2_affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12381/g2/msm.go b/wrappers/golang_v3/curves/bls12381/g2/msm.go index b491e40b4..16fe4fdd7 100644 --- a/wrappers/golang_v3/curves/bls12381/g2/msm.go +++ b/wrappers/golang_v3/curves/bls12381/g2/msm.go @@ -8,57 +8,41 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func G2GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.g2_affine_t)(pointsPointer) cResults := (*C.g2_projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) - - __ret := C.bls12_381_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) - return err -} - -// Deprecated: G2PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// G2PrecomputePoints should be used instead. -func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := G2GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.g2_affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) - __ret := C.bls12_381_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bls12_381_g2_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } -func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func G2PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.g2_affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cBases := (*C.g2_affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.g2_affine_t)(outputBasesPointer) - __ret := C.bls12_381_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bls12_381_g2_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bls12381/include/curve.h b/wrappers/golang_v3/curves/bls12381/include/curve.h index 1cb3bd61e..88ec9e04b 100644 --- a/wrappers/golang_v3/curves/bls12381/include/curve.h +++ b/wrappers/golang_v3/curves/bls12381/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_381_CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct projective_t projective_t; typedef struct affine_t affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool bls12_381_eq(projective_t* point1, projective_t* point2); void bls12_381_to_affine(projective_t* point, affine_t* point_out); void bls12_381_generate_projective_points(projective_t* points, int size); void bls12_381_generate_affine_points(affine_t* points, int size); -cudaError_t bls12_381_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t bls12_381_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int bls12_381_affine_convert_montgomery(const affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, affine_t* d_out); +int bls12_381_projective_convert_montgomery(const projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12381/main.go b/wrappers/golang_v3/curves/bls12381/main.go index 3f3a21059..6320483cd 100644 --- a/wrappers/golang_v3/curves/bls12381/main.go +++ b/wrappers/golang_v3/curves/bls12381/main.go @@ -1,4 +1,4 @@ package bls12381 -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bls12_381 -lingo_field_bls12_381 -lstdc++ -lm +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bls12_381 -licicle_curve_bls12_381 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build import "C" diff --git a/wrappers/golang_v3/curves/bls12381/msm/include/msm.h b/wrappers/golang_v3/curves/bls12381/msm/include/msm.h index 9312cdd85..9518b1aa8 100644 --- a/wrappers/golang_v3/curves/bls12381/msm/include/msm.h +++ b/wrappers/golang_v3/curves/bls12381/msm/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BLS12_381_MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct projective_t projective_t; typedef struct affine_t affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t bls12_381_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); -cudaError_t bls12_381_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); -cudaError_t bls12_381_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); +int bls12_381_msm(const scalar_t* scalars, const affine_t* points, int count, MSMConfig* config, projective_t* out); +int bls12_381_msm_precompute_bases(affine_t* input_bases, int bases_size, MSMConfig* config, affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bls12381/msm/msm.go b/wrappers/golang_v3/curves/bls12381/msm/msm.go index 7170c7336..09362e36e 100644 --- a/wrappers/golang_v3/curves/bls12381/msm/msm.go +++ b/wrappers/golang_v3/curves/bls12381/msm/msm.go @@ -8,57 +8,41 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.affine_t)(pointsPointer) cResults := (*C.projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) - - __ret := C.bls12_381_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) - return err -} - -// Deprecated: PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// PrecomputePoints should be used instead. -func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.affine_t)(outputBasesPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) - __ret := C.bls12_381_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bls12_381_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } -func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cBases := (*C.affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.affine_t)(outputBasesPointer) - __ret := C.bls12_381_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bls12_381_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bls12381/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/bls12381/poseidon/include/poseidon.h deleted file mode 100644 index 1372013ef..000000000 --- a/wrappers/golang_v3/curves/bls12381/poseidon/include/poseidon.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#ifndef _BLS12_381_POSEIDON_H -#define _BLS12_381_POSEIDON_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct scalar_t scalar_t; -typedef struct PoseidonConfig PoseidonConfig; -typedef struct DeviceContext DeviceContext; -typedef struct PoseidonConstants PoseidonConstants; - - -cudaError_t bls12_381_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); -cudaError_t bls12_381_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); -cudaError_t bls12_381_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go b/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go deleted file mode 100644 index f3d814d92..000000000 --- a/wrappers/golang_v3/curves/bls12381/poseidon/poseidon.go +++ /dev/null @@ -1,57 +0,0 @@ -package poseidon - -// #cgo CFLAGS: -I./include/ -// #include "poseidon.h" -import "C" - -import ( - "unsafe" - - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" -) - -func GetDefaultPoseidonConfig() core.PoseidonConfig { - return core.GetDefaultPoseidonConfig() -} - -func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { - scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) - - cScalars := (*C.scalar_t)(scalarsPointer) - cResults := (*C.scalar_t)(resultsPointer) - cNumberOfStates := (C.int)(numberOfStates) - cArity := (C.int)(constants.Arity) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - cCfg := (*C.PoseidonConfig)(cfgPointer) - - __ret := C.bls12_381_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) - - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cFullRoundsHalfs := (C.int)(fullRoundsHalfs) - cPartialRounds := (C.int)(partialRounds) - cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) - - __ret := C.bls12_381_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - - __ret := C.bls12_381_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} diff --git a/wrappers/golang_v3/curves/bls12381/tests/curve_test.go b/wrappers/golang_v3/curves/bls12381/tests/curve_test.go index 34513d096..65558e943 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/curve_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go b/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go index 7ceb4af10..119b30a6d 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/ecntt_test.go @@ -7,24 +7,30 @@ import ( bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/ecntt" ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "github.com/stretchr/testify/assert" ) func TestECNtt(t *testing.T) { cfg := ntt.GetDefaultNttConfig() + ext := runtime.CreateConfigExtension() + ext.SetInt(core.CUDA_NTT_ALGORITHM, int(core.Radix2)) + cfg.Ext = ext.AsUnsafePointer() + points := bls12_381.GenerateProjectivePoints(1 << largestTestSize) for _, size := range []int{4, 5, 6, 7, 8} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size pointsCopy := core.HostSliceFromElements[bls12_381.Projective](points[:testSize]) cfg.Ordering = v - cfg.NttAlgorithm = core.Radix2 output := make(core.HostSlice[bls12_381.Projective], testSize) e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + assert.Equal(t, runtime.Success, e, "ECNtt failed") } } } diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go index dd21ccf4f..462d18bb5 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_curve_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/g2" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) func TestG2AffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go index 1021298dc..ac862a4a5 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" icicleBls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func projectiveToGnarkAffineG2(p g2.G2Projective) bls12381.G2Affine { @@ -62,7 +62,7 @@ func projectiveToGnarkAffineG2(p g2.G2Projective) bls12381.G2Affine { return *g2Affine.FromJacobian(&g2Jac) } -func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBls12_381.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { +func testAgainstGnarkCryptoMsmG2(t *testing.T, scalars core.HostSlice[icicleBls12_381.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) { scalarsFr := make([]fr.Element, len(scalars)) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -74,18 +74,19 @@ func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBls12_381.ScalarFi pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) } - return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) + testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t, scalarsFr, pointsFp, out) } -func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12381.G2Affine], out g2.G2Projective) bool { +func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12381.G2Affine], out g2.G2Projective) { var msmRes bls12381.G2Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - var icicleResAsJac bls12381.G2Jac - proj := projectiveToGnarkAffineG2(out) - icicleResAsJac.FromAffine(&proj) + var msmResAffine bls12381.G2Affine + msmResAffine.FromJacobian(&msmRes) - return msmRes.Equal(&icicleResAsJac) + icicleResAffine := projectiveToGnarkAffineG2(out) + + assert.Equal(t, msmResAffine, icicleResAffine) } func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bls12381.G2Affine { @@ -122,85 +123,87 @@ func TestMSMG2(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicleBls12_381.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p g2.G2Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } } -func TestMSMG2PinnedHostMemory(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicleBls12_381.GenerateScalars(size) - points := g2.G2GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[g2.G2Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[g2.G2Projective], 1) - - e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - - if pinnableAndLockable { - e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) - - } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} +// func TestMSMG2PinnedHostMemory(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleBls12_381.GenerateScalars(size) +// points := g2.G2GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[g2.G2Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) +// +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) +// +// +// if pinnableAndLockable { +// e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) +// +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } func TestMSMG2GnarkCryptoTypes(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{3} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := make([]fr.Element, size) @@ -217,18 +220,18 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true cfg.AreScalarsMontgomeryForm = true e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } } @@ -236,6 +239,7 @@ func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicleBls12_381.GenerateScalars(totalSize) @@ -244,10 +248,10 @@ func TestMSMG2Batch(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -256,7 +260,7 @@ func TestMSMG2Batch(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) } } } @@ -269,6 +273,8 @@ func TestPrecomputePointsG2(t *testing.T) { for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicleBls12_381.GenerateScalars(totalSize) @@ -276,18 +282,20 @@ func TestPrecomputePointsG2(t *testing.T) { var precomputeOut core.DeviceSlice _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = g2.G2PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p g2.G2Projective var out core.DeviceSlice _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -297,7 +305,50 @@ func TestPrecomputePointsG2(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestPrecomputePointsSharedBasesG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_381.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = g2.G2PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0:size] + out := outHost[i] + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) } } } @@ -306,6 +357,8 @@ func TestPrecomputePointsG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power scalars := icicleBls12_381.GenerateScalars(size) @@ -320,27 +373,31 @@ func TestMSMG2SkewedDistribution(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } } func TestMSMG2MultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { + runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { @@ -348,22 +405,22 @@ func TestMSMG2MultiDevice(t *testing.T) { scalars := icicleBls12_381.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p g2.G2Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } }) } diff --git a/wrappers/golang_v3/curves/bls12381/tests/main_test.go b/wrappers/golang_v3/curves/bls12381/tests/main_test.go index 5cf2e30f3..05a24834d 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/main_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/main_test.go @@ -1,7 +1,7 @@ package tests import ( - "os" + "fmt" "testing" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" @@ -16,6 +16,8 @@ const ( largestTestSize = 20 ) +var DEVICE runtime.Device + func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() @@ -29,22 +31,36 @@ func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcic func TestMain(m *testing.M) { runtime.LoadBackendFromEnv() - device := runtime.CreateDevice("CUDA", 0) - runtime.SetDevice(&device) - - // setup domain - cfg := core.GetDefaultNTTInitDomainConfig() - e := initDomain(largestTestSize, cfg) + devices, e := runtime.GetRegisteredDevices() if e != runtime.Success { - panic("initDomain failed") + panic("Failed to load registered devices") } + for _, deviceType := range devices { + DEVICE = runtime.CreateDevice(deviceType, 0) + runtime.SetDevice(&DEVICE) - // execute tests - os.Exit(m.Run()) + // setup domain + cfg := core.GetDefaultNTTInitDomainConfig() + e = initDomain(largestTestSize, cfg) + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("initDomain is not implemented for ", deviceType, " device type") + } else { + panic("initDomain failed") + } + } - // release domain - e = ntt.ReleaseDomain() - if e != runtime.Success { - panic("ReleaseDomain failed") + // execute tests + m.Run() + + // release domain + e = ntt.ReleaseDomain() + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("ReleaseDomain is not implemented for ", deviceType, " device type") + } else { + panic("ReleaseDomain failed") + } + } } } diff --git a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go index 2434f7d97..57199c943 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" icicleBls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func projectiveToGnarkAffine(p icicleBls12_381.Projective) bls12381.G1Affine { @@ -35,7 +35,7 @@ func projectiveToGnarkAffine(p icicleBls12_381.Projective) bls12381.G1Affine { return bls12381.G1Affine{X: *x, Y: *y} } -func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBls12_381.ScalarField], points core.HostSlice[icicleBls12_381.Affine], out icicleBls12_381.Projective) bool { +func testAgainstGnarkCryptoMsm(t *testing.T, scalars core.HostSlice[icicleBls12_381.ScalarField], points core.HostSlice[icicleBls12_381.Affine], out icicleBls12_381.Projective) { scalarsFr := make([]fr.Element, len(scalars)) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -47,18 +47,19 @@ func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBls12_381.ScalarFiel pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) } - return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out) + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsFr, pointsFp, out) } -func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12381.G1Affine], out icicleBls12_381.Projective) bool { +func testAgainstGnarkCryptoMsmGnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12381.G1Affine], out icicleBls12_381.Projective) { var msmRes bls12381.G1Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - var icicleResAsJac bls12381.G1Jac - proj := projectiveToGnarkAffine(out) - icicleResAsJac.FromAffine(&proj) + var msmResAffine bls12381.G1Affine + msmResAffine.FromJacobian(&msmRes) - return msmRes.Equal(&icicleResAsJac) + icicleResAffine := projectiveToGnarkAffine(out) + + assert.Equal(t, msmResAffine, icicleResAffine) } func convertIcicleAffineToG1Affine(iciclePoints []icicleBls12_381.Affine) []bls12381.G1Affine { @@ -82,85 +83,87 @@ func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicleBls12_381.GenerateScalars(size) points := icicleBls12_381.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleBls12_381.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } } -func TestMSMPinnedHostMemory(t *testing.T) { - cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicleBls12_381.GenerateScalars(size) - points := icicleBls12_381.GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[icicleBls12_381.Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p icicleBls12_381.Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) - - e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - - if pinnableAndLockable { - e = msm.Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) - - } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} +// func TestMSMPinnedHostMemory(t *testing.T) { +// cfg := msm.GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleBls12_381.GenerateScalars(size) +// points := icicleBls12_381.GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[icicleBls12_381.Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p icicleBls12_381.Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) +// +// e = msm.Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) +// +// +// if pinnableAndLockable { +// e = msm.Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) +// +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } func TestMSMGnarkCryptoTypes(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{3} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := make([]fr.Element, size) @@ -177,18 +180,18 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { var p icicleBls12_381.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true cfg.AreScalarsMontgomeryForm = true e = msm.Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } } @@ -196,6 +199,7 @@ func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicleBls12_381.GenerateScalars(totalSize) @@ -204,10 +208,10 @@ func TestMSMBatch(t *testing.T) { var p icicleBls12_381.Projective var out core.DeviceSlice _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_381.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -216,7 +220,7 @@ func TestMSMBatch(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) } } } @@ -229,6 +233,8 @@ func TestPrecomputePoints(t *testing.T) { for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicleBls12_381.GenerateScalars(totalSize) @@ -236,18 +242,20 @@ func TestPrecomputePoints(t *testing.T) { var precomputeOut core.DeviceSlice _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p icicleBls12_381.Projective var out core.DeviceSlice _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[icicleBls12_381.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -257,7 +265,50 @@ func TestPrecomputePoints(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestPrecomputePointsSharedBases(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBls12_381.GenerateScalars(totalSize) + points := icicleBls12_381.GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p icicleBls12_381.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[icicleBls12_381.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0:size] + out := outHost[i] + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) } } } @@ -266,6 +317,8 @@ func TestPrecomputePoints(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power scalars := icicleBls12_381.GenerateScalars(size) @@ -280,27 +333,31 @@ func TestMSMSkewedDistribution(t *testing.T) { var p icicleBls12_381.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } } func TestMSMMultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { + runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { @@ -308,22 +365,22 @@ func TestMSMMultiDevice(t *testing.T) { scalars := icicleBls12_381.GenerateScalars(size) points := icicleBls12_381.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleBls12_381.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBls12_381.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } }) } diff --git a/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go b/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go index 1a503f087..b43d7445d 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" ) -func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bls12_381.ScalarField], output core.HostSlice[bls12_381.ScalarField], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNtt(t *testing.T, size int, scalars core.HostSlice[bls12_381.ScalarField], output core.HostSlice[bls12_381.ScalarField], order core.Ordering, direction core.NTTDir) { scalarsFr := make([]fr.Element, size) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -26,10 +26,10 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bls12_381.Scalar outputAsFr[i] = slice64 } - return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) + testAgainstGnarkCryptoNttGnarkTypes(t, size, scalarsFr, outputAsFr, order, direction) } -func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNttGnarkTypes(t *testing.T, size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) { domainWithPrecompute := fft.NewDomain(uint64(size)) // DIT + BitReverse == Ordering.kRR // DIT == Ordering.kRN @@ -51,7 +51,7 @@ func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.E if order == core.KNN || order == core.KRR { fft.BitReverse(scalarsFr) } - return reflect.DeepEqual(scalarsFr, outputAsFr) + assert.Equal(t, scalarsFr, outputAsFr) } func TestNTTGetDefaultConfig(t *testing.T) { actual := ntt.GetDefaultNttConfig() @@ -75,6 +75,8 @@ func TestNtt(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:testSize]) @@ -85,7 +87,7 @@ func TestNtt(t *testing.T) { ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -100,6 +102,8 @@ func TestNttFrElement(t *testing.T) { for _, size := range []int{4} { for _, v := range [1]core.Ordering{core.KNN} { + runtime.SetDevice(&DEVICE) + testSize := size scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) @@ -110,7 +114,7 @@ func TestNttFrElement(t *testing.T) { ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNttGnarkTypes(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -122,6 +126,8 @@ func TestNttDeviceAsync(t *testing.T) { for _, size := range []int{1, 10, largestTestSize} { for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:testSize]) @@ -143,7 +149,7 @@ func TestNttDeviceAsync(t *testing.T) { runtime.SynchronizeStream(stream) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, direction) } } } @@ -157,6 +163,8 @@ func TestNttBatch(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, batchSize := range []int{2, 16, largestBatchSize} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size totalSize := testSize * batchSize diff --git a/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go b/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go deleted file mode 100644 index e36b0d41b..000000000 --- a/wrappers/golang_v3/curves/bls12381/tests/poseidon_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package tests - -import ( - "testing" - - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" - bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bls12381/poseidon" - - "fmt" - - "github.com/stretchr/testify/assert" -) - -func formatOutput(x bls12_381.ScalarField) string { - r := x.GetLimbs() - return fmt.Sprintf("%08x%08x%08x%08x%08x%08x%08x%08x", r[7], r[6], r[5], r[4], r[3], r[2], r[1], r[0]) -} - -func TestPoseidon(t *testing.T) { - - arity := 2 - numberOfStates := 1 - - cfg := poseidon.GetDefaultPoseidonConfig() - cfg.IsAsync = true - stream, _ := cr.CreateStream() - cfg.Ctx.Stream = &stream - - var constants core.PoseidonConstants[bls12_381.ScalarField] - - poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants - - scalars := bls12_381.GenerateScalars(numberOfStates * arity) - scalars[0] = scalars[0].Zero() - scalars[1] = scalars[0].Zero() - - scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) - - var deviceInput core.DeviceSlice - scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) - var deviceOutput core.DeviceSlice - deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) - - poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function - - output := make(core.HostSlice[bls12_381.ScalarField], numberOfStates) - output.CopyFromDeviceAsync(&deviceOutput, stream) - - expectedString := "48fe0b1331196f6cdb33a7c6e5af61b76fd388e1ef1d3d418be5147f0e4613d4" //This result is from https://github.com/triplewz/poseidon - outputString := formatOutput(output[0]) - - assert.Equal(t, outputString, expectedString, "Poseidon hash does not match expected result") - -} diff --git a/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go b/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go index d76f5c33e..d04227034 100644 --- a/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go +++ b/wrappers/golang_v3/curves/bn254/ecntt/ecntt.go @@ -6,10 +6,10 @@ import "C" import ( "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) cr.EIcicleError { +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) cPoints := (*C.projective_t)(pointsPointer) @@ -19,6 +19,6 @@ func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTC cResults := (*C.projective_t)(resultsPointer) __ret := C.bn254_ecntt(cPoints, cSize, cDir, cCfg, cResults) - err := (cr.EIcicleError)(__ret) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bn254/g2/curve.go b/wrappers/golang_v3/curves/bn254/g2/curve.go index e9a1fd7be..c3b4c3ad5 100644 --- a/wrappers/golang_v3/curves/bn254/g2/curve.go +++ b/wrappers/golang_v3/curves/bn254/g2/curve.go @@ -1,177 +1,171 @@ package g2 -// // #cgo CFLAGS: -I./include/ -// // #include "curve.h" -// import "C" - -// import ( -// "unsafe" +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" -// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" -// ) + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) -// type G2Projective struct { -// X, Y, Z G2BaseField -// } - -// func (p G2Projective) Size() int { -// return p.X.Size() * 3 -// } - -// func (p G2Projective) AsPointer() *uint32 { -// return p.X.AsPointer() -// } - -// func (p *G2Projective) Zero() G2Projective { -// p.X.Zero() -// p.Y.One() -// p.Z.Zero() - -// return *p -// } - -// func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { -// p.X.FromLimbs(x) -// p.Y.FromLimbs(y) -// p.Z.FromLimbs(z) - -// return *p -// } - -// func (p *G2Projective) FromAffine(a G2Affine) G2Projective { -// z := G2BaseField{} -// z.One() - -// p.X = a.X -// p.Y = a.Y -// p.Z = z - -// return *p -// } - -// func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { -// cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) -// cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) -// __ret := C.bn254_g2_eq(cP, cP2) -// return __ret == (C._Bool)(true) -// } - -// func (p *G2Projective) ProjectiveToAffine() G2Affine { -// var a G2Affine - -// cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) -// cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) -// C.bn254_g2_to_affine(cP, cA) -// return a -// } - -// func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { -// points := make([]G2Projective, size) -// for i := range points { -// points[i] = G2Projective{} -// } - -// pointsSlice := core.HostSliceFromElements[G2Projective](points) -// pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) -// cSize := (C.int)(size) -// C.bn254_g2_generate_projective_points(pPoints, cSize) - -// return pointsSlice -// } - -// type G2Affine struct { -// X, Y G2BaseField -// } - -// func (a G2Affine) Size() int { -// return a.X.Size() * 2 -// } - -// func (a G2Affine) AsPointer() *uint32 { -// return a.X.AsPointer() -// } - -// func (a *G2Affine) Zero() G2Affine { -// a.X.Zero() -// a.Y.Zero() - -// return *a -// } - -// func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { -// a.X.FromLimbs(x) -// a.Y.FromLimbs(y) - -// return *a -// } - -// func (a G2Affine) ToProjective() G2Projective { -// var z G2BaseField - -// return G2Projective{ -// X: a.X, -// Y: a.Y, -// Z: z.One(), -// } -// } - -// func G2AffineFromProjective(p *G2Projective) G2Affine { -// return p.ProjectiveToAffine() -// } - -// func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { -// points := make([]G2Affine, size) -// for i := range points { -// points[i] = G2Affine{} -// } - -// pointsSlice := core.HostSliceFromElements[G2Affine](points) -// cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) -// cSize := (C.int)(size) -// C.bn254_g2_generate_affine_points(cPoints, cSize) - -// return pointsSlice -// } - -// func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { -// cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) -// cSize := (C.size_t)(points.Len()) -// cIsInto := (C._Bool)(isInto) -// defaultCtx, _ := cr.GetDefaultDeviceContext() -// cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) -// __ret := C.bn254_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) -// err := (cr.CudaError)(__ret) -// return err -// } - -// func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { -// points.CheckDevice() -// return convertG2AffinePointsMontgomery(points, true) -// } - -// func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { -// points.CheckDevice() -// return convertG2AffinePointsMontgomery(points, false) -// } - -// func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { -// cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) -// cSize := (C.size_t)(points.Len()) -// cIsInto := (C._Bool)(isInto) -// defaultCtx, _ := cr.GetDefaultDeviceContext() -// cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) -// __ret := C.bn254_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) -// err := (cr.CudaError)(__ret) -// return err -// } - -// func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { -// points.CheckDevice() -// return convertG2ProjectivePointsMontgomery(points, true) -// } - -// func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { -// points.CheckDevice() -// return convertG2ProjectivePointsMontgomery(points, false) -// } +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bn254_g2_eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bn254_g2_to_affine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254_g2_generate_projective_points(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254_g2_generate_affine_points(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bn254_g2_affine_convert_montgomery((*C.g2_affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.g2_affine_t)(cValues)) + err := runtime.EIcicleError(cErr) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { + points.CheckDevice() + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bn254_g2_projective_convert_montgomery((*C.g2_projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.g2_projective_t)(cValues)) + err := runtime.EIcicleError(cErr) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { + points.CheckDevice() + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang_v3/curves/bn254/g2/g2base_field.go b/wrappers/golang_v3/curves/bn254/g2/g2base_field.go index ab1c8404b..409a7d5ad 100644 --- a/wrappers/golang_v3/curves/bn254/g2/g2base_field.go +++ b/wrappers/golang_v3/curves/bn254/g2/g2base_field.go @@ -1,84 +1,84 @@ package g2 -// import ( -// "encoding/binary" -// "fmt" -// ) - -// const ( -// G2BASE_LIMBS int = 16 -// ) - -// type G2BaseField struct { -// limbs [G2BASE_LIMBS]uint32 -// } - -// func (f G2BaseField) Len() int { -// return int(G2BASE_LIMBS) -// } - -// func (f G2BaseField) Size() int { -// return int(G2BASE_LIMBS * 4) -// } - -// func (f G2BaseField) GetLimbs() []uint32 { -// return f.limbs[:] -// } - -// func (f G2BaseField) AsPointer() *uint32 { -// return &f.limbs[0] -// } - -// func (f *G2BaseField) FromUint32(v uint32) G2BaseField { -// f.limbs[0] = v -// return *f -// } - -// func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { -// if len(limbs) != f.Len() { -// panic("Called FromLimbs with limbs of different length than field") -// } -// for i := range f.limbs { -// f.limbs[i] = limbs[i] -// } - -// return *f -// } - -// func (f *G2BaseField) Zero() G2BaseField { -// for i := range f.limbs { -// f.limbs[i] = 0 -// } - -// return *f -// } - -// func (f *G2BaseField) One() G2BaseField { -// for i := range f.limbs { -// f.limbs[i] = 0 -// } -// f.limbs[0] = 1 - -// return *f -// } - -// func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { -// if len(bytes)/4 != f.Len() { -// panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) -// } - -// for i := range f.limbs { -// f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) -// } - -// return *f -// } - -// func (f G2BaseField) ToBytesLittleEndian() []byte { -// bytes := make([]byte, f.Len()*4) -// for i, v := range f.limbs { -// binary.LittleEndian.PutUint32(bytes[i*4:], v) -// } - -// return bytes -// } +import ( + "encoding/binary" + "fmt" +) + +const ( + G2BASE_LIMBS int = 16 +) + +type G2BaseField struct { + limbs [G2BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromUint32(v uint32) G2BaseField { + f.limbs[0] = v + return *f +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang_v3/curves/bn254/g2/include/curve.h b/wrappers/golang_v3/curves/bn254/g2/include/curve.h index e8863f1ef..147e4bc9a 100644 --- a/wrappers/golang_v3/curves/bn254/g2/include/curve.h +++ b/wrappers/golang_v3/curves/bn254/g2/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BN254_G2CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct g2_projective_t g2_projective_t; typedef struct g2_affine_t g2_affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool bn254_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bn254_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); void bn254_g2_generate_projective_points(g2_projective_t* points, int size); void bn254_g2_generate_affine_points(g2_affine_t* points, int size); -cudaError_t bn254_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t bn254_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int bn254_g2_affine_convert_montgomery(const g2_affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, g2_affine_t* d_out); +int bn254_g2_projective_convert_montgomery(const g2_projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, g2_projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/g2/include/msm.h b/wrappers/golang_v3/curves/bn254/g2/include/msm.h index 41f814526..d0907aac3 100644 --- a/wrappers/golang_v3/curves/bn254/g2/include/msm.h +++ b/wrappers/golang_v3/curves/bn254/g2/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BN254_G2MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct g2_projective_t g2_projective_t; typedef struct g2_affine_t g2_affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t bn254_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); -cudaError_t bn254_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out); -cudaError_t bn254_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out); +int bn254_g2_msm(const scalar_t* scalars, const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); +int bn254_g2_msm_precompute_bases(g2_affine_t* input_bases, int bases_size, MSMConfig* config, g2_affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/g2/msm.go b/wrappers/golang_v3/curves/bn254/g2/msm.go index b3a4538a5..9af57f53a 100644 --- a/wrappers/golang_v3/curves/bn254/g2/msm.go +++ b/wrappers/golang_v3/curves/bn254/g2/msm.go @@ -1,63 +1,48 @@ package g2 -// // #cgo CFLAGS: -I./include/ -// // #include "msm.h" -// import "C" - -// import ( -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" -// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" -// "unsafe" -// ) - -// func G2GetDefaultMSMConfig() core.MSMConfig { -// return core.GetDefaultMSMConfig() -// } - -// func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { -// scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) - -// cScalars := (*C.scalar_t)(scalarsPointer) -// cPoints := (*C.g2_affine_t)(pointsPointer) -// cResults := (*C.g2_projective_t)(resultsPointer) -// cSize := (C.int)(size) -// cCfg := (*C.MSMConfig)(cfgPointer) - -// __ret := C.bn254_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) -// err := (cr.CudaError)(__ret) -// return err -// } - -// // Deprecated: G2PrecomputeBases exists for backward compatibility. -// // It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// // G2PrecomputePoints should be used instead. -// func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { -// cfg := G2GetDefaultMSMConfig() -// cfg.PrecomputeFactor = precomputeFactor -// pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - -// cPoints := (*C.g2_affine_t)(pointsPointer) -// cPointsLen := (C.int)(points.Len()) -// cPrecomputeFactor := (C.int)(precomputeFactor) -// cC := (C.int)(c) -// cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) -// cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) -// cOutputBases := (*C.g2_affine_t)(outputBasesPointer) - -// __ret := C.bn254_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) -// err := (cr.CudaError)(__ret) -// return err -// } - -// func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { -// pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) - -// cPoints := (*C.g2_affine_t)(pointsPointer) -// cMsmSize := (C.int)(msmSize) -// cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) -// cOutputBases := (*C.g2_affine_t)(outputBasesPointer) - -// __ret := C.bn254_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) -// err := (cr.CudaError)(__ret) -// return err -// } +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) + + cScalars := (*C.scalar_t)(scalarsPointer) + cPoints := (*C.g2_affine_t)(pointsPointer) + cResults := (*C.g2_projective_t)(resultsPointer) + cSize := (C.int)(size) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bn254_g2_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err +} + +func G2PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) + + cBases := (*C.g2_affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + + __ret := C.bn254_g2_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) + return err +} diff --git a/wrappers/golang_v3/curves/bn254/include/curve.h b/wrappers/golang_v3/curves/bn254/include/curve.h index d42ac01b4..ee78b4658 100644 --- a/wrappers/golang_v3/curves/bn254/include/curve.h +++ b/wrappers/golang_v3/curves/bn254/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BN254_CURVE_H @@ -16,8 +15,8 @@ bool bn254_eq(projective_t* point1, projective_t* point2); void bn254_to_affine(projective_t* point, affine_t* point_out); void bn254_generate_projective_points(projective_t* points, int size); void bn254_generate_affine_points(affine_t* points, int size); -cudaError_t bn254_affine_convert_montgomery(const affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, affine_t* d_out); -cudaError_t bn254_projective_convert_montgomery(const projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, projective_t* d_out); +int bn254_affine_convert_montgomery(const affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, affine_t* d_out); +int bn254_projective_convert_montgomery(const projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/msm/include/msm.h b/wrappers/golang_v3/curves/bn254/msm/include/msm.h index 456e27878..5d35c59da 100644 --- a/wrappers/golang_v3/curves/bn254/msm/include/msm.h +++ b/wrappers/golang_v3/curves/bn254/msm/include/msm.h @@ -12,8 +12,8 @@ typedef struct projective_t projective_t; typedef struct affine_t affine_t; typedef struct MSMConfig MSMConfig; -int bn254_msm(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); -int bn254_msm_precompute_bases(affine_t* points, int bases_size, MSMConfig* config, affine_t* output_bases); +int bn254_msm(const scalar_t* scalars, const affine_t* points, int count, MSMConfig* config, projective_t* out); +int bn254_msm_precompute_bases(affine_t* input_bases, int bases_size, MSMConfig* config, affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bn254/msm/msm.go b/wrappers/golang_v3/curves/bn254/msm/msm.go index 4c90f1c53..b6358d44a 100644 --- a/wrappers/golang_v3/curves/bn254/msm/msm.go +++ b/wrappers/golang_v3/curves/bn254/msm/msm.go @@ -29,27 +29,6 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor return err } -// Deprecated: PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// PrecomputePoints should be used instead. -// func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) runtime.EIcicleError { -// cfg := GetDefaultMSMConfig() -// cfg.PrecomputeFactor = precomputeFactor -// pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - -// cPoints := (*C.affine_t)(pointsPointer) -// cPointsLen := (C.int)(points.Len()) -// cPrecomputeFactor := (C.int)(precomputeFactor) -// cC := (C.int)(c) -// cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) -// cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) -// cOutputBases := (*C.affine_t)(outputBasesPointer) - -// __ret := C.bn254_precompute_msm_bases(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) -// err := (runtime.EIcicleError)(__ret) -// return err -// } - func PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) diff --git a/wrappers/golang_v3/curves/bn254/tests/curve_test.go b/wrappers/golang_v3/curves/bn254/tests/curve_test.go index 128d3680c..b59b857e6 100644 --- a/wrappers/golang_v3/curves/bn254/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/curve_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go index 28dbf2920..9d2cbdaf2 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ecntt_test.go @@ -21,7 +21,6 @@ func TestECNtt(t *testing.T) { for _, size := range []int{4, 5, 6, 7, 8} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { - runtime.SetDevice(&DEVICE) testSize := 1 << size diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go index a36364085..6529ca483 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_curve_test.go @@ -1,103 +1,103 @@ package tests -// import ( -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" -// "github.com/stretchr/testify/assert" -// "testing" -// ) - -// func TestG2AffineZero(t *testing.T) { -// var fieldZero = g2.G2BaseField{} - -// var affineZero g2.G2Affine -// assert.Equal(t, affineZero.X, fieldZero) -// assert.Equal(t, affineZero.Y, fieldZero) - -// x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// var affine g2.G2Affine -// affine.FromLimbs(x, y) - -// affine.Zero() -// assert.Equal(t, affine.X, fieldZero) -// assert.Equal(t, affine.Y, fieldZero) -// } - -// func TestG2AffineFromLimbs(t *testing.T) { -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - -// var affine g2.G2Affine -// affine.FromLimbs(randLimbs, randLimbs2) - -// assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) -// assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) -// } - -// func TestG2AffineToProjective(t *testing.T) { -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// var fieldOne g2.G2BaseField -// fieldOne.One() - -// var expected g2.G2Projective -// expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) - -// var affine g2.G2Affine -// affine.FromLimbs(randLimbs, randLimbs2) - -// projectivePoint := affine.ToProjective() -// assert.Equal(t, expected, projectivePoint) -// } - -// func TestG2ProjectiveZero(t *testing.T) { -// var projectiveZero g2.G2Projective -// projectiveZero.Zero() -// var fieldZero = g2.G2BaseField{} -// var fieldOne g2.G2BaseField -// fieldOne.One() - -// assert.Equal(t, projectiveZero.X, fieldZero) -// assert.Equal(t, projectiveZero.Y, fieldOne) -// assert.Equal(t, projectiveZero.Z, fieldZero) - -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// var projective g2.G2Projective -// projective.FromLimbs(randLimbs, randLimbs, randLimbs) - -// projective.Zero() -// assert.Equal(t, projective.X, fieldZero) -// assert.Equal(t, projective.Y, fieldOne) -// assert.Equal(t, projective.Z, fieldZero) -// } - -// func TestG2ProjectiveFromLimbs(t *testing.T) { -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) - -// var projective g2.G2Projective -// projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) - -// assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) -// assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) -// assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) -// } - -// func TestG2ProjectiveFromAffine(t *testing.T) { -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// var fieldOne g2.G2BaseField -// fieldOne.One() - -// var expected g2.G2Projective -// expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) - -// var affine g2.G2Affine -// affine.FromLimbs(randLimbs, randLimbs2) - -// var projectivePoint g2.G2Projective -// projectivePoint.FromAffine(affine) -// assert.Equal(t, expected, projectivePoint) -// } +import ( + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = g2.G2BaseField{} + + var affineZero g2.G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var affine g2.G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero g2.G2Projective + projectiveZero.Zero() + var fieldZero = g2.G2BaseField{} + var fieldOne g2.G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + + var projective g2.G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + var fieldOne g2.G2BaseField + fieldOne.One() + + var expected g2.G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:]) + + var affine g2.G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint g2.G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go index 024c05f2a..08b3cba5d 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_g2base_field_test.go @@ -1,88 +1,88 @@ package tests -// import ( -// bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" -// "github.com/stretchr/testify/assert" -// "testing" -// ) - -// const ( -// G2BASE_LIMBS = bn254.G2BASE_LIMBS -// ) - -// func TestG2BaseFieldFromLimbs(t *testing.T) { -// emptyField := bn254.G2BaseField{} -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// emptyField.FromLimbs(randLimbs[:]) -// assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") -// randLimbs[0] = 100 -// assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) -// } - -// func TestG2BaseFieldGetLimbs(t *testing.T) { -// emptyField := bn254.G2BaseField{} -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// emptyField.FromLimbs(randLimbs[:]) - -// assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") -// } - -// func TestG2BaseFieldOne(t *testing.T) { -// var emptyField bn254.G2BaseField -// emptyField.One() -// limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS)) -// assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") - -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// emptyField.FromLimbs(randLimbs[:]) - -// emptyField.One() -// assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") -// } - -// func TestG2BaseFieldZero(t *testing.T) { -// var emptyField bn254.G2BaseField -// emptyField.Zero() -// limbsZero := make([]uint32, G2BASE_LIMBS) -// assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") - -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// emptyField.FromLimbs(randLimbs[:]) - -// emptyField.Zero() -// assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") -// } - -// func TestG2BaseFieldSize(t *testing.T) { -// var emptyField bn254.G2BaseField -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// emptyField.FromLimbs(randLimbs[:]) - -// assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") -// } - -// func TestG2BaseFieldAsPointer(t *testing.T) { -// var emptyField bn254.G2BaseField -// randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) -// emptyField.FromLimbs(randLimbs[:]) - -// assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") -// } - -// func TestG2BaseFieldFromBytes(t *testing.T) { -// var emptyField bn254.G2BaseField -// bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) - -// emptyField.FromBytesLittleEndian(bytes) - -// assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") -// } - -// func TestG2BaseFieldToBytes(t *testing.T) { -// var emptyField bn254.G2BaseField -// expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) -// emptyField.FromLimbs(limbs) - -// assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") -// } +import ( + bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + G2BASE_LIMBS = bn254.G2BASE_LIMBS +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := bn254.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.GetLimbs()) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := bn254.G2BaseField{} + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField bn254.G2BaseField + emptyField.One() + limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField bn254.G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField bn254.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField bn254.G2BaseField + randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField bn254.G2BaseField + bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField bn254.G2BaseField + expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go index 914039b37..d4a49120a 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go @@ -1,371 +1,428 @@ package tests -// import ( -// "fmt" -// "sync" -// "testing" - -// "github.com/stretchr/testify/assert" - -// "github.com/consensys/gnark-crypto/ecc" -// "github.com/consensys/gnark-crypto/ecc/bn254" -// "github.com/consensys/gnark-crypto/ecc/bn254/fp" -// "github.com/consensys/gnark-crypto/ecc/bn254/fr" - -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" -// cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" -// icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" -// "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" -// ) - -// func projectiveToGnarkAffineG2(p g2.G2Projective) bn254.G2Affine { -// pxBytes := p.X.ToBytesLittleEndian() -// pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) -// pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) -// x := bn254.E2{ -// A0: pxA0, -// A1: pxA1, -// } - -// pyBytes := p.Y.ToBytesLittleEndian() -// pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) -// pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) -// y := bn254.E2{ -// A0: pyA0, -// A1: pyA1, -// } - -// pzBytes := p.Z.ToBytesLittleEndian() -// pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) -// pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) -// z := bn254.E2{ -// A0: pzA0, -// A1: pzA1, -// } - -// var zSquared bn254.E2 -// zSquared.Mul(&z, &z) - -// var X bn254.E2 -// X.Mul(&x, &z) - -// var Y bn254.E2 -// Y.Mul(&y, &zSquared) - -// g2Jac := bn254.G2Jac{ -// X: X, -// Y: Y, -// Z: z, -// } - -// var g2Affine bn254.G2Affine -// return *g2Affine.FromJacobian(&g2Jac) -// } - -// func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBn254.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { -// scalarsFr := make([]fr.Element, len(scalars)) -// for i, v := range scalars { -// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) -// scalarsFr[i] = slice64 -// } - -// pointsFp := make([]bn254.G2Affine, len(points)) -// for i, v := range points { -// pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) -// } - -// return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) -// } - -// func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bn254.G2Affine], out g2.G2Projective) bool { -// var msmRes bn254.G2Jac -// msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - -// var icicleResAsJac bn254.G2Jac -// proj := projectiveToGnarkAffineG2(out) -// icicleResAsJac.FromAffine(&proj) - -// return msmRes.Equal(&icicleResAsJac) -// } - -// func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bn254.G2Affine { -// points := make([]bn254.G2Affine, len(iciclePoints)) -// for index, iciclePoint := range iciclePoints { -// xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian()) -// xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes]) -// xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:]) -// xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes) -// xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes) - -// yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian()) -// yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes]) -// yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:]) -// yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes) -// yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes) - -// points[index] = bn254.G2Affine{ -// X: bn254.E2{ -// A0: xA0Elem, -// A1: xA1Elem, -// }, -// Y: bn254.E2{ -// A0: yA0Elem, -// A1: yA1Elem, -// }, -// } -// } - -// return points -// } - -// func TestMSMG2(t *testing.T) { -// cfg := g2.G2GetDefaultMSMConfig() -// cfg.IsAsync = true -// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { -// size := 1 << power - -// scalars := icicleBn254.GenerateScalars(size) -// points := g2.G2GenerateAffinePoints(size) - -// stream, _ := cr.CreateStream() -// var p g2.G2Projective -// var out core.DeviceSlice -// _, e := out.MallocAsync(p.Size(), p.Size(), stream) -// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") -// cfg.Ctx.Stream = &stream - -// e = g2.G2Msm(scalars, points, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") -// outHost := make(core.HostSlice[g2.G2Projective], 1) -// outHost.CopyFromDeviceAsync(&out, stream) -// out.FreeAsync(stream) - -// cr.SynchronizeStream(&stream) -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - -// } -// } - -// func TestMSMG2PinnedHostMemory(t *testing.T) { -// cfg := g2.G2GetDefaultMSMConfig() -// for _, power := range []int{10} { -// size := 1 << power - -// scalars := icicleBn254.GenerateScalars(size) -// points := g2.G2GenerateAffinePoints(size) - -// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) -// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - -// pinnableAndLockable := pinnable == 1 && lockable == 0 - -// var pinnedPoints core.HostSlice[g2.G2Affine] -// if pinnableAndLockable { -// points.Pin(cr.CudaHostRegisterDefault) -// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) -// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") -// } - -// var p g2.G2Projective -// var out core.DeviceSlice -// _, e := out.Malloc(p.Size(), p.Size()) -// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") -// outHost := make(core.HostSlice[g2.G2Projective], 1) - -// e = g2.G2Msm(scalars, points, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - -// outHost.CopyFromDevice(&out) -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - -// if pinnableAndLockable { -// e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - -// outHost.CopyFromDevice(&out) -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) - -// } - -// out.Free() - -// if pinnableAndLockable { -// points.Unpin() -// pinnedPoints.FreePinned() -// } -// } -// } -// func TestMSMG2GnarkCryptoTypes(t *testing.T) { -// cfg := g2.G2GetDefaultMSMConfig() -// for _, power := range []int{3} { -// size := 1 << power - -// scalars := make([]fr.Element, size) -// var x fr.Element -// for i := 0; i < size; i++ { -// x.SetRandom() -// scalars[i] = x -// } -// scalarsHost := (core.HostSlice[fr.Element])(scalars) -// points := g2.G2GenerateAffinePoints(size) -// pointsGnark := convertIcicleG2AffineToG2Affine(points) -// pointsHost := (core.HostSlice[bn254.G2Affine])(pointsGnark) - -// var p g2.G2Projective -// var out core.DeviceSlice -// _, e := out.Malloc(p.Size(), p.Size()) -// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") -// cfg.ArePointsMontgomeryForm = true -// cfg.AreScalarsMontgomeryForm = true - -// e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") -// outHost := make(core.HostSlice[g2.G2Projective], 1) -// outHost.CopyFromDevice(&out) -// out.Free() - -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) -// } -// } - -// func TestMSMG2Batch(t *testing.T) { -// cfg := g2.G2GetDefaultMSMConfig() -// for _, power := range []int{10, 16} { -// for _, batchSize := range []int{1, 3, 16} { -// size := 1 << power -// totalSize := size * batchSize -// scalars := icicleBn254.GenerateScalars(totalSize) -// points := g2.G2GenerateAffinePoints(totalSize) - -// var p g2.G2Projective -// var out core.DeviceSlice -// _, e := out.Malloc(batchSize*p.Size(), p.Size()) -// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - -// e = g2.G2Msm(scalars, points, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") -// outHost := make(core.HostSlice[g2.G2Projective], batchSize) -// outHost.CopyFromDevice(&out) -// out.Free() -// // Check with gnark-crypto -// for i := 0; i < batchSize; i++ { -// scalarsSlice := scalars[i*size : (i+1)*size] -// pointsSlice := points[i*size : (i+1)*size] -// out := outHost[i] -// assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) -// } -// } -// } -// } - -// func TestPrecomputePointsG2(t *testing.T) { -// cfg := g2.G2GetDefaultMSMConfig() -// const precomputeFactor = 8 -// cfg.PrecomputeFactor = precomputeFactor - -// for _, power := range []int{10, 16} { -// for _, batchSize := range []int{1, 3, 16} { -// size := 1 << power -// totalSize := size * batchSize -// scalars := icicleBn254.GenerateScalars(totalSize) -// points := g2.G2GenerateAffinePoints(totalSize) - -// var precomputeOut core.DeviceSlice -// _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) -// assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") - -// e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) -// assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") - -// var p g2.G2Projective -// var out core.DeviceSlice -// _, e = out.Malloc(batchSize*p.Size(), p.Size()) -// assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") - -// e = g2.G2Msm(scalars, precomputeOut, &cfg, out) -// assert.Equal(t, cr.CudaSuccess, e, "Msm failed") -// outHost := make(core.HostSlice[g2.G2Projective], batchSize) -// outHost.CopyFromDevice(&out) -// out.Free() -// precomputeOut.Free() -// // Check with gnark-crypto -// for i := 0; i < batchSize; i++ { -// scalarsSlice := scalars[i*size : (i+1)*size] -// pointsSlice := points[i*size : (i+1)*size] -// out := outHost[i] -// assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) -// } -// } -// } -// } - -// func TestMSMG2SkewedDistribution(t *testing.T) { -// cfg := g2.G2GetDefaultMSMConfig() -// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { -// size := 1 << power - -// scalars := icicleBn254.GenerateScalars(size) -// for i := size / 4; i < size; i++ { -// scalars[i].One() -// } -// points := g2.G2GenerateAffinePoints(size) -// for i := 0; i < size/4; i++ { -// points[i].Zero() -// } - -// var p g2.G2Projective -// var out core.DeviceSlice -// _, e := out.Malloc(p.Size(), p.Size()) -// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - -// e = g2.G2Msm(scalars, points, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") -// outHost := make(core.HostSlice[g2.G2Projective], 1) -// outHost.CopyFromDevice(&out) -// out.Free() -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) -// } -// } - -// func TestMSMG2MultiDevice(t *testing.T) { -// numDevices, _ := cr.GetDeviceCount() -// fmt.Println("There are ", numDevices, " devices available") -// wg := sync.WaitGroup{} - -// for i := 0; i < numDevices; i++ { -// wg.Add(1) -// cr.RunOnDevice(i, func(args ...any) { -// defer wg.Done() -// cfg := g2.G2GetDefaultMSMConfig() -// cfg.IsAsync = true -// for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { -// size := 1 << power -// scalars := icicleBn254.GenerateScalars(size) -// points := g2.G2GenerateAffinePoints(size) - -// stream, _ := cr.CreateStream() -// var p g2.G2Projective -// var out core.DeviceSlice -// _, e := out.MallocAsync(p.Size(), p.Size(), stream) -// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") -// cfg.Ctx.Stream = &stream - -// e = g2.G2Msm(scalars, points, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm failed") -// outHost := make(core.HostSlice[g2.G2Projective], 1) -// outHost.CopyFromDeviceAsync(&out, stream) -// out.FreeAsync(stream) - -// cr.SynchronizeStream(&stream) -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) -// } -// }) -// } -// wg.Wait() -// } +import ( + "fmt" + "sync" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" + icicleBn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bn254/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" +) + +func projectiveToGnarkAffineG2(p g2.G2Projective) bn254.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := bn254.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := bn254.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := bn254.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared bn254.E2 + zSquared.Mul(&z, &z) + + var X bn254.E2 + X.Mul(&x, &z) + + var Y bn254.E2 + Y.Mul(&y, &zSquared) + + g2Jac := bn254.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine bn254.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} + +func testAgainstGnarkCryptoMsmG2(t *testing.T, scalars core.HostSlice[icicleBn254.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bn254.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + + testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t, scalarsFr, pointsFp, out) +} + +func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bn254.G2Affine], out g2.G2Projective) { + var msmRes bn254.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var msmResAffine bn254.G2Affine + msmResAffine.FromJacobian(&msmRes) + + icicleResAffine := projectiveToGnarkAffineG2(out) + + assert.Equal(t, msmResAffine, icicleResAffine) +} + +func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bn254.G2Affine { + points := make([]bn254.G2Affine, len(iciclePoints)) + for index, iciclePoint := range iciclePoints { + xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian()) + xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes]) + xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:]) + xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes) + xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes) + + yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian()) + yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes]) + yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:]) + yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes) + yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes) + + points[index] = bn254.G2Affine{ + X: bn254.E2{ + A0: xA0Elem, + A1: xA1Elem, + }, + Y: bn254.E2{ + A0: yA0Elem, + A1: yA1Elem, + }, + } + } + + return points +} + +func TestMSMG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power + + scalars := icicleBn254.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := runtime.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, runtime.Success, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + runtime.SynchronizeStream(stream) + // Check with gnark-crypto + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) + } +} + +// func TestMSMG2PinnedHostMemory(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleBn254.GenerateScalars(size) +// points := g2.G2GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[g2.G2Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) +// +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) +// +// +// if pinnableAndLockable { +// e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) +// +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } +func TestMSMG2GnarkCryptoTypes(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{3} { + runtime.SetDevice(&DEVICE) + size := 1 << power + + scalars := make([]fr.Element, size) + var x fr.Element + for i := 0; i < size; i++ { + x.SetRandom() + scalars[i] = x + } + scalarsHost := (core.HostSlice[fr.Element])(scalars) + points := g2.G2GenerateAffinePoints(size) + pointsGnark := convertIcicleG2AffineToG2Affine(points) + pointsHost := (core.HostSlice[bn254.G2Affine])(pointsGnark) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + + e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) + assert.Equal(t, e, runtime.Success, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, runtime.Success, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestPrecomputePointsG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(totalSize) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = g2.G2PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestPrecomputePointsSharedBasesG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBn254.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = g2.G2PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0:size] + out := outHost[i] + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + + scalars := icicleBn254.GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := g2.G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, runtime.Success, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + // Check with gnark-crypto + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) + } +} + +func TestMSMG2MultiDevice(t *testing.T) { + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") + wg := sync.WaitGroup{} + + for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} + wg.Add(1) + runtime.RunOnDevice(¤tDevice, func(args ...any) { + defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + + cfg := g2.G2GetDefaultMSMConfig() + cfg.IsAsync = true + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + scalars := icicleBn254.GenerateScalars(size) + points := g2.G2GenerateAffinePoints(size) + + stream, _ := runtime.CreateStream() + var p g2.G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream + + e = g2.G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, runtime.Success, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], 1) + outHost.CopyFromDeviceAsync(&out, stream) + out.FreeAsync(stream) + + runtime.SynchronizeStream(stream) + // Check with gnark-crypto + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) + } + }) + } + wg.Wait() +} diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index 21d252c8c..7011c0052 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -82,7 +82,7 @@ func convertIcicleAffineToG1Affine(iciclePoints []icicleBn254.Affine) []bn254.G1 func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 10} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -90,12 +90,10 @@ func TestMSM(t *testing.T) { points := icicleBn254.GenerateAffinePoints(size) stream, _ := runtime.CreateStream() - defer runtime.DestroyStream(stream) var p icicleBn254.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") - cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) @@ -110,51 +108,52 @@ func TestMSM(t *testing.T) { } } -// func TestMSMPinnedHostMemory(t *testing.T) { -// cfg := msm.GetDefaultMSMConfig() -// for _, power := range []int{10} { -// size := 1 << power - -// scalars := icicleBn254.GenerateScalars(size) -// points := icicleBn254.GenerateAffinePoints(size) - -// pinnable := runtime.GetDeviceAttribute(runtime.CudaDevAttrHostRegisterSupported, 0) -// lockable := runtime.GetDeviceAttribute(runtime.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - -// pinnableAndLockable := pinnable == 1 && lockable == 0 - -// var pinnedPoints core.HostSlice[icicleBn254.Affine] -// if pinnableAndLockable { -// points.Pin(runtime.CudaHostRegisterDefault) -// pinnedPoints, _ = points.AllocPinned(runtime.CudaHostAllocDefault) -// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") -// } - -// var p icicleBn254.Projective -// var out core.DeviceSlice -// _, e := out.Malloc(p.Size(), p.Size()) -// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") -// outHost := make(core.HostSlice[icicleBn254.Projective], 1) - -// e = msm.Msm(scalars, points, &cfg, out) -// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") - -// outHost.CopyFromDevice(&out) -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - -// if pinnableAndLockable { -// e = msm.Msm(scalars, pinnedPoints, &cfg, out) -// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") - -// outHost.CopyFromDevice(&out) -// // Check with gnark-crypto -// assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) - -// } - -// out.Free() - +// func TestMSMPinnedHostMemory(t *testing.T) { +// cfg := msm.GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleBn254.GenerateScalars(size) +// points := icicleBn254.GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[icicleBn254.Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p icicleBn254.Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[icicleBn254.Projective], 1) +// +// e = msm.Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) +// +// +// if pinnableAndLockable { +// e = msm.Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) +// +// } +// +// out.Free() +// // if pinnableAndLockable { // points.Unpin() // pinnedPoints.FreePinned() @@ -170,7 +169,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { scalars := make([]fr.Element, size) var x fr.Element for i := 0; i < size; i++ { - x.SetInt64(int64(10000 * (i + 1))) + x.SetRandom() scalars[i] = x } scalarsHost := (core.HostSlice[fr.Element])(scalars) @@ -187,7 +186,6 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { e = msm.Msm(scalarsHost, pointsHost, &cfg, out) assert.Equal(t, e, runtime.Success, "Msm failed") - assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBn254.Projective], 1) outHost.CopyFromDevice(&out) out.Free() @@ -199,8 +197,8 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{5} { - for _, batchSize := range []int{1, 3} { + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -229,12 +227,12 @@ func TestMSMBatch(t *testing.T) { } func TestPrecomputePoints(t *testing.T) { - cfg := core.GetDefaultMSMConfig() + cfg := msm.GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10} { - for _, batchSize := range []int{1, 3, 5, 16} { + for _, batchSize := range []int{1, 3, 16} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -272,13 +270,14 @@ func TestPrecomputePoints(t *testing.T) { } } } + func TestPrecomputePointsSharedBases(t *testing.T) { - cfg := core.GetDefaultMSMConfig() + cfg := msm.GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10} { - for _, batchSize := range []int{1, 3, 5, 16} { + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -352,7 +351,7 @@ func TestMSMMultiDevice(t *testing.T) { wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { - currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: i} + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() @@ -361,7 +360,7 @@ func TestMSMMultiDevice(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { size := 1 << power scalars := icicleBn254.GenerateScalars(size) points := icicleBn254.GenerateAffinePoints(size) @@ -386,5 +385,4 @@ func TestMSMMultiDevice(t *testing.T) { }) } wg.Wait() - } diff --git a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go index 6f226d254..78ff69641 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go @@ -51,10 +51,7 @@ func testAgainstGnarkCryptoNttGnarkTypes(t *testing.T, size int, scalarsFr core. if order == core.KNN || order == core.KRR { fft.BitReverse(scalarsFr) } - // println(scalarsFr[0].String()) - // println(outputAsFr[0].String()) assert.Equal(t, scalarsFr, outputAsFr) - // return reflect.DeepEqual(scalarsFr, outputAsFr) } func TestNTTGetDefaultConfig(t *testing.T) { actual := ntt.GetDefaultNttConfig() @@ -76,7 +73,7 @@ func TestNtt(t *testing.T) { cfg := ntt.GetDefaultNttConfig() scalars := bn254.GenerateScalars(1 << largestTestSize) - for _, size := range []int{4, 8} { + for _, size := range []int{4, largestTestSize} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { runtime.SetDevice(&DEVICE) @@ -87,11 +84,7 @@ func TestNtt(t *testing.T) { // run ntt output := make(core.HostSlice[bn254.ScalarField], testSize) - err := ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) - if err == runtime.ApiNotImplemented { - t.Skipf("NTT is not implemented for %s device type. Skipping test", DEVICE.GetDeviceType()) - } - assert.Equal(t, runtime.Success, err) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, core.KForward) @@ -118,11 +111,7 @@ func TestNttFrElement(t *testing.T) { // run ntt output := make(core.HostSlice[fr.Element], testSize) - err := ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) - if err == runtime.ApiNotImplemented { - t.Skipf("NTT is not implemented for %s device type. Skipping test", DEVICE.GetDeviceType()) - } - assert.Equal(t, runtime.Success, err) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto testAgainstGnarkCryptoNttGnarkTypes(t, testSize, scalarsCopy, output, v, core.KForward) @@ -143,32 +132,24 @@ func TestNttDeviceAsync(t *testing.T) { scalarsCopy := core.HostSliceFromElements[bn254.ScalarField](scalars[:testSize]) stream, _ := runtime.CreateStream() - defer runtime.DestroyStream(stream) cfg.Ordering = v cfg.IsAsync = true cfg.StreamHandle = stream var deviceInput core.DeviceSlice - defer deviceInput.FreeAsync(stream) scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) var deviceOutput core.DeviceSlice - defer deviceOutput.FreeAsync(stream) deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) // run ntt - err := ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) - if err == runtime.ApiNotImplemented { - t.Skipf("NTT is not implemented for %s device type. Skipping test", DEVICE.GetDeviceType()) - } - assert.Equal(t, runtime.Success, err) + ntt.Ntt(deviceInput, direction, &cfg, deviceOutput) output := make(core.HostSlice[bn254.ScalarField], testSize) output.CopyFromDeviceAsync(&deviceOutput, stream) runtime.SynchronizeStream(stream) // Compare with gnark-crypto testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, direction) - } } } @@ -193,11 +174,7 @@ func TestNttBatch(t *testing.T) { cfg.BatchSize = int32(batchSize) // run ntt output := make(core.HostSlice[bn254.ScalarField], totalSize) - err := ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) - if err == runtime.ApiNotImplemented { - t.Skip("NTT is not implemented for ", DEVICE.GetDeviceType(), " device type. Skipping test") - } - assert.Equal(t, runtime.Success, err) + ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto domainWithPrecompute := fft.NewDomain(uint64(testSize)) diff --git a/wrappers/golang_v3/curves/bw6761/curve.go b/wrappers/golang_v3/curves/bw6761/curve.go index 13cd1a3aa..9d12d46de 100644 --- a/wrappers/golang_v3/curves/bw6761/curve.go +++ b/wrappers/golang_v3/curves/bw6761/curve.go @@ -8,7 +8,7 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) type Projective struct { @@ -134,44 +134,38 @@ func GenerateAffinePoints(size int) core.HostSlice[Affine] { return pointsSlice } -func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bw6_761_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bw6_761_affine_convert_montgomery((*C.affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, true) } -func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, false) } -func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bw6_761_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bw6_761_projective_convert_montgomery((*C.projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, true) } -func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go b/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go index 76fa366e0..949cd945c 100644 --- a/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go +++ b/wrappers/golang_v3/curves/bw6761/ecntt/ecntt.go @@ -6,10 +6,10 @@ import "C" import ( "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) cPoints := (*C.projective_t)(pointsPointer) @@ -18,7 +18,7 @@ func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTC cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.projective_t)(resultsPointer) - __ret := C.bw6_761_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.bw6_761_ecntt(cPoints, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } diff --git a/wrappers/golang_v3/curves/bw6761/ecntt/include/ecntt.h b/wrappers/golang_v3/curves/bw6761/ecntt/include/ecntt.h index 9c0cf0eff..dc1cea361 100644 --- a/wrappers/golang_v3/curves/bw6761/ecntt/include/ecntt.h +++ b/wrappers/golang_v3/curves/bw6761/ecntt/include/ecntt.h @@ -10,7 +10,7 @@ extern "C" { typedef struct NTTConfig NTTConfig; typedef struct projective_t projective_t; -cudaError_t bw6_761_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); +int bw6_761_ecntt(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bw6761/g2/curve.go b/wrappers/golang_v3/curves/bw6761/g2/curve.go index 8a8bf37e7..8e3bca532 100644 --- a/wrappers/golang_v3/curves/bw6761/g2/curve.go +++ b/wrappers/golang_v3/curves/bw6761/g2/curve.go @@ -8,7 +8,7 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) type G2Projective struct { @@ -134,44 +134,38 @@ func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { return pointsSlice } -func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.g2_affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bw6_761_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bw6_761_g2_affine_convert_montgomery((*C.g2_affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.g2_affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2AffinePointsMontgomery(points, true) } -func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2AffinePointsMontgomery(points, false) } -func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.g2_projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.bw6_761_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.bw6_761_g2_projective_convert_montgomery((*C.g2_projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.g2_projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2ProjectivePointsMontgomery(points, true) } -func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertG2ProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/curves/bw6761/g2/include/curve.h b/wrappers/golang_v3/curves/bw6761/g2/include/curve.h index b57b55cfc..ae2fa409f 100644 --- a/wrappers/golang_v3/curves/bw6761/g2/include/curve.h +++ b/wrappers/golang_v3/curves/bw6761/g2/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BW6_761_G2CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct g2_projective_t g2_projective_t; typedef struct g2_affine_t g2_affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool bw6_761_g2_eq(g2_projective_t* point1, g2_projective_t* point2); void bw6_761_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out); void bw6_761_g2_generate_projective_points(g2_projective_t* points, int size); void bw6_761_g2_generate_affine_points(g2_affine_t* points, int size); -cudaError_t bw6_761_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t bw6_761_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int bw6_761_g2_affine_convert_montgomery(const g2_affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, g2_affine_t* d_out); +int bw6_761_g2_projective_convert_montgomery(const g2_projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, g2_projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bw6761/g2/include/msm.h b/wrappers/golang_v3/curves/bw6761/g2/include/msm.h index 3c0ff4cad..710918202 100644 --- a/wrappers/golang_v3/curves/bw6761/g2/include/msm.h +++ b/wrappers/golang_v3/curves/bw6761/g2/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BW6_761_G2MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct g2_projective_t g2_projective_t; typedef struct g2_affine_t g2_affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t bw6_761_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); -cudaError_t bw6_761_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out); -cudaError_t bw6_761_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out); +int bw6_761_g2_msm(const scalar_t* scalars, const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); +int bw6_761_g2_msm_precompute_bases(g2_affine_t* input_bases, int bases_size, MSMConfig* config, g2_affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bw6761/g2/msm.go b/wrappers/golang_v3/curves/bw6761/g2/msm.go index 7daae627d..ee829a8c4 100644 --- a/wrappers/golang_v3/curves/bw6761/g2/msm.go +++ b/wrappers/golang_v3/curves/bw6761/g2/msm.go @@ -8,57 +8,41 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func G2GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.g2_affine_t)(pointsPointer) cResults := (*C.g2_projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) - - __ret := C.bw6_761_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) - return err -} - -// Deprecated: G2PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// G2PrecomputePoints should be used instead. -func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := G2GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.g2_affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.g2_affine_t)(outputBasesPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) - __ret := C.bw6_761_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bw6_761_g2_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } -func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func G2PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.g2_affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cBases := (*C.g2_affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.g2_affine_t)(outputBasesPointer) - __ret := C.bw6_761_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bw6_761_g2_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bw6761/include/curve.h b/wrappers/golang_v3/curves/bw6761/include/curve.h index cc6e401cb..e568210a3 100644 --- a/wrappers/golang_v3/curves/bw6761/include/curve.h +++ b/wrappers/golang_v3/curves/bw6761/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BW6_761_CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct projective_t projective_t; typedef struct affine_t affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool bw6_761_eq(projective_t* point1, projective_t* point2); void bw6_761_to_affine(projective_t* point, affine_t* point_out); void bw6_761_generate_projective_points(projective_t* points, int size); void bw6_761_generate_affine_points(affine_t* points, int size); -cudaError_t bw6_761_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t bw6_761_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int bw6_761_affine_convert_montgomery(const affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, affine_t* d_out); +int bw6_761_projective_convert_montgomery(const projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bw6761/main.go b/wrappers/golang_v3/curves/bw6761/main.go index 9e7f9462c..d93ca331e 100644 --- a/wrappers/golang_v3/curves/bw6761/main.go +++ b/wrappers/golang_v3/curves/bw6761/main.go @@ -1,4 +1,4 @@ package bw6761 -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bw6_761 -lingo_field_bw6_761 -lstdc++ -lm +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bw6_761 -licicle_curve_bw6_761 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build import "C" diff --git a/wrappers/golang_v3/curves/bw6761/msm/include/msm.h b/wrappers/golang_v3/curves/bw6761/msm/include/msm.h index 883917079..e2eef31c4 100644 --- a/wrappers/golang_v3/curves/bw6761/msm/include/msm.h +++ b/wrappers/golang_v3/curves/bw6761/msm/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _BW6_761_MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct projective_t projective_t; typedef struct affine_t affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t bw6_761_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); -cudaError_t bw6_761_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); -cudaError_t bw6_761_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); +int bw6_761_msm(const scalar_t* scalars, const affine_t* points, int count, MSMConfig* config, projective_t* out); +int bw6_761_msm_precompute_bases(affine_t* input_bases, int bases_size, MSMConfig* config, affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/bw6761/msm/msm.go b/wrappers/golang_v3/curves/bw6761/msm/msm.go index 8da18f78f..39334c2f9 100644 --- a/wrappers/golang_v3/curves/bw6761/msm/msm.go +++ b/wrappers/golang_v3/curves/bw6761/msm/msm.go @@ -8,57 +8,41 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.affine_t)(pointsPointer) cResults := (*C.projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) - - __ret := C.bw6_761_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) - return err -} - -// Deprecated: PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// PrecomputePoints should be used instead. -func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.affine_t)(outputBasesPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) - __ret := C.bw6_761_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bw6_761_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } -func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cBases := (*C.affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.affine_t)(outputBasesPointer) - __ret := C.bw6_761_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.bw6_761_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/bw6761/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/bw6761/poseidon/include/poseidon.h deleted file mode 100644 index 1731d1058..000000000 --- a/wrappers/golang_v3/curves/bw6761/poseidon/include/poseidon.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#ifndef _BW6_761_POSEIDON_H -#define _BW6_761_POSEIDON_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct scalar_t scalar_t; -typedef struct PoseidonConfig PoseidonConfig; -typedef struct DeviceContext DeviceContext; -typedef struct PoseidonConstants PoseidonConstants; - - -cudaError_t bw6_761_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); -cudaError_t bw6_761_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); -cudaError_t bw6_761_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go b/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go deleted file mode 100644 index aaa5c4bb2..000000000 --- a/wrappers/golang_v3/curves/bw6761/poseidon/poseidon.go +++ /dev/null @@ -1,57 +0,0 @@ -package poseidon - -// #cgo CFLAGS: -I./include/ -// #include "poseidon.h" -import "C" - -import ( - "unsafe" - - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" -) - -func GetDefaultPoseidonConfig() core.PoseidonConfig { - return core.GetDefaultPoseidonConfig() -} - -func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { - scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) - - cScalars := (*C.scalar_t)(scalarsPointer) - cResults := (*C.scalar_t)(resultsPointer) - cNumberOfStates := (C.int)(numberOfStates) - cArity := (C.int)(constants.Arity) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - cCfg := (*C.PoseidonConfig)(cfgPointer) - - __ret := C.bw6_761_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) - - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cFullRoundsHalfs := (C.int)(fullRoundsHalfs) - cPartialRounds := (C.int)(partialRounds) - cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) - - __ret := C.bw6_761_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - - __ret := C.bw6_761_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} diff --git a/wrappers/golang_v3/curves/bw6761/tests/curve_test.go b/wrappers/golang_v3/curves/bw6761/tests/curve_test.go index f862281ab..7903df6c1 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/curve_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/curve_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go b/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go index dcc89caff..4708b484b 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/ecntt_test.go @@ -7,24 +7,30 @@ import ( bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/ecntt" ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "github.com/stretchr/testify/assert" ) func TestECNtt(t *testing.T) { cfg := ntt.GetDefaultNttConfig() + ext := runtime.CreateConfigExtension() + ext.SetInt(core.CUDA_NTT_ALGORITHM, int(core.Radix2)) + cfg.Ext = ext.AsUnsafePointer() + points := bw6_761.GenerateProjectivePoints(1 << largestTestSize) for _, size := range []int{4, 5, 6, 7, 8} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size pointsCopy := core.HostSliceFromElements[bw6_761.Projective](points[:testSize]) cfg.Ordering = v - cfg.NttAlgorithm = core.Radix2 output := make(core.HostSlice[bw6_761.Projective], testSize) e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + assert.Equal(t, runtime.Success, e, "ECNtt failed") } } } diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go index 9df68cb59..017e753cc 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_curve_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/g2" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) func TestG2AffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go index bfea6cee0..aadf3daaf 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761" + "github.com/consensys/gnark-crypto/ecc/bw6-761" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" icicleBw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/g2" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func projectiveToGnarkAffineG2(p g2.G2Projective) bw6761.G2Affine { @@ -35,7 +35,7 @@ func projectiveToGnarkAffineG2(p g2.G2Projective) bw6761.G2Affine { return bw6761.G2Affine{X: *x, Y: *y} } -func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBw6_761.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool { +func testAgainstGnarkCryptoMsmG2(t *testing.T, scalars core.HostSlice[icicleBw6_761.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) { scalarsFr := make([]fr.Element, len(scalars)) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -47,18 +47,19 @@ func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBw6_761.ScalarFiel pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) } - return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out) + testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t, scalarsFr, pointsFp, out) } -func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bw6761.G2Affine], out g2.G2Projective) bool { +func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bw6761.G2Affine], out g2.G2Projective) { var msmRes bw6761.G2Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - var icicleResAsJac bw6761.G2Jac - proj := projectiveToGnarkAffineG2(out) - icicleResAsJac.FromAffine(&proj) + var msmResAffine bw6761.G2Affine + msmResAffine.FromJacobian(&msmRes) - return msmRes.Equal(&icicleResAsJac) + icicleResAffine := projectiveToGnarkAffineG2(out) + + assert.Equal(t, msmResAffine, icicleResAffine) } func convertIcicleAffineToG2Affine(iciclePoints []g2.G2Affine) []bw6761.G2Affine { @@ -82,85 +83,87 @@ func TestMSMG2(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicleBw6_761.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p g2.G2Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } } -func TestMSMG2PinnedHostMemory(t *testing.T) { - cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicleBw6_761.GenerateScalars(size) - points := g2.G2GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[g2.G2Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p g2.G2Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[g2.G2Projective], 1) - - e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) - - if pinnableAndLockable { - e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) - - } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} +// func TestMSMG2PinnedHostMemory(t *testing.T) { +// cfg := g2.G2GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleBw6_761.GenerateScalars(size) +// points := g2.G2GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[g2.G2Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p g2.G2Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[g2.G2Projective], 1) +// +// e = g2.G2Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) +// +// +// if pinnableAndLockable { +// e = g2.G2Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, pinnedPoints, outHost[0])) +// +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } func TestMSMG2GnarkCryptoTypes(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{3} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := make([]fr.Element, size) @@ -177,18 +180,18 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true cfg.AreScalarsMontgomeryForm = true e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } } @@ -196,6 +199,7 @@ func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicleBw6_761.GenerateScalars(totalSize) @@ -204,10 +208,10 @@ func TestMSMG2Batch(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -216,7 +220,7 @@ func TestMSMG2Batch(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) } } } @@ -229,6 +233,8 @@ func TestPrecomputePointsG2(t *testing.T) { for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicleBw6_761.GenerateScalars(totalSize) @@ -236,18 +242,20 @@ func TestPrecomputePointsG2(t *testing.T) { var precomputeOut core.DeviceSlice _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = g2.G2PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p g2.G2Projective var out core.DeviceSlice _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -257,7 +265,50 @@ func TestPrecomputePointsG2(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestPrecomputePointsSharedBasesG2(t *testing.T) { + cfg := g2.G2GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBw6_761.GenerateScalars(totalSize) + points := g2.G2GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = g2.G2PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p g2.G2Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = g2.G2Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[g2.G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0:size] + out := outHost[i] + testAgainstGnarkCryptoMsmG2(t, scalarsSlice, pointsSlice, out) } } } @@ -266,6 +317,8 @@ func TestPrecomputePointsG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power scalars := icicleBw6_761.GenerateScalars(size) @@ -280,27 +333,31 @@ func TestMSMG2SkewedDistribution(t *testing.T) { var p g2.G2Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } } func TestMSMG2MultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { + runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { @@ -308,22 +365,22 @@ func TestMSMG2MultiDevice(t *testing.T) { scalars := icicleBw6_761.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p g2.G2Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = g2.G2Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[g2.G2Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsmG2(t, scalars, points, outHost[0]) } }) } diff --git a/wrappers/golang_v3/curves/bw6761/tests/main_test.go b/wrappers/golang_v3/curves/bw6761/tests/main_test.go index afc5f0cb0..05d182a42 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/main_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/main_test.go @@ -1,7 +1,7 @@ package tests import ( - "os" + "fmt" "testing" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" @@ -16,6 +16,8 @@ const ( largestTestSize = 20 ) +var DEVICE runtime.Device + func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() @@ -29,22 +31,36 @@ func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcic func TestMain(m *testing.M) { runtime.LoadBackendFromEnv() - device := runtime.CreateDevice("CUDA", 0) - runtime.SetDevice(&device) - - // setup domain - cfg := core.GetDefaultNTTInitDomainConfig() - e := initDomain(largestTestSize, cfg) + devices, e := runtime.GetRegisteredDevices() if e != runtime.Success { - panic("initDomain failed") + panic("Failed to load registered devices") } + for _, deviceType := range devices { + DEVICE = runtime.CreateDevice(deviceType, 0) + runtime.SetDevice(&DEVICE) - // execute tests - os.Exit(m.Run()) + // setup domain + cfg := core.GetDefaultNTTInitDomainConfig() + e = initDomain(largestTestSize, cfg) + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("initDomain is not implemented for ", deviceType, " device type") + } else { + panic("initDomain failed") + } + } - // release domain - e = ntt.ReleaseDomain() - if e != runtime.Success { - panic("ReleaseDomain failed") + // execute tests + m.Run() + + // release domain + e = ntt.ReleaseDomain() + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("ReleaseDomain is not implemented for ", deviceType, " device type") + } else { + panic("ReleaseDomain failed") + } + } } } diff --git a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go index f4099b88c..4fd4499ed 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go @@ -8,14 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/consensys/gnark-crypto/ecc" - bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761" + "github.com/consensys/gnark-crypto/ecc/bw6-761" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" icicleBw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func projectiveToGnarkAffine(p icicleBw6_761.Projective) bw6761.G1Affine { @@ -35,7 +35,7 @@ func projectiveToGnarkAffine(p icicleBw6_761.Projective) bw6761.G1Affine { return bw6761.G1Affine{X: *x, Y: *y} } -func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBw6_761.ScalarField], points core.HostSlice[icicleBw6_761.Affine], out icicleBw6_761.Projective) bool { +func testAgainstGnarkCryptoMsm(t *testing.T, scalars core.HostSlice[icicleBw6_761.ScalarField], points core.HostSlice[icicleBw6_761.Affine], out icicleBw6_761.Projective) { scalarsFr := make([]fr.Element, len(scalars)) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -47,18 +47,19 @@ func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBw6_761.ScalarField] pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) } - return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out) + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsFr, pointsFp, out) } -func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bw6761.G1Affine], out icicleBw6_761.Projective) bool { +func testAgainstGnarkCryptoMsmGnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bw6761.G1Affine], out icicleBw6_761.Projective) { var msmRes bw6761.G1Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - var icicleResAsJac bw6761.G1Jac - proj := projectiveToGnarkAffine(out) - icicleResAsJac.FromAffine(&proj) + var msmResAffine bw6761.G1Affine + msmResAffine.FromJacobian(&msmRes) - return msmRes.Equal(&icicleResAsJac) + icicleResAffine := projectiveToGnarkAffine(out) + + assert.Equal(t, msmResAffine, icicleResAffine) } func convertIcicleAffineToG1Affine(iciclePoints []icicleBw6_761.Affine) []bw6761.G1Affine { @@ -82,85 +83,87 @@ func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicleBw6_761.GenerateScalars(size) points := icicleBw6_761.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleBw6_761.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } } -func TestMSMPinnedHostMemory(t *testing.T) { - cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicleBw6_761.GenerateScalars(size) - points := icicleBw6_761.GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[icicleBw6_761.Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p icicleBw6_761.Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) - - e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) - - if pinnableAndLockable { - e = msm.Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") - - outHost.CopyFromDevice(&out) - // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) - - } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } - } -} +// func TestMSMPinnedHostMemory(t *testing.T) { +// cfg := msm.GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleBw6_761.GenerateScalars(size) +// points := icicleBw6_761.GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[icicleBw6_761.Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p icicleBw6_761.Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) +// +// e = msm.Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) +// +// +// if pinnableAndLockable { +// e = msm.Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// // // Check with gnark-crypto +// assert.True(t, testAgainstGnarkCryptoMsm(scalars, pinnedPoints, outHost[0])) +// +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } func TestMSMGnarkCryptoTypes(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{3} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := make([]fr.Element, size) @@ -177,18 +180,18 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { var p icicleBw6_761.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true cfg.AreScalarsMontgomeryForm = true e = msm.Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + testAgainstGnarkCryptoMsmGnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } } @@ -196,6 +199,7 @@ func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicleBw6_761.GenerateScalars(totalSize) @@ -204,10 +208,10 @@ func TestMSMBatch(t *testing.T) { var p icicleBw6_761.Projective var out core.DeviceSlice _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBw6_761.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -216,7 +220,7 @@ func TestMSMBatch(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) } } } @@ -229,6 +233,8 @@ func TestPrecomputePoints(t *testing.T) { for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicleBw6_761.GenerateScalars(totalSize) @@ -236,18 +242,20 @@ func TestPrecomputePoints(t *testing.T) { var precomputeOut core.DeviceSlice _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p icicleBw6_761.Projective var out core.DeviceSlice _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[icicleBw6_761.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -257,7 +265,50 @@ func TestPrecomputePoints(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) + } + } + } +} + +func TestPrecomputePointsSharedBases(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicleBw6_761.GenerateScalars(totalSize) + points := icicleBw6_761.GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p icicleBw6_761.Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[icicleBw6_761.Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0:size] + out := outHost[i] + testAgainstGnarkCryptoMsm(t, scalarsSlice, pointsSlice, out) } } } @@ -266,6 +317,8 @@ func TestPrecomputePoints(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power scalars := icicleBw6_761.GenerateScalars(size) @@ -280,27 +333,31 @@ func TestMSMSkewedDistribution(t *testing.T) { var p icicleBw6_761.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } } func TestMSMMultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { + runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { @@ -308,22 +365,22 @@ func TestMSMMultiDevice(t *testing.T) { scalars := icicleBw6_761.GenerateScalars(size) points := icicleBw6_761.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleBw6_761.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleBw6_761.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + testAgainstGnarkCryptoMsm(t, scalars, points, outHost[0]) } }) } diff --git a/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go b/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go index d0e86317f..e90f32c33 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" ) -func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bw6_761.ScalarField], output core.HostSlice[bw6_761.ScalarField], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNtt(t *testing.T, size int, scalars core.HostSlice[bw6_761.ScalarField], output core.HostSlice[bw6_761.ScalarField], order core.Ordering, direction core.NTTDir) { scalarsFr := make([]fr.Element, size) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -26,10 +26,10 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bw6_761.ScalarFi outputAsFr[i] = slice64 } - return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) + testAgainstGnarkCryptoNttGnarkTypes(t, size, scalarsFr, outputAsFr, order, direction) } -func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNttGnarkTypes(t *testing.T, size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) { domainWithPrecompute := fft.NewDomain(uint64(size)) // DIT + BitReverse == Ordering.kRR // DIT == Ordering.kRN @@ -51,7 +51,7 @@ func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.E if order == core.KNN || order == core.KRR { fft.BitReverse(scalarsFr) } - return reflect.DeepEqual(scalarsFr, outputAsFr) + assert.Equal(t, scalarsFr, outputAsFr) } func TestNTTGetDefaultConfig(t *testing.T) { actual := ntt.GetDefaultNttConfig() @@ -75,6 +75,8 @@ func TestNtt(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bw6_761.ScalarField](scalars[:testSize]) @@ -85,7 +87,7 @@ func TestNtt(t *testing.T) { ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -100,6 +102,8 @@ func TestNttFrElement(t *testing.T) { for _, size := range []int{4} { for _, v := range [1]core.Ordering{core.KNN} { + runtime.SetDevice(&DEVICE) + testSize := size scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) @@ -110,7 +114,7 @@ func TestNttFrElement(t *testing.T) { ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNttGnarkTypes(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -122,6 +126,8 @@ func TestNttDeviceAsync(t *testing.T) { for _, size := range []int{1, 10, largestTestSize} { for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[bw6_761.ScalarField](scalars[:testSize]) @@ -143,7 +149,7 @@ func TestNttDeviceAsync(t *testing.T) { runtime.SynchronizeStream(stream) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, direction) } } } @@ -157,6 +163,8 @@ func TestNttBatch(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, batchSize := range []int{2, 16, largestBatchSize} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size totalSize := testSize * batchSize diff --git a/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go b/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go deleted file mode 100644 index ae47cdfdd..000000000 --- a/wrappers/golang_v3/curves/bw6761/tests/poseidon_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package tests - -import ( - "testing" - - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" - bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/bw6761/poseidon" -) - -func TestPoseidon(t *testing.T) { - - arity := 2 - numberOfStates := 1 - - cfg := poseidon.GetDefaultPoseidonConfig() - cfg.IsAsync = true - stream, _ := cr.CreateStream() - cfg.Ctx.Stream = &stream - - var constants core.PoseidonConstants[bw6_761.ScalarField] - - poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants - - scalars := bw6_761.GenerateScalars(numberOfStates * arity) - scalars[0] = scalars[0].Zero() - scalars[1] = scalars[0].Zero() - - scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) - - var deviceInput core.DeviceSlice - scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) - var deviceOutput core.DeviceSlice - deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) - - poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function - - output := make(core.HostSlice[bw6_761.ScalarField], numberOfStates) - output.CopyFromDeviceAsync(&deviceOutput, stream) - -} diff --git a/wrappers/golang_v3/curves/grumpkin/curve.go b/wrappers/golang_v3/curves/grumpkin/curve.go index 677fd5fa5..80a57316b 100644 --- a/wrappers/golang_v3/curves/grumpkin/curve.go +++ b/wrappers/golang_v3/curves/grumpkin/curve.go @@ -8,7 +8,7 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) type Projective struct { @@ -134,44 +134,38 @@ func GenerateAffinePoints(size int) core.HostSlice[Affine] { return pointsSlice } -func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.grumpkin_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.grumpkin_affine_convert_montgomery((*C.affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, true) } -func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertAffinePointsMontgomery(points, false) } -func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.grumpkin_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.grumpkin_projective_convert_montgomery((*C.projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, true) } -func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convertProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/curves/grumpkin/include/curve.h b/wrappers/golang_v3/curves/grumpkin/include/curve.h index 8466982ed..710dc4553 100644 --- a/wrappers/golang_v3/curves/grumpkin/include/curve.h +++ b/wrappers/golang_v3/curves/grumpkin/include/curve.h @@ -1,4 +1,3 @@ -#include #include #ifndef _GRUMPKIN_CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct projective_t projective_t; typedef struct affine_t affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool grumpkin_eq(projective_t* point1, projective_t* point2); void grumpkin_to_affine(projective_t* point, affine_t* point_out); void grumpkin_generate_projective_points(projective_t* points, int size); void grumpkin_generate_affine_points(affine_t* points, int size); -cudaError_t grumpkin_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t grumpkin_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int grumpkin_affine_convert_montgomery(const affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, affine_t* d_out); +int grumpkin_projective_convert_montgomery(const projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/grumpkin/main.go b/wrappers/golang_v3/curves/grumpkin/main.go index 3404e2279..68f05d26c 100644 --- a/wrappers/golang_v3/curves/grumpkin/main.go +++ b/wrappers/golang_v3/curves/grumpkin/main.go @@ -1,4 +1,4 @@ package grumpkin -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_grumpkin -lingo_field_grumpkin -lstdc++ -lm +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_grumpkin -licicle_curve_grumpkin -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build import "C" diff --git a/wrappers/golang_v3/curves/grumpkin/msm/include/msm.h b/wrappers/golang_v3/curves/grumpkin/msm/include/msm.h index 9314720be..58529b6b9 100644 --- a/wrappers/golang_v3/curves/grumpkin/msm/include/msm.h +++ b/wrappers/golang_v3/curves/grumpkin/msm/include/msm.h @@ -1,4 +1,3 @@ -#include #include #ifndef _GRUMPKIN_MSM_H @@ -12,11 +11,9 @@ typedef struct scalar_t scalar_t; typedef struct projective_t projective_t; typedef struct affine_t affine_t; typedef struct MSMConfig MSMConfig; -typedef struct DeviceContext DeviceContext; -cudaError_t grumpkin_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out); -cudaError_t grumpkin_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out); -cudaError_t grumpkin_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out); +int grumpkin_msm(const scalar_t* scalars, const affine_t* points, int count, MSMConfig* config, projective_t* out); +int grumpkin_msm_precompute_bases(affine_t* input_bases, int bases_size, MSMConfig* config, affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/curves/grumpkin/msm/msm.go b/wrappers/golang_v3/curves/grumpkin/msm/msm.go index 48f20e1e5..e7a1d1810 100644 --- a/wrappers/golang_v3/curves/grumpkin/msm/msm.go +++ b/wrappers/golang_v3/curves/grumpkin/msm/msm.go @@ -8,57 +8,41 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func GetDefaultMSMConfig() core.MSMConfig { return core.GetDefaultMSMConfig() } -func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.affine_t)(pointsPointer) cResults := (*C.projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) - - __ret := C.grumpkin_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults) - err := (cr.CudaError)(__ret) - return err -} - -// Deprecated: PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// PrecomputePoints should be used instead. -func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { - cfg := GetDefaultMSMConfig() - cfg.PrecomputeFactor = precomputeFactor - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) - - cPoints := (*C.affine_t)(pointsPointer) - cPointsLen := (C.int)(points.Len()) - cPrecomputeFactor := (C.int)(precomputeFactor) - cC := (C.int)(c) - cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) - cOutputBases := (*C.affine_t)(outputBasesPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) - __ret := C.grumpkin_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.grumpkin_msm(cScalars, cPoints, cSize, cCfg, cResults) + err := runtime.EIcicleError(__ret) return err } -func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.affine_t)(pointsPointer) - cMsmSize := (C.int)(msmSize) + cBases := (*C.affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.affine_t)(outputBasesPointer) - __ret := C.grumpkin_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases) - err := (cr.CudaError)(__ret) + __ret := C.grumpkin_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) + err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/curves/grumpkin/poseidon/include/poseidon.h b/wrappers/golang_v3/curves/grumpkin/poseidon/include/poseidon.h deleted file mode 100644 index ed27d7dba..000000000 --- a/wrappers/golang_v3/curves/grumpkin/poseidon/include/poseidon.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#ifndef _GRUMPKIN_POSEIDON_H -#define _GRUMPKIN_POSEIDON_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct scalar_t scalar_t; -typedef struct PoseidonConfig PoseidonConfig; -typedef struct DeviceContext DeviceContext; -typedef struct PoseidonConstants PoseidonConstants; - - -cudaError_t grumpkin_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config); -cudaError_t grumpkin_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants); -cudaError_t grumpkin_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go b/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go deleted file mode 100644 index d62b7dbf6..000000000 --- a/wrappers/golang_v3/curves/grumpkin/poseidon/poseidon.go +++ /dev/null @@ -1,57 +0,0 @@ -package poseidon - -// #cgo CFLAGS: -I./include/ -// #include "poseidon.h" -import "C" - -import ( - "unsafe" - - "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" -) - -func GetDefaultPoseidonConfig() core.PoseidonConfig { - return core.GetDefaultPoseidonConfig() -} - -func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError { - scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates) - - cScalars := (*C.scalar_t)(scalarsPointer) - cResults := (*C.scalar_t)(resultsPointer) - cNumberOfStates := (C.int)(numberOfStates) - cArity := (C.int)(constants.Arity) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - cCfg := (*C.PoseidonConfig)(cfgPointer) - - __ret := C.grumpkin_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg) - - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cFullRoundsHalfs := (C.int)(fullRoundsHalfs) - cPartialRounds := (C.int)(partialRounds) - cConstants := (*C.scalar_t)(constants.AsUnsafePointer()) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants)) - - __ret := C.grumpkin_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} - -func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError { - - cArity := (C.int)(arity) - cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) - cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants)) - - __ret := C.grumpkin_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) -} diff --git a/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go b/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go index 66b6b3d90..93ee02d13 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/curve_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/test_helpers" "github.com/stretchr/testify/assert" + "testing" ) func TestAffineZero(t *testing.T) { diff --git a/wrappers/golang_v3/curves/grumpkin/tests/main_test.go b/wrappers/golang_v3/curves/grumpkin/tests/main_test.go index 309de0833..5ef2f80b3 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/main_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/main_test.go @@ -1,7 +1,6 @@ package tests import ( - "os" "testing" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" @@ -11,12 +10,20 @@ const ( largestTestSize = 20 ) +var DEVICE runtime.Device + func TestMain(m *testing.M) { runtime.LoadBackendFromEnv() - device := runtime.CreateDevice("CUDA", 0) - runtime.SetDevice(&device) + devices, e := runtime.GetRegisteredDevices() + if e != runtime.Success { + panic("Failed to load registered devices") + } + for _, deviceType := range devices { + DEVICE = runtime.CreateDevice(deviceType, 0) + runtime.SetDevice(&DEVICE) - // execute tests - os.Exit(m.Run()) + // execute tests + m.Run() + } } diff --git a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go index 506ad754c..ad3fa9aba 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go @@ -8,136 +8,180 @@ import ( "github.com/stretchr/testify/assert" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" icicleGrumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin/msm" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicleGrumpkin.GenerateScalars(size) points := icicleGrumpkin.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleGrumpkin.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) } } -func TestMSMPinnedHostMemory(t *testing.T) { - cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10} { - size := 1 << power - - scalars := icicleGrumpkin.GenerateScalars(size) - points := icicleGrumpkin.GenerateAffinePoints(size) - - pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) - lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) - - pinnableAndLockable := pinnable == 1 && lockable == 0 - - var pinnedPoints core.HostSlice[icicleGrumpkin.Affine] - if pinnableAndLockable { - points.Pin(cr.CudaHostRegisterDefault) - pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) - assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") - } - - var p icicleGrumpkin.Projective - var out core.DeviceSlice - _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) +// func TestMSMPinnedHostMemory(t *testing.T) { +// cfg := msm.GetDefaultMSMConfig() +// for _, power := range []int{10} { +// size := 1 << power +// +// scalars := icicleGrumpkin.GenerateScalars(size) +// points := icicleGrumpkin.GenerateAffinePoints(size) +// +// pinnable := cr.GetDeviceAttribute(cr.CudaDevAttrHostRegisterSupported, 0) +// lockable := cr.GetDeviceAttribute(cr.CudaDevAttrPageableMemoryAccessUsesHostPageTables, 0) +// +// pinnableAndLockable := pinnable == 1 && lockable == 0 +// +// var pinnedPoints core.HostSlice[icicleGrumpkin.Affine] +// if pinnableAndLockable { +// points.Pin(cr.CudaHostRegisterDefault) +// pinnedPoints, _ = points.AllocPinned(cr.CudaHostAllocDefault) +// assert.Equal(t, points, pinnedPoints, "Allocating newly pinned memory resulted in bad points") +// } +// +// var p icicleGrumpkin.Projective +// var out core.DeviceSlice +// _, e := out.Malloc(p.Size(), p.Size()) +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") +// outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) +// +// e = msm.Msm(scalars, points, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// +// +// if pinnableAndLockable { +// e = msm.Msm(scalars, pinnedPoints, &cfg, out) +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") +// +// outHost.CopyFromDevice(&out) +// +// } +// +// out.Free() +// +// if pinnableAndLockable { +// points.Unpin() +// pinnedPoints.FreePinned() +// } +// } +// } - e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") - - outHost.CopyFromDevice(&out) +func TestMSMBatch(t *testing.T) { + cfg := msm.GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power + totalSize := size * batchSize + scalars := icicleGrumpkin.GenerateScalars(totalSize) + points := icicleGrumpkin.GenerateAffinePoints(totalSize) - if pinnableAndLockable { - e = msm.Msm(scalars, pinnedPoints, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") + var p icicleGrumpkin.Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + e = msm.Msm(scalars, points, &cfg, out) + assert.Equal(t, e, runtime.Success, "Msm failed") + outHost := make(core.HostSlice[icicleGrumpkin.Projective], batchSize) outHost.CopyFromDevice(&out) + out.Free() } - - out.Free() - - if pinnableAndLockable { - points.Unpin() - pinnedPoints.FreePinned() - } } } -func TestMSMBatch(t *testing.T) { +func TestPrecomputePoints(t *testing.T) { cfg := msm.GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicleGrumpkin.GenerateScalars(totalSize) points := icicleGrumpkin.GenerateAffinePoints(totalSize) + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + var p icicleGrumpkin.Projective var out core.DeviceSlice - _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") - e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + e = msm.Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[icicleGrumpkin.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() + precomputeOut.Free() } } } -func TestPrecomputePoints(t *testing.T) { +func TestPrecomputePointsSharedBases(t *testing.T) { cfg := msm.GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicleGrumpkin.GenerateScalars(totalSize) - points := icicleGrumpkin.GenerateAffinePoints(totalSize) + points := icicleGrumpkin.GenerateAffinePoints(size) var precomputeOut core.DeviceSlice _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = msm.PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + e = msm.PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p icicleGrumpkin.Projective var out core.DeviceSlice _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[icicleGrumpkin.Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -150,6 +194,8 @@ func TestPrecomputePoints(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power scalars := icicleGrumpkin.GenerateScalars(size) @@ -164,10 +210,10 @@ func TestMSMSkewedDistribution(t *testing.T) { var p icicleGrumpkin.Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) outHost.CopyFromDevice(&out) out.Free() @@ -176,14 +222,18 @@ func TestMSMSkewedDistribution(t *testing.T) { } func TestMSMMultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { + runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { @@ -191,20 +241,20 @@ func TestMSMMultiDevice(t *testing.T) { scalars := icicleGrumpkin.GenerateScalars(size) points := icicleGrumpkin.GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p icicleGrumpkin.Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = msm.Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[icicleGrumpkin.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) } }) diff --git a/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go b/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go deleted file mode 100644 index ba5d187ed..000000000 --- a/wrappers/golang_v3/curves/grumpkin/tests/poseidon_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package tests - -import ( - "testing" - - core "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" - grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin" - poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/curves/grumpkin/poseidon" -) - -func TestPoseidon(t *testing.T) { - - arity := 2 - numberOfStates := 1 - - cfg := poseidon.GetDefaultPoseidonConfig() - cfg.IsAsync = true - stream, _ := cr.CreateStream() - cfg.Ctx.Stream = &stream - - var constants core.PoseidonConstants[grumpkin.ScalarField] - - poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants - - scalars := grumpkin.GenerateScalars(numberOfStates * arity) - scalars[0] = scalars[0].Zero() - scalars[1] = scalars[0].Zero() - - scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity]) - - var deviceInput core.DeviceSlice - scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) - var deviceOutput core.DeviceSlice - deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) - - poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function - - output := make(core.HostSlice[grumpkin.ScalarField], numberOfStates) - output.CopyFromDeviceAsync(&deviceOutput, stream) - -} diff --git a/wrappers/golang_v3/fields/babybear/tests/main_test.go b/wrappers/golang_v3/fields/babybear/tests/main_test.go index 89f915fa1..5c781649a 100644 --- a/wrappers/golang_v3/fields/babybear/tests/main_test.go +++ b/wrappers/golang_v3/fields/babybear/tests/main_test.go @@ -1,7 +1,7 @@ package tests import ( - "os" + "fmt" "testing" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" @@ -14,6 +14,8 @@ const ( largestTestSize = 20 ) +var DEVICE runtime.Device + func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouIcicle := babybear.ScalarField{} rouIcicle.FromUint32(1461624142) @@ -23,22 +25,36 @@ func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcic func TestMain(m *testing.M) { runtime.LoadBackendFromEnv() - device := runtime.CreateDevice("CUDA", 0) - runtime.SetDevice(&device) - - // setup domain - cfg := core.GetDefaultNTTInitDomainConfig() - e := initDomain(largestTestSize, cfg) + devices, e := runtime.GetRegisteredDevices() if e != runtime.Success { - panic("initDomain failed") + panic("Failed to load registered devices") } - - // execute tests - os.Exit(m.Run()) - - // release domain - e = ntt.ReleaseDomain() - if e != runtime.Success { - panic("ReleaseDomain failed") + for _, deviceType := range devices { + DEVICE = runtime.CreateDevice(deviceType, 0) + runtime.SetDevice(&DEVICE) + + // setup domain + cfg := core.GetDefaultNTTInitDomainConfig() + e = initDomain(largestTestSize, cfg) + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("initDomain is not implemented for ", deviceType, " device type") + } else { + panic("initDomain failed") + } + } + + // execute tests + m.Run() + + // release domain + e = ntt.ReleaseDomain() + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("ReleaseDomain is not implemented for ", deviceType, " device type") + } else { + panic("ReleaseDomain failed") + } + } } } diff --git a/wrappers/golang_v3/fields/babybear/tests/ntt_test.go b/wrappers/golang_v3/fields/babybear/tests/ntt_test.go index a825bebc8..d17c6b618 100644 --- a/wrappers/golang_v3/fields/babybear/tests/ntt_test.go +++ b/wrappers/golang_v3/fields/babybear/tests/ntt_test.go @@ -33,6 +33,8 @@ func TestNtt(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[babybear.ScalarField](scalars[:testSize]) @@ -53,6 +55,8 @@ func TestNttDeviceAsync(t *testing.T) { for _, size := range []int{1, 10, largestTestSize} { for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[babybear.ScalarField](scalars[:testSize]) @@ -86,6 +90,8 @@ func TestNttBatch(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, batchSize := range []int{2, 16, largestBatchSize} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size totalSize := testSize * batchSize diff --git a/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl index 22c5ce5ad..82f936223 100644 --- a/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl +++ b/wrappers/golang_v3/internal/generator/curves/templates/curve.go.tmpl @@ -8,7 +8,7 @@ import ( "unsafe" "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) {{end}} type {{.CurvePrefix}}Projective struct { @@ -134,44 +134,38 @@ func {{.CurvePrefix}}GenerateAffinePoints(size int) core.HostSlice[{{.CurvePrefi return pointsSlice } -func convert{{.CurvePrefix}}AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.{{toCName .CurvePrefix}}affine_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convert{{.CurvePrefix}}AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_affine_convert_montgomery((*C.{{toCName .CurvePrefix}}affine_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.{{toCName .CurvePrefix}}affine_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func {{.CurvePrefix}}AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { +func {{.CurvePrefix}}AffineToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convert{{.CurvePrefix}}AffinePointsMontgomery(points, true) } -func {{.CurvePrefix}}AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func {{.CurvePrefix}}AffineFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convert{{.CurvePrefix}}AffinePointsMontgomery(points, false) } -func convert{{.CurvePrefix}}ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { - cValues := (*C.{{toCName .CurvePrefix}}projective_t)(points.AsUnsafePointer()) - cSize := (C.size_t)(points.Len()) - cIsInto := (C._Bool)(isInto) - defaultCtx, _ := cr.GetDefaultDeviceContext() - cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) - __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx) - err := (cr.CudaError)(__ret) +func convert{{.CurvePrefix}}ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) runtime.EIcicleError { + defaultCfg := core.DefaultVecOpsConfig() + cValues, _, _, cCfg, cSize := core.VecOpCheck(*points, *points, *points, &defaultCfg) + cErr := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_projective_convert_montgomery((*C.{{toCName .CurvePrefix}}projective_t)(cValues), (C.size_t)(cSize), (C._Bool)(isInto), (*C.VecOpsConfig)(cCfg), (*C.{{toCName .CurvePrefix}}projective_t)(cValues)) + err := runtime.EIcicleError(cErr) return err } -func {{.CurvePrefix}}ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { +func {{.CurvePrefix}}ProjectiveToMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convert{{.CurvePrefix}}ProjectivePointsMontgomery(points, true) } -func {{.CurvePrefix}}ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { +func {{.CurvePrefix}}ProjectiveFromMontgomery(points *core.DeviceSlice) runtime.EIcicleError { points.CheckDevice() return convert{{.CurvePrefix}}ProjectivePointsMontgomery(points, false) } diff --git a/wrappers/golang_v3/internal/generator/curves/templates/curve.h.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/curve.h.tmpl index 22179e6f6..3dd3a2993 100644 --- a/wrappers/golang_v3/internal/generator/curves/templates/curve.h.tmpl +++ b/wrappers/golang_v3/internal/generator/curves/templates/curve.h.tmpl @@ -1,4 +1,3 @@ -#include #include #ifndef _{{toUpper .Curve}}_{{.CurvePrefix}}CURVE_H @@ -10,14 +9,14 @@ extern "C" { typedef struct {{toCName .CurvePrefix}}projective_t {{toCName .CurvePrefix}}projective_t; typedef struct {{toCName .CurvePrefix}}affine_t {{toCName .CurvePrefix}}affine_t; -typedef struct DeviceContext DeviceContext; +typedef struct VecOpsConfig VecOpsConfig; bool {{.Curve}}{{toCNameBackwards .CurvePrefix}}_eq({{toCName .CurvePrefix}}projective_t* point1, {{toCName .CurvePrefix}}projective_t* point2); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_to_affine({{toCName .CurvePrefix}}projective_t* point, {{toCName .CurvePrefix}}affine_t* point_out); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_projective_points({{toCName .CurvePrefix}}projective_t* points, int size); void {{.Curve}}{{toCNameBackwards .CurvePrefix}}_generate_affine_points({{toCName .CurvePrefix}}affine_t* points, int size); -cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_affine_convert_montgomery({{toCName .CurvePrefix}}affine_t* points, size_t n, bool is_into, DeviceContext* ctx); -cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_projective_convert_montgomery({{toCName .CurvePrefix}}projective_t* points, size_t n, bool is_into, DeviceContext* ctx); +int {{.Curve}}{{toCNameBackwards .CurvePrefix}}_affine_convert_montgomery(const {{toCName .CurvePrefix}}affine_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, {{toCName .CurvePrefix}}affine_t* d_out); +int {{.Curve}}{{toCNameBackwards .CurvePrefix}}_projective_convert_montgomery(const {{toCName .CurvePrefix}}projective_t* d_in, size_t n, bool is_into, const VecOpsConfig* ctx, {{toCName .CurvePrefix}}projective_t* d_out); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl index 3a85167d0..76f3c9884 100644 --- a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl +++ b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl @@ -1,4 +1,4 @@ package {{.PackageName}} -// #cgo LDFLAGS: -L${SRCDIR}/../../../../{{.UpDirs}}icicle/build/lib -lingo_curve_{{.Field}} -lingo_field_{{.Field}} -lstdc++ -lm +// #cgo LDFLAGS: -L${SRCDIR}/../../../../{{.UpDirs}}icicle_v3/build -licicle_field_{{.Field}} -licicle_curve_{{.Field}} -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../{{.UpDirs}}icicle_v3/build import "C" diff --git a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl index cb02a7fc2..dbfcd6600 100644 --- a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.go.tmpl @@ -6,10 +6,10 @@ import "C" import ( "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" - cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/cuda_runtime" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" ) -func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { +func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) runtime.EIcicleError { pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results) cPoints := (*C.projective_t)(pointsPointer) @@ -18,7 +18,7 @@ func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTC cCfg := (*C.NTTConfig)(cfgPointer) cResults := (*C.projective_t)(resultsPointer) - __ret := C.{{.Curve}}_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults) - err := (cr.CudaError)(__ret) - return core.FromCudaError(err) + __ret := C.{{.Curve}}_ecntt(cPoints, cSize, cDir, cCfg, cResults) + err := runtime.EIcicleError(__ret) + return err } diff --git a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.h.tmpl b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.h.tmpl index 3180f5340..a31a75529 100644 --- a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.h.tmpl +++ b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt.h.tmpl @@ -10,7 +10,7 @@ extern "C" { typedef struct NTTConfig NTTConfig; typedef struct projective_t projective_t; -cudaError_t {{.Curve}}_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); +int {{.Curve}}_ecntt(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl index 7cc06f08b..b6f758f55 100644 --- a/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ecntt/templates/ecntt_test.go.tmpl @@ -7,24 +7,30 @@ import ( {{.Curve}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}" ecntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/ecntt" ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}/ntt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/runtime" "github.com/stretchr/testify/assert" ) func TestECNtt(t *testing.T) { cfg := ntt.GetDefaultNttConfig() + ext := runtime.CreateConfigExtension() + ext.SetInt(core.CUDA_NTT_ALGORITHM, int(core.Radix2)) + cfg.Ext = ext.AsUnsafePointer() + points := {{.Curve}}.GenerateProjectivePoints(1 << largestTestSize) for _, size := range []int{4, 5, 6, 7, 8} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size pointsCopy := core.HostSliceFromElements[{{.Curve}}.Projective](points[:testSize]) cfg.Ordering = v - cfg.NttAlgorithm = core.Radix2 output := make(core.HostSlice[{{.Curve}}.Projective], testSize) e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output) - assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed") + assert.Equal(t, runtime.Success, e, "ECNtt failed") } } } diff --git a/wrappers/golang_v3/internal/generator/main.go b/wrappers/golang_v3/internal/generator/main.go index ded450417..128a5d6b4 100644 --- a/wrappers/golang_v3/internal/generator/main.go +++ b/wrappers/golang_v3/internal/generator/main.go @@ -74,7 +74,7 @@ func generateFiles() { fields.Generate(extensionsDir, "extension", extensionField, extensionFieldPrefix, true, field.ExtensionLimbsNum) vecops.Generate(extensionsDir, extensionField, extensionFieldPrefix) ntt.Generate(fieldDir, "extension", field.Field, scalarFieldPrefix, field.GnarkImport, field.ROU, false, extensionField, extensionFieldPrefix) - lib_linker.Generate(extensionsDir, "extension", field.Field, lib_linker.FIELD, 1) + // lib_linker.Generate(extensionsDir, "extension", field.Field, lib_linker.FIELD, 1) } tests.Generate(fieldDir, field.Field, scalarFieldPrefix, field.GnarkImport, field.ROU, field.SupportsNTT, field.SupportsPoly) diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl index c65e503a7..d519e6c80 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm.go.tmpl @@ -16,49 +16,33 @@ func {{.CurvePrefix}}GetDefaultMSMConfig() core.MSMConfig { } func {{.CurvePrefix}}Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) runtime.EIcicleError { - scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results) + scalarsPointer, pointsPointer, resultsPointer, size := core.MsmCheck(scalars, points, cfg, results) cScalars := (*C.scalar_t)(scalarsPointer) cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) cResults := (*C.{{toCName .CurvePrefix}}projective_t)(resultsPointer) cSize := (C.int)(size) - cCfg := (*C.MSMConfig)(cfgPointer) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm(cScalars, cPoints, cSize, cCfg, cResults) err := runtime.EIcicleError(__ret) return err } -// Deprecated: {{.CurvePrefix}}PrecomputeBases exists for backward compatibility. -// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version. -// {{.CurvePrefix}}PrecomputePoints should be used instead. -// func {{.CurvePrefix}}PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError { -// cfg := {{.CurvePrefix}}GetDefaultMSMConfig() -// cfg.PrecomputeFactor = precomputeFactor -// pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases) -// -// cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) -// cPointsLen := (C.int)(points.Len()) -// cPrecomputeFactor := (C.int)(precomputeFactor) -// cC := (C.int)(c) -// cPointsIsOnDevice := (C._Bool)(points.IsOnDevice()) -// cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx)) -// cOutputBases := (*C.{{toCName .CurvePrefix}}affine_t)(outputBasesPointer) -// -// __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases) -// err := (cr.CudaError)(__ret) -// return err -// } - -func {{.CurvePrefix}}PrecomputeBases(points core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { - pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases) +func {{.CurvePrefix}}PrecomputeBases(bases core.HostOrDeviceSlice, cfg *core.MSMConfig, outputBases core.DeviceSlice) runtime.EIcicleError { + basesPointer, outputBasesPointer := core.PrecomputeBasesCheck(bases, cfg, outputBases) - cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer) - cMsmSize := (C.int)(points.Len()) + cBases := (*C.{{toCName .CurvePrefix}}affine_t)(basesPointer) + var cBasesLen C.int + if cfg.AreBasesShared { + cBasesLen = (C.int)(bases.Len()) + } else { + cBasesLen = (C.int)(bases.Len() / int(cfg.BatchSize)) + } cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) cOutputBases := (*C.{{toCName .CurvePrefix}}affine_t)(outputBasesPointer) - __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_precompute_bases(cPoints, cMsmSize, cCfg, cOutputBases) + __ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_precompute_bases(cBases, cBasesLen, cCfg, cOutputBases) err := runtime.EIcicleError(__ret) return err } diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl index 1a77da3e2..3d773e8e5 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm.h.tmpl @@ -12,8 +12,8 @@ typedef struct {{toCName .CurvePrefix}}projective_t {{toCName .CurvePrefix}}proj typedef struct {{toCName .CurvePrefix}}affine_t {{toCName .CurvePrefix}}affine_t; typedef struct MSMConfig MSMConfig; -cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm(const scalar_t* scalars, const {{toCName .CurvePrefix}}affine_t* points, int count, MSMConfig* config, {{toCName .CurvePrefix}}projective_t* out); -cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_precompute_bases({{toCName .CurvePrefix}}affine_t* input_bases, int bases_size, MSMConfig* config, {{toCName .CurvePrefix}}affine_t* output_bases); +int {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm(const scalar_t* scalars, const {{toCName .CurvePrefix}}affine_t* points, int count, MSMConfig* config, {{toCName .CurvePrefix}}projective_t* out); +int {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_precompute_bases({{toCName .CurvePrefix}}affine_t* input_bases, int bases_size, MSMConfig* config, {{toCName .CurvePrefix}}affine_t* output_bases); #ifdef __cplusplus } diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl index 116db3c6a..d2b4756b4 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl @@ -82,7 +82,7 @@ func projectiveToGnarkAffineG2(p g2.G2Projective) {{toPackage .GnarkImport}}.G2A return *g2Affine.FromJacobian(&g2Jac) } {{end}} -func testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars core.HostSlice[icicle{{capitalize .Curve}}.ScalarField], points core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Affine], out {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective) bool { +func testAgainstGnarkCryptoMsm{{.CurvePrefix}}(t *testing.T, scalars core.HostSlice[icicle{{capitalize .Curve}}.ScalarField], points core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Affine], out {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective) { scalarsFr := make([]fr.Element, len(scalars)) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -94,18 +94,19 @@ func testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars core.HostSlice[icicle{{ca pointsFp[i] = projectiveToGnarkAffine{{.CurvePrefix}}(v.ToProjective()) } - return testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(scalarsFr, pointsFp, out) + testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(t, scalarsFr, pointsFp, out) } -func testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[{{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Affine], out {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective) bool { +func testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(t *testing.T, scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[{{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Affine], out {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective) { var msmRes {{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Jac msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) - var icicleResAsJac {{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Jac - proj := projectiveToGnarkAffine{{.CurvePrefix}}(out) - icicleResAsJac.FromAffine(&proj) + var msmResAffine {{toPackage .GnarkImport}}.{{if eq .CurvePrefix "G2"}}G2{{else}}G1{{end}}Affine + msmResAffine.FromJacobian(&msmRes) - return msmRes.Equal(&icicleResAsJac) + icicleResAffine := projectiveToGnarkAffine{{.CurvePrefix}}(out) + + assert.Equal(t, msmResAffine, icicleResAffine) } {{$isBW6 := eq .Curve "bw6_761"}}{{$isG2 := eq .CurvePrefix "G2"}}{{$isG1 := ne .CurvePrefix "G2"}}{{if or $isBW6 $isG1 -}} @@ -160,6 +161,7 @@ func TestMSM{{.CurvePrefix}}(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) @@ -181,8 +183,7 @@ func TestMSM{{.CurvePrefix}}(t *testing.T) { runtime.SynchronizeStream(stream) {{if ne .GnarkImport "" -}} // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])) - {{end}} + testAgainstGnarkCryptoMsm{{.CurvePrefix}}(t, scalars, points, outHost[0]){{end}} } } @@ -209,11 +210,11 @@ func TestMSM{{.CurvePrefix}}(t *testing.T) { // var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective // var out core.DeviceSlice // _, e := out.Malloc(p.Size(), p.Size()) -// assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") +// assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") // outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) // // e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm allocated pinned host mem failed") +// assert.Equal(t, e, runtime.Success, "Msm allocated pinned host mem failed") // // outHost.CopyFromDevice(&out) // {{if ne .GnarkImport "" -}} @@ -223,7 +224,7 @@ func TestMSM{{.CurvePrefix}}(t *testing.T) { // // if pinnableAndLockable { // e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, pinnedPoints, &cfg, out) -// assert.Equal(t, e, cr.CudaSuccess, "Msm registered pinned host mem failed") +// assert.Equal(t, e, runtime.Success, "Msm registered pinned host mem failed") // // outHost.CopyFromDevice(&out) // {{if ne .GnarkImport "" -}} @@ -244,6 +245,7 @@ func TestMSM{{.CurvePrefix}}(t *testing.T) { func TestMSM{{if eq .CurvePrefix "G2"}}G2{{end}}GnarkCryptoTypes(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() for _, power := range []int{3} { + runtime.SetDevice(&DEVICE) size := 1 << power scalars := make([]fr.Element, size) @@ -260,18 +262,18 @@ func TestMSM{{if eq .CurvePrefix "G2"}}G2{{end}}GnarkCryptoTypes(t *testing.T) { var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.ArePointsMontgomeryForm = true + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.AreBasesMontgomeryForm = true cfg.AreScalarsMontgomeryForm = true e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalarsHost, pointsHost, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) outHost.CopyFromDevice(&out) out.Free() // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0])) + testAgainstGnarkCryptoMsm{{.CurvePrefix}}GnarkCryptoTypes(t, scalarsHost, pointsHost, outHost[0]) } } {{end}} @@ -279,6 +281,7 @@ func TestMSM{{.CurvePrefix}}Batch(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize scalars := icicle{{capitalize .Curve}}.GenerateScalars(totalSize) @@ -287,10 +290,10 @@ func TestMSM{{.CurvePrefix}}Batch(t *testing.T) { var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective var out core.DeviceSlice _, e := out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -300,7 +303,7 @@ func TestMSM{{.CurvePrefix}}Batch(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm{{.CurvePrefix}}(t, scalarsSlice, pointsSlice, out) }{{end}} } } @@ -313,6 +316,8 @@ func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) { for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + size := 1 << power totalSize := size * batchSize scalars := icicle{{capitalize .Curve}}.GenerateScalars(totalSize) @@ -320,18 +325,20 @@ func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) { var precomputeOut core.DeviceSlice _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") - e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}PrecomputePoints(points, size, &cfg, precomputeOut) - assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed") + cfg.BatchSize = int32(batchSize) + cfg.AreBasesShared = false + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective var out core.DeviceSlice _, e = out.Malloc(batchSize*p.Size(), p.Size()) - assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed") + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, precomputeOut, &cfg, out) - assert.Equal(t, cr.CudaSuccess, e, "Msm failed") + assert.Equal(t, runtime.Success, e, "Msm failed") outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], batchSize) outHost.CopyFromDevice(&out) out.Free() @@ -342,7 +349,51 @@ func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) { scalarsSlice := scalars[i*size : (i+1)*size] pointsSlice := points[i*size : (i+1)*size] out := outHost[i] - assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalarsSlice, pointsSlice, out)) + testAgainstGnarkCryptoMsm{{.CurvePrefix}}(t, scalarsSlice, pointsSlice, out) + }{{end}} + } + } +} + +func TestPrecomputePointsSharedBases{{.CurvePrefix}}(t *testing.T) { + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() + const precomputeFactor = 8 + cfg.PrecomputeFactor = precomputeFactor + + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + runtime.SetDevice(&DEVICE) + + size := 1 << power + totalSize := size * batchSize + scalars := icicle{{capitalize .Curve}}.GenerateScalars(totalSize) + points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) + + var precomputeOut core.DeviceSlice + _, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for PrecomputeBases results failed") + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}PrecomputeBases(points, &cfg, precomputeOut) + assert.Equal(t, runtime.Success, e, "PrecomputeBases failed") + + var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective + var out core.DeviceSlice + _, e = out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, runtime.Success, e, "Allocating bytes on device for Projective results failed") + + e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, precomputeOut, &cfg, out) + assert.Equal(t, runtime.Success, e, "Msm failed") + outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + precomputeOut.Free() + {{if ne .GnarkImport "" -}} + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[0 : size] + out := outHost[i] + testAgainstGnarkCryptoMsm{{.CurvePrefix}}(t, scalarsSlice, pointsSlice, out) }{{end}} } } @@ -351,6 +402,8 @@ func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) { func TestMSM{{.CurvePrefix}}SkewedDistribution(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + runtime.SetDevice(&DEVICE) + size := 1 << power scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) @@ -365,28 +418,32 @@ func TestMSM{{.CurvePrefix}}SkewedDistribution(t *testing.T) { var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective var out core.DeviceSlice _, e := out.Malloc(p.Size(), p.Size()) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) outHost.CopyFromDevice(&out) out.Free() {{if ne .GnarkImport "" -}} // Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])){{end}} + testAgainstGnarkCryptoMsm{{.CurvePrefix}}(t, scalars, points, outHost[0]){{end}} } } func TestMSM{{.CurvePrefix}}MultiDevice(t *testing.T) { - numDevices, _ := cr.GetDeviceCount() - fmt.Println("There are ", numDevices, " devices available") + numDevices, _ := runtime.GetDeviceCount() + fmt.Println("There are ", numDevices, " ", DEVICE.GetDeviceType(), " devices available") wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { + currentDevice := runtime.Device{DeviceType: DEVICE.DeviceType, Id: int32(i)} wg.Add(1) - cr.RunOnDevice(i, func(args ...any) { + runtime.RunOnDevice(¤tDevice, func(args ...any) { defer wg.Done() + + fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") + cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() cfg.IsAsync = true for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { @@ -394,22 +451,22 @@ func TestMSM{{.CurvePrefix}}MultiDevice(t *testing.T) { scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) - stream, _ := cr.CreateStream() + stream, _ := runtime.CreateStream() var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective var out core.DeviceSlice _, e := out.MallocAsync(p.Size(), p.Size(), stream) - assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") - cfg.Ctx.Stream = &stream + assert.Equal(t, e, runtime.Success, "Allocating bytes on device for Projective results failed") + cfg.StreamHandle = stream e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, points, &cfg, out) - assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + assert.Equal(t, e, runtime.Success, "Msm failed") outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) - cr.SynchronizeStream(&stream) + runtime.SynchronizeStream(stream) {{if ne .GnarkImport "" -}}// Check with gnark-crypto - assert.True(t, testAgainstGnarkCryptoMsm{{.CurvePrefix}}(scalars, points, outHost[0])){{end}} + testAgainstGnarkCryptoMsm{{.CurvePrefix}}(t, scalars, points, outHost[0]){{end}} } }) } diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl index 22d3788f1..14a2d4229 100644 --- a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl @@ -19,7 +19,7 @@ import ( ) {{if ne .GnarkImport "" -}} -func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], output core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNtt(t *testing.T, size int, scalars core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], output core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], order core.Ordering, direction core.NTTDir) { scalarsFr := make([]fr.Element, size) for i, v := range scalars { slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) @@ -31,10 +31,10 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[{{.Field}}.{{.Fi outputAsFr[i] = slice64 } - return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction) + testAgainstGnarkCryptoNttGnarkTypes(t, size, scalarsFr, outputAsFr, order, direction) } -func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool { +func testAgainstGnarkCryptoNttGnarkTypes(t *testing.T, size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) { domainWithPrecompute := fft.NewDomain(uint64(size)) // DIT + BitReverse == Ordering.kRR // DIT == Ordering.kRN @@ -56,7 +56,7 @@ func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.E if order == core.KNN || order == core.KRR { fft.BitReverse(scalarsFr) } - return reflect.DeepEqual(scalarsFr, outputAsFr) + assert.Equal(t, scalarsFr, outputAsFr) } {{end -}} @@ -82,6 +82,8 @@ func TestNtt(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[{{.Field}}.{{.FieldPrefix}}Field](scalars[:testSize]) @@ -93,7 +95,7 @@ func TestNtt(t *testing.T) { {{if ne .GnarkImport "" -}} // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, core.KForward) {{end -}} } } @@ -110,6 +112,8 @@ func TestNttFrElement(t *testing.T) { for _, size := range []int{4} { for _, v := range [1]core.Ordering{core.KNN} { + runtime.SetDevice(&DEVICE) + testSize := size scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize]) @@ -120,7 +124,7 @@ func TestNttFrElement(t *testing.T) { ntt.Ntt(scalarsCopy, core.KForward, &cfg, output) // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward)) + testAgainstGnarkCryptoNttGnarkTypes(t, testSize, scalarsCopy, output, v, core.KForward) } } } @@ -132,6 +136,8 @@ func TestNttDeviceAsync(t *testing.T) { for _, size := range []int{1, 10, largestTestSize} { for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size scalarsCopy := core.HostSliceFromElements[{{.Field}}.{{.FieldPrefix}}Field](scalars[:testSize]) @@ -154,7 +160,7 @@ func TestNttDeviceAsync(t *testing.T) { runtime.SynchronizeStream(stream) {{if ne .GnarkImport "" -}} // Compare with gnark-crypto - assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + testAgainstGnarkCryptoNtt(t, testSize, scalarsCopy, output, v, direction) {{end -}} } } @@ -169,6 +175,8 @@ func TestNttBatch(t *testing.T) { for _, size := range []int{4, largestTestSize} { for _, batchSize := range []int{2, 16, largestBatchSize} { + runtime.SetDevice(&DEVICE) + testSize := 1 << size totalSize := testSize * batchSize diff --git a/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl b/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl index ee46dcd74..fefb8a4fd 100644 --- a/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/tests/templates/main_test.go.tmpl @@ -1,10 +1,10 @@ package tests import ( - "os" - "testing" - + "testing" {{if or .SupportsNTT .SupportsPoly -}} + "fmt" + "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/core" {{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang_v3/{{.BaseImportPath}}"{{end}} {{if .SupportsNTT -}} @@ -19,6 +19,8 @@ import ( const ( largestTestSize = 20 ) +var DEVICE runtime.Device + {{if or .SupportsNTT .SupportsPoly -}} func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { {{if ne .GnarkImport "" -}} @@ -38,22 +40,36 @@ func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcic func TestMain(m *testing.M) { runtime.LoadBackendFromEnv() - device := runtime.CreateDevice("CUDA", 0) - runtime.SetDevice(&device) - - {{if or .SupportsNTT .SupportsPoly -}}// setup domain - cfg := core.GetDefaultNTTInitDomainConfig() - e := initDomain(largestTestSize, cfg) + devices, e := runtime.GetRegisteredDevices() if e != runtime.Success { - panic("initDomain failed") - }{{end}} + panic("Failed to load registered devices") + } + for _, deviceType := range devices { + DEVICE = runtime.CreateDevice(deviceType, 0) + runtime.SetDevice(&DEVICE) - // execute tests - os.Exit(m.Run()) + {{if or .SupportsNTT .SupportsPoly -}}// setup domain + cfg := core.GetDefaultNTTInitDomainConfig() + e = initDomain(largestTestSize, cfg) + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("initDomain is not implemented for ", deviceType, " device type") + } else { + panic("initDomain failed") + } + }{{end}} - {{if or .SupportsNTT .SupportsPoly -}}// release domain - e = ntt.ReleaseDomain() - if e != runtime.Success { - panic("ReleaseDomain failed") - }{{end}} + // execute tests + m.Run() + + {{if or .SupportsNTT .SupportsPoly -}}// release domain + e = ntt.ReleaseDomain() + if e != runtime.Success { + if e != runtime.ApiNotImplemented { + fmt.Println("ReleaseDomain is not implemented for ", deviceType, " device type") + } else { + panic("ReleaseDomain failed") + } + }{{end}} + } } diff --git a/wrappers/golang_v3/runtime/device.go b/wrappers/golang_v3/runtime/device.go index f59fe0e05..d3883271d 100644 --- a/wrappers/golang_v3/runtime/device.go +++ b/wrappers/golang_v3/runtime/device.go @@ -7,7 +7,7 @@ const MAX_TYPE_SIZE = 64 type Device struct { DeviceType [MAX_TYPE_SIZE]C.char - Id int + Id int32 } type DeviceProperties struct { @@ -28,7 +28,7 @@ func CreateDevice(deviceType string, id int) Device { if len(deviceType) >= MAX_TYPE_SIZE { cDeviceType[MAX_TYPE_SIZE-1] = C.char(0) } - return Device{DeviceType: cDeviceType, Id: id} + return Device{DeviceType: cDeviceType, Id: int32(id)} } func (self *Device) GetDeviceType() string { From 0cb0b49be91f1fd8812f7e276fba866b77ef2673 Mon Sep 17 00:00:00 2001 From: ChickenLover Date: Sun, 28 Jul 2024 15:31:28 +0700 Subject: [PATCH 22/38] Add Sha3 (#560) ## Describe the changes This PR... ## Linked Issues Resolves # --- docs/docs/icicle/primitives/keccak.md | 6 +- icicle/include/hash/keccak/keccak.cuh | 34 +++++- icicle/src/hash/keccak/extern.cu | 50 +++++++- icicle/src/hash/keccak/keccak.cu | 15 ++- icicle/src/merkle-tree/merkle.cu | 10 +- wrappers/rust/icicle-hash/src/keccak/mod.rs | 114 ++++++++++++++++++ wrappers/rust/icicle-hash/src/keccak/tests.rs | 2 +- 7 files changed, 213 insertions(+), 18 deletions(-) diff --git a/docs/docs/icicle/primitives/keccak.md b/docs/docs/icicle/primitives/keccak.md index 37ea9904d..e81b8f86c 100644 --- a/docs/docs/icicle/primitives/keccak.md +++ b/docs/docs/icicle/primitives/keccak.md @@ -12,6 +12,10 @@ At its core, Keccak consists of a permutation function operating on a state arra - **Chi:** This step applies a nonlinear mixing operation to each lane of the state array. - **Iota:** This step introduces a round constant to the state array. +## Keccak vs Sha3 + +There exists a [confusion](https://www.cybertest.com/blog/keccak-vs-sha3) between what is called `Keccak` and `Sha3`. In ICICLE we support both. `Keccak256` relates to the old hash function used in Ethereum, and `Sha3-256` relates to the modern hash function. + ## Using Keccak ICICLE Keccak supports batch hashing, which can be utilized for constructing a merkle tree or running multiple hashes in parallel. @@ -35,7 +39,7 @@ let input_block_len = 136; let number_of_hashes = 1024; let preimages = vec![1u8; number_of_hashes * input_block_len]; -let mut digests = vec![0u8; number_of_hashes * 64]; +let mut digests = vec![0u8; number_of_hashes * 32]; let preimages_slice = HostSlice::from_slice(&preimages); let digests_slice = HostSlice::from_mut_slice(&mut digests); diff --git a/icicle/include/hash/keccak/keccak.cuh b/icicle/include/hash/keccak/keccak.cuh index d95c22a40..01bed87ea 100644 --- a/icicle/include/hash/keccak/keccak.cuh +++ b/icicle/include/hash/keccak/keccak.cuh @@ -22,9 +22,14 @@ namespace keccak { // Number of state elements in u64 const int KECCAK_STATE_SIZE = 25; + const int KECCAK_PADDING_CONST = 1; + const int SHA3_PADDING_CONST = 6; + class Keccak : public Hasher { public: + const int PADDING_CONST; + cudaError_t run_hash_many_kernel( const uint8_t* input, uint64_t* output, @@ -33,7 +38,34 @@ namespace keccak { unsigned int output_len, const device_context::DeviceContext& ctx) const override; - Keccak(unsigned int rate) : Hasher(KECCAK_STATE_SIZE, KECCAK_STATE_SIZE, rate, 0) {} + Keccak(unsigned int rate, unsigned int padding_const) + : Hasher(KECCAK_STATE_SIZE, KECCAK_STATE_SIZE, rate, 0), PADDING_CONST(padding_const) + { + } + }; + + class Keccak256 : public Keccak + { + public: + Keccak256() : Keccak(KECCAK_256_RATE, KECCAK_PADDING_CONST) {} + }; + + class Keccak512 : public Keccak + { + public: + Keccak512() : Keccak(KECCAK_512_RATE, KECCAK_PADDING_CONST) {} + }; + + class Sha3_256 : public Keccak + { + public: + Sha3_256() : Keccak(KECCAK_256_RATE, SHA3_PADDING_CONST) {} + }; + + class Sha3_512 : public Keccak + { + public: + Sha3_512() : Keccak(KECCAK_512_RATE, SHA3_PADDING_CONST) {} }; } // namespace keccak diff --git a/icicle/src/hash/keccak/extern.cu b/icicle/src/hash/keccak/extern.cu index b1e6d6aaa..519a0e14f 100644 --- a/icicle/src/hash/keccak/extern.cu +++ b/icicle/src/hash/keccak/extern.cu @@ -11,15 +11,29 @@ namespace keccak { extern "C" cudaError_t keccak256_cuda(uint8_t* input, int input_block_size, int number_of_blocks, uint8_t* output, HashConfig& config) { - return Keccak(KECCAK_256_RATE) - .hash_many(input, (uint64_t*)output, number_of_blocks, input_block_size, KECCAK_256_DIGEST, config); + return Keccak256().hash_many( + input, (uint64_t*)output, number_of_blocks, input_block_size, KECCAK_256_DIGEST, config); } extern "C" cudaError_t keccak512_cuda(uint8_t* input, int input_block_size, int number_of_blocks, uint8_t* output, HashConfig& config) { - return Keccak(KECCAK_512_RATE) - .hash_many(input, (uint64_t*)output, number_of_blocks, input_block_size, KECCAK_512_DIGEST, config); + return Keccak512().hash_many( + input, (uint64_t*)output, number_of_blocks, input_block_size, KECCAK_512_DIGEST, config); + } + + extern "C" cudaError_t + sha3_256_cuda(uint8_t* input, int input_block_size, int number_of_blocks, uint8_t* output, HashConfig& config) + { + return Sha3_256().hash_many( + input, (uint64_t*)output, number_of_blocks, input_block_size, KECCAK_256_DIGEST, config); + } + + extern "C" cudaError_t + sha3_512_cuda(uint8_t* input, int input_block_size, int number_of_blocks, uint8_t* output, HashConfig& config) + { + return Sha3_512().hash_many( + input, (uint64_t*)output, number_of_blocks, input_block_size, KECCAK_512_DIGEST, config); } extern "C" cudaError_t build_keccak256_merkle_tree_cuda( @@ -29,7 +43,7 @@ namespace keccak { unsigned int input_block_len, const merkle_tree::TreeBuilderConfig& tree_config) { - Keccak keccak(KECCAK_256_RATE); + Keccak256 keccak; return merkle_tree::build_merkle_tree( leaves, digests, height, input_block_len, keccak, keccak, tree_config); } @@ -41,7 +55,31 @@ namespace keccak { unsigned int input_block_len, const merkle_tree::TreeBuilderConfig& tree_config) { - Keccak keccak(KECCAK_512_RATE); + Keccak512 keccak; + return merkle_tree::build_merkle_tree( + leaves, digests, height, input_block_len, keccak, keccak, tree_config); + } + + extern "C" cudaError_t build_sha3_256_merkle_tree_cuda( + const uint8_t* leaves, + uint64_t* digests, + unsigned int height, + unsigned int input_block_len, + const merkle_tree::TreeBuilderConfig& tree_config) + { + Sha3_256 keccak; + return merkle_tree::build_merkle_tree( + leaves, digests, height, input_block_len, keccak, keccak, tree_config); + } + + extern "C" cudaError_t build_sha3_512_merkle_tree_cuda( + const uint8_t* leaves, + uint64_t* digests, + unsigned int height, + unsigned int input_block_len, + const merkle_tree::TreeBuilderConfig& tree_config) + { + Sha3_512 keccak; return merkle_tree::build_merkle_tree( leaves, digests, height, input_block_len, keccak, keccak, tree_config); } diff --git a/icicle/src/hash/keccak/keccak.cu b/icicle/src/hash/keccak/keccak.cu index e805bcf63..542da24ae 100644 --- a/icicle/src/hash/keccak/keccak.cu +++ b/icicle/src/hash/keccak/keccak.cu @@ -180,8 +180,13 @@ namespace keccak { } template - __global__ void - keccak_hash_blocks(const uint8_t* input, int input_block_size, int output_len, int number_of_blocks, uint64_t* output) + __global__ void keccak_hash_blocks( + const uint8_t* input, + int input_block_size, + int output_len, + int number_of_blocks, + uint64_t* output, + int padding_const) { int sid = (blockIdx.x * blockDim.x) + threadIdx.x; if (sid >= number_of_blocks) { return; } @@ -209,7 +214,7 @@ namespace keccak { } // pad 10*1 - last_block[input_len] = 1; + last_block[input_len] = padding_const; for (int i = 0; i < R - input_len - 1; i++) { last_block[input_len + i + 1] = 0; } @@ -240,11 +245,11 @@ namespace keccak { switch (rate) { case KECCAK_256_RATE: keccak_hash_blocks<<>>( - input, input_len, output_len, number_of_states, output); + input, input_len, output_len, number_of_states, output, PADDING_CONST); break; case KECCAK_512_RATE: keccak_hash_blocks<<>>( - input, input_len, output_len, number_of_states, output); + input, input_len, output_len, number_of_states, output, PADDING_CONST); break; default: THROW_ICICLE_ERR(IcicleError_t::InvalidArgument, "KeccakHash: #rate must be one of [136, 72]"); diff --git a/icicle/src/merkle-tree/merkle.cu b/icicle/src/merkle-tree/merkle.cu index 53f3b8f6f..2fe171634 100644 --- a/icicle/src/merkle-tree/merkle.cu +++ b/icicle/src/merkle-tree/merkle.cu @@ -129,8 +129,9 @@ namespace merkle_tree { while (number_of_states > 0) { CHK_IF_RETURN(compression.run_hash_many_kernel( - (L*)prev_layer, next_layer, number_of_states, tree_config.digest_elements * tree_config.arity, - tree_config.digest_elements, hash_config.ctx)); + (L*)prev_layer, next_layer, number_of_states, + tree_config.digest_elements * tree_config.arity * (sizeof(D) / sizeof(L)), tree_config.digest_elements, + hash_config.ctx)); if (!keep_rows || subtree_height < keep_rows) { D* digests_with_offset = @@ -298,8 +299,9 @@ namespace merkle_tree { size_t segment_offset = start_segment_offset; while (number_of_states > 0) { CHK_IF_RETURN(compression.run_hash_many_kernel( - (L*)prev_layer, next_layer, number_of_states, tree_config.digest_elements * tree_config.arity, - tree_config.digest_elements, tree_config.ctx)); + (L*)prev_layer, next_layer, number_of_states, + tree_config.digest_elements * tree_config.arity * (sizeof(D) / sizeof(L)), tree_config.digest_elements, + tree_config.ctx)); if (!tree_config.keep_rows || cap_height < tree_config.keep_rows + (int)caps_mode) { D* digests_with_offset = digests + segment_offset; CHK_IF_RETURN(cudaMemcpyAsync( diff --git a/wrappers/rust/icicle-hash/src/keccak/mod.rs b/wrappers/rust/icicle-hash/src/keccak/mod.rs index 88fc5a2c7..df2cbfb73 100644 --- a/wrappers/rust/icicle-hash/src/keccak/mod.rs +++ b/wrappers/rust/icicle-hash/src/keccak/mod.rs @@ -25,6 +25,22 @@ extern "C" { config: &HashConfig, ) -> CudaError; + pub(crate) fn sha3_256_cuda( + input: *const u8, + input_block_size: u32, + number_of_blocks: u32, + output: *mut u8, + config: &HashConfig, + ) -> CudaError; + + pub(crate) fn sha3_512_cuda( + input: *const u8, + input_block_size: u32, + number_of_blocks: u32, + output: *mut u8, + config: &HashConfig, + ) -> CudaError; + pub(crate) fn build_keccak256_merkle_tree_cuda( leaves: *const u8, digests: *mut u64, @@ -40,6 +56,22 @@ extern "C" { input_block_len: u32, config: &TreeBuilderConfig, ) -> CudaError; + + pub(crate) fn build_sha3_256_merkle_tree_cuda( + leaves: *const u8, + digests: *mut u64, + height: u32, + input_block_len: u32, + config: &TreeBuilderConfig, + ) -> CudaError; + + pub(crate) fn build_sha3_512_merkle_tree_cuda( + leaves: *const u8, + digests: *mut u64, + height: u32, + input_block_len: u32, + config: &TreeBuilderConfig, + ) -> CudaError; } pub fn keccak256( @@ -86,6 +118,50 @@ pub fn keccak512( } } +pub fn sha3_256( + input: &(impl HostOrDeviceSlice + ?Sized), + input_block_size: u32, + number_of_blocks: u32, + output: &mut (impl HostOrDeviceSlice + ?Sized), + config: &HashConfig, +) -> IcicleResult<()> { + let mut local_cfg = config.clone(); + local_cfg.are_inputs_on_device = input.is_on_device(); + local_cfg.are_outputs_on_device = output.is_on_device(); + unsafe { + sha3_256_cuda( + input.as_ptr(), + input_block_size, + number_of_blocks, + output.as_mut_ptr(), + &local_cfg, + ) + .wrap() + } +} + +pub fn sha3_512( + input: &(impl HostOrDeviceSlice + ?Sized), + input_block_size: u32, + number_of_blocks: u32, + output: &mut (impl HostOrDeviceSlice + ?Sized), + config: &HashConfig, +) -> IcicleResult<()> { + let mut local_cfg = config.clone(); + local_cfg.are_inputs_on_device = input.is_on_device(); + local_cfg.are_outputs_on_device = output.is_on_device(); + unsafe { + sha3_512_cuda( + input.as_ptr(), + input_block_size, + number_of_blocks, + output.as_mut_ptr(), + &local_cfg, + ) + .wrap() + } +} + pub fn build_keccak256_merkle_tree( leaves: &(impl HostOrDeviceSlice + ?Sized), digests: &mut (impl HostOrDeviceSlice + ?Sized), @@ -123,3 +199,41 @@ pub fn build_keccak512_merkle_tree( .wrap() } } + +pub fn build_sha3_256_merkle_tree( + leaves: &(impl HostOrDeviceSlice + ?Sized), + digests: &mut (impl HostOrDeviceSlice + ?Sized), + height: usize, + input_block_len: usize, + config: &TreeBuilderConfig, +) -> IcicleResult<()> { + unsafe { + build_sha3_256_merkle_tree_cuda( + leaves.as_ptr(), + digests.as_mut_ptr(), + height as u32, + input_block_len as u32, + config, + ) + .wrap() + } +} + +pub fn build_sha3_512_merkle_tree( + leaves: &(impl HostOrDeviceSlice + ?Sized), + digests: &mut (impl HostOrDeviceSlice + ?Sized), + height: usize, + input_block_len: usize, + config: &TreeBuilderConfig, +) -> IcicleResult<()> { + unsafe { + build_sha3_512_merkle_tree_cuda( + leaves.as_ptr(), + digests.as_mut_ptr(), + height as u32, + input_block_len as u32, + config, + ) + .wrap() + } +} diff --git a/wrappers/rust/icicle-hash/src/keccak/tests.rs b/wrappers/rust/icicle-hash/src/keccak/tests.rs index 5675e9158..0aa8cbc0e 100644 --- a/wrappers/rust/icicle-hash/src/keccak/tests.rs +++ b/wrappers/rust/icicle-hash/src/keccak/tests.rs @@ -15,7 +15,7 @@ pub(crate) mod tests { let number_of_hashes = 1024; let preimages = vec![1u8; number_of_hashes * input_block_len]; - let mut digests = vec![0u8; number_of_hashes * 64]; + let mut digests = vec![0u8; number_of_hashes * 32]; let preimages_slice = HostSlice::from_slice(&preimages); let digests_slice = HostSlice::from_mut_slice(&mut digests); From 65d66719d2d66c1152b82910083b4f8395286935 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Sun, 28 Jul 2024 08:54:17 +0000 Subject: [PATCH 23/38] ci and build script --- .github/workflows/v3_golang.yml | 161 +++++++++++++ .github/workflows/v3_rust.yml | 2 +- wrappers/golang_v3/build.sh | 222 +++++++++--------- wrappers/golang_v3/curves/bls12377/main.go | 2 +- wrappers/golang_v3/curves/bls12381/main.go | 2 +- wrappers/golang_v3/curves/bn254/main.go | 2 +- .../golang_v3/curves/bn254/tests/msm_test.go | 2 +- wrappers/golang_v3/curves/bw6761/main.go | 2 +- wrappers/golang_v3/curves/grumpkin/main.go | 2 +- wrappers/golang_v3/fields/babybear/main.go | 2 +- .../generator/curves/templates/main.go.tmpl | 2 +- .../generator/fields/templates/main.go.tmpl | 2 +- wrappers/golang_v3/runtime/main.go | 2 +- wrappers/golang_v3/runtime/runtime.go | 5 +- 14 files changed, 290 insertions(+), 120 deletions(-) create mode 100644 .github/workflows/v3_golang.yml diff --git a/.github/workflows/v3_golang.yml b/.github/workflows/v3_golang.yml new file mode 100644 index 000000000..1a0951f0e --- /dev/null +++ b/.github/workflows/v3_golang.yml @@ -0,0 +1,161 @@ +name: GoLang + +on: + pull_request: + branches: + - V3 + - yshekel/V3 # TODO remove when merged to V3 + push: + branches: + - V3 + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check-changed-files: + uses: ./.github/workflows/check-changed-files.yml + + check-format: + name: Check Code Format + runs-on: ubuntu-22.04 + needs: check-changed-files + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version: '1.20.0' + - name: Check gofmt + if: needs.check-changed-files.outputs.golang == 'true' + run: if [[ $(go list ./... | xargs go fmt) ]]; then echo "Please run go fmt"; exit 1; fi + + build-curves-linux: + name: Build and test curves on Linux + runs-on: [self-hosted, Linux, X64, icicle] + needs: [check-changed-files, check-format] + strategy: + matrix: + curve: + - name: bn254 + build_args: -g2 -ecntt + - name: bls12_381 + build_args: -g2 -ecntt + - name: bls12_377 + build_args: -g2 -ecntt + - name: bw6_761 + build_args: -g2 -ecntt + - name: grumpkin + build_args: + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version: '1.20.0' + - name: Build + working-directory: ./wrappers/golang_v3 + if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + # builds a single curve with the curve's specified build args + run: ./build.sh -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} + - name: Test + working-directory: ./wrappers/golang_v3/curves + if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + run: | + CURVE=$(echo ${{ matrix.curve.name }} | sed -e 's/_//g') + export CPATH=$CPATH:/usr/local/cuda/include + go test ./$CURVE/tests -count=1 -failfast -p 2 -timeout 60m -v + + build-fields-linux: + name: Build and test fields on Linux + runs-on: [self-hosted, Linux, X64, icicle] + needs: [check-changed-files, check-format] + strategy: + matrix: + field: + - name: babybear + build_args: -field-ext + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version: '1.20.0' + - name: Build + working-directory: ./wrappers/golang_v3 + if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + # builds a single field with the fields specified build args + run: ./build.sh -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} + - name: Test + working-directory: ./wrappers/golang_v3/fields + if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + run: | + FIELD=$(echo ${{ matrix.field.name }} | sed -e 's/_//g') + export CPATH=$CPATH:/usr/local/cuda/include + go test ./$FIELD/tests -count=1 -failfast -p 2 -timeout 60m -v + + # build-hashes-linux: + # name: Build and test hashes on Linux + # runs-on: [self-hosted, Linux, X64, icicle] + # needs: [check-changed-files, check-format] + # strategy: + # matrix: + # hash: + # - name: keccak + # build_args: + # steps: + # - name: Checkout Repo + # uses: actions/checkout@v4 + # - name: Setup go + # uses: actions/setup-go@v5 + # with: + # go-version: '1.20.0' + # - name: Build + # working-directory: ./wrappers/golang_v3 + # if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + # # builds a single hash algorithm with the hash's specified build args + # run: ./build.sh -hash=${{ matrix.hash.name }} ${{ matrix.hash.build_args }} + # - name: Test + # working-directory: ./wrappers/golang_v3/hash + # if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + # run: | + # HASH=$(echo ${{ matrix.hash.name }} | sed -e 's/_//g') + # export CPATH=$CPATH:/usr/local/cuda/include + # go test ./$HASH/tests -count=1 -failfast -p 2 -timeout 60m -v + + # TODO: bw6 on windows requires more memory than the standard runner has + # Add a large runner and then enable this job + # build-windows: + # name: Build on Windows + # runs-on: windows-2022 + # needs: [check-changed-files, check-format] + # strategy: + # matrix: + # curve: [bn254, bls12_381, bls12_377, bw6_761] + # steps: + # - name: Checkout Repo + # uses: actions/checkout@v4 + # - name: Setup go + # uses: actions/setup-go@v5 + # with: + # go-version: '1.20.0' + # - name: Download and Install Cuda + # if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + # id: cuda-toolkit + # uses: Jimver/cuda-toolkit@v0.2.11 + # with: + # cuda: '12.0.0' + # method: 'network' + # # https://docs.nvidia.com/cuda/archive/12.0.0/cuda-installation-guide-microsoft-windows/index.html + # sub-packages: '["cudart", "nvcc", "thrust", "visual_studio_integration"]' + # - name: Build libs + # if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + # working-directory: ./wrappers/golang + # env: + # CUDA_PATH: ${{ steps.cuda-toolkit.outputs.CUDA_PATH }} + # shell: pwsh + # run: ./build.ps1 ${{ matrix.curve }} ON # builds a single curve with G2 enabled diff --git a/.github/workflows/v3_rust.yml b/.github/workflows/v3_rust.yml index 1c17b5e98..5a4fdb42d 100644 --- a/.github/workflows/v3_rust.yml +++ b/.github/workflows/v3_rust.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@v4 - name: Check rustfmt if: needs.check-changed-files.outputs.rust == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' - working-directory: ./wrappers/rust + working-directory: ./wrappers/rust_v3 # "-name target -prune" removes searching in any directory named "target" # Formatting by single file is necessary due to generated files not being present # before building the project. diff --git a/wrappers/golang_v3/build.sh b/wrappers/golang_v3/build.sh index e3fc6d23a..a89bfb351 100755 --- a/wrappers/golang_v3/build.sh +++ b/wrappers/golang_v3/build.sh @@ -1,122 +1,128 @@ #!/bin/bash -# G2_DEFINED=OFF -# ECNTT_DEFINED=OFF -# CUDA_COMPILER_PATH=/usr/local/cuda/bin/nvcc -# DEVMODE=OFF -# EXT_FIELD=OFF -# BUILD_CURVES=( ) -# BUILD_FIELDS=( ) -# BUILD_HASHES=( ) +G2_DEFINED=OFF +ECNTT_DEFINED=OFF +CUDA_COMPILER_PATH=/usr/local/cuda/bin/nvcc -# SUPPORTED_CURVES=("bn254" "bls12_377" "bls12_381" "bw6_761", "grumpkin") -# SUPPORTED_FIELDS=("babybear") -# SUPPORTED_HASHES=("keccak") +DEVMODE=OFF +EXT_FIELD=OFF +BUILD_CURVES=( ) +BUILD_FIELDS=( ) +BUILD_HASHES=( ) -# if [[ $1 == "-help" ]]; then -# echo "Build script for building ICICLE cpp libraries" -# echo "" -# echo "If more than one curve or more than one field is supplied, the last one supplied will be built" -# echo "" -# echo "USAGE: ./build.sh [OPTION...]" -# echo "" -# echo "OPTIONS:" -# echo " -curve= The curve that should be built. If \"all\" is supplied," -# echo " all curves will be built with any other supplied curve options" -# echo " -g2 Builds the curve lib with G2 enabled" -# echo " -ecntt Builds the curve lib with ECNTT enabled" -# echo " -field= The field that should be built. If \"all\" is supplied," -# echo " all fields will be built with any other supplied field options" -# echo " -field-ext Builds the field lib with the extension field enabled" -# echo " -devmode Enables devmode debugging and fast build times" -# echo " -cuda_version= The version of cuda to use for compiling" -# echo "" -# exit 0 -# fi +SUPPORTED_CURVES=("bn254" "bls12_377" "bls12_381" "bw6_761", "grumpkin") +SUPPORTED_FIELDS=("babybear") +# SUPPORTED_HASHES=("keccak") -# for arg in "$@" -# do -# arg_lower=$(echo "$arg" | tr '[:upper:]' '[:lower:]') -# case "$arg_lower" in -# -cuda_version=*) -# cuda_version=$(echo "$arg" | cut -d'=' -f2) -# CUDA_COMPILER_PATH=/usr/local/cuda-$cuda_version/bin/nvcc -# ;; -# -ecntt) -# ECNTT_DEFINED=ON -# ;; -# -g2) -# G2_DEFINED=ON -# ;; -# -curve=*) -# curve=$(echo "$arg_lower" | cut -d'=' -f2) -# if [[ $curve == "all" ]] -# then -# BUILD_CURVES=("${SUPPORTED_CURVES[@]}") -# else -# BUILD_CURVES=( $curve ) -# fi -# ;; -# -field=*) -# field=$(echo "$arg_lower" | cut -d'=' -f2) -# if [[ $field == "all" ]] -# then -# BUILD_FIELDS=("${SUPPORTED_FIELDS[@]}") -# else -# BUILD_FIELDS=( $field ) -# fi -# ;; -# -field-ext) -# EXT_FIELD=ON -# ;; -# -hash*) -# hash=$(echo "$arg_lower" | cut -d'=' -f2) -# if [[ $hash == "all" ]] -# then -# BUILD_HASHES=("${SUPPORTED_HASHES[@]}") -# else -# BUILD_HASHES=( $hash ) -# fi -# ;; -# -devmode) -# DEVMODE=ON -# ;; -# *) -# echo "Unknown argument: $arg" -# exit 1 -# ;; -# esac -# done +BUILD_DIR="${ICICLE_BUILD_DIR:-$(realpath "$PWD/../../icicle_v3/build")}" +DEFAULT_BACKEND_INSTALL_DIR="${DEFAULT_BACKEND_INSTALL_DIR:="/usr/local/"}" +if [[ $1 == "-help" ]]; then + echo "Build script for building ICICLE cpp libraries" + echo "" + echo "If more than one curve or more than one field is supplied, the last one supplied will be built" + echo "" + echo "USAGE: ./build.sh [OPTION...]" + echo "" + echo "OPTIONS:" + echo " -curve= The curve that should be built. If \"all\" is supplied," + echo " all curves will be built with any other supplied curve options" + echo " -g2 Builds the curve lib with G2 enabled" + echo " -ecntt Builds the curve lib with ECNTT enabled" + echo " -field= The field that should be built. If \"all\" is supplied," + echo " all fields will be built with any other supplied field options" + echo " -field-ext Builds the field lib with the extension field enabled" + echo " -backend Path to the folder where libraries will be installed" + echo " -devmode Enables devmode debugging and fast build times" + echo " -cuda_version= The version of cuda to use for compiling" + echo "" + exit 0 +fi -BUILD_DIR="${ICICLE_BUILD_DIR:-$(realpath "$PWD/../../icicle_v3/build")}" -export DEFAULT_BACKEND_INSTALL_DIR="${DEFAULT_BACKEND_INSTALL_DIR:="${BUILD_DIR}/backend"}" +for arg in "$@" +do + arg_lower=$(echo "$arg" | tr '[:upper:]' '[:lower:]') + case "$arg_lower" in + -cuda_version=*) + cuda_version=$(echo "$arg" | cut -d'=' -f2) + CUDA_COMPILER_PATH=/usr/local/cuda-$cuda_version/bin/nvcc + ;; + -backend=*) + DEFAULT_BACKEND_INSTALL_DIR=$(echo "$arg_lower" | cut -d'=' -f2) + ;; + -ecntt) + ECNTT_DEFINED=ON + ;; + -g2) + G2_DEFINED=ON + ;; + -curve=*) + curve=$(echo "$arg_lower" | cut -d'=' -f2) + if [[ $curve == "all" ]] + then + BUILD_CURVES=("${SUPPORTED_CURVES[@]}") + else + BUILD_CURVES=( $curve ) + fi + ;; + -field=*) + field=$(echo "$arg_lower" | cut -d'=' -f2) + if [[ $field == "all" ]] + then + BUILD_FIELDS=("${SUPPORTED_FIELDS[@]}") + else + BUILD_FIELDS=( $field ) + fi + ;; + -field-ext) + EXT_FIELD=ON + ;; + -hash*) + hash=$(echo "$arg_lower" | cut -d'=' -f2) + if [[ $hash == "all" ]] + then + BUILD_HASHES=("${SUPPORTED_HASHES[@]}") + else + BUILD_HASHES=( $hash ) + fi + ;; + -devmode) + DEVMODE=ON + ;; + *) + echo "Unknown argument: $arg" + exit 1 + ;; + esac +done -# cd ../../icicle -# mkdir -p build -# rm -f "$BUILD_DIR/CMakeCache.txt" +cd ../../icicle_v3 +mkdir -p build +rm -f "$BUILD_DIR/CMakeCache.txt" -# for CURVE in "${BUILD_CURVES[@]}" -# do -# echo "CURVE=${CURVE}" > build_config.txt -# echo "ECNTT=${ECNTT_DEFINED}" >> build_config.txt -# echo "G2=${G2_DEFINED}" >> build_config.txt -# echo "DEVMODE=${DEVMODE}" >> build_config.txt -# cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCURVE=$CURVE -DG2=$G2_DEFINED -DECNTT=$ECNTT_DEFINED -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build -# cmake --build build -j8 && rm build_config.txt -# done +for CURVE in "${BUILD_CURVES[@]}" +do + echo "CURVE=${CURVE}" > build_config.txt + echo "ECNTT=${ECNTT_DEFINED}" >> build_config.txt + echo "G2=${G2_DEFINED}" >> build_config.txt + echo "DEVMODE=${DEVMODE}" >> build_config.txt + echo "DEFAULT_BACKEND_INSTALL_DIR=${DEFAULT_BACKEND_INSTALL_DIR}" >> build_config.txt + cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCMAKE_INSTALL_PREFIX=$DEFAULT_BACKEND_INSTALL_DIR -DCURVE=$CURVE -DG2=$G2_DEFINED -DECNTT=$ECNTT_DEFINED -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build + cmake --build build --target install -j8 && rm build_config.txt +done -# # Needs to remove the CMakeCache.txt file to allow building fields after curves -# # have been built since CURVE and FIELD cannot both be defined -# rm -f "$BUILD_DIR/CMakeCache.txt" +# Needs to remove the CMakeCache.txt file to allow building fields after curves +# have been built since CURVE and FIELD cannot both be defined +rm -f "$BUILD_DIR/CMakeCache.txt" -# for FIELD in "${BUILD_FIELDS[@]}" -# do -# echo "FIELD=${FIELD}" > build_config.txt -# echo "DEVMODE=${DEVMODE}" >> build_config.txt -# cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DFIELD=$FIELD -DEXT_FIELD=$EXT_FIELD -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build -# cmake --build build -j8 && rm build_config.txt -# done +for FIELD in "${BUILD_FIELDS[@]}" +do + echo "FIELD=${FIELD}" > build_config.txt + echo "DEVMODE=${DEVMODE}" >> build_config.txt + echo "DEFAULT_BACKEND_INSTALL_DIR=${DEFAULT_BACKEND_INSTALL_DIR}" >> build_config.txt + cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCMAKE_INSTALL_PREFIX=$DEFAULT_BACKEND_INSTALL_DIR -DFIELD=$FIELD -DEXT_FIELD=$EXT_FIELD -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build + cmake --build build --target install -j8 && rm build_config.txt +done # for HASH in "${BUILD_HASHES[@]}" # do diff --git a/wrappers/golang_v3/curves/bls12377/main.go b/wrappers/golang_v3/curves/bls12377/main.go index 3e87e611e..f41ffc1e7 100644 --- a/wrappers/golang_v3/curves/bls12377/main.go +++ b/wrappers/golang_v3/curves/bls12377/main.go @@ -1,4 +1,4 @@ package bls12377 -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bls12_377 -licicle_curve_bls12_377 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_field_bls12_377 -licicle_curve_bls12_377 -lstdc++ -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/curves/bls12381/main.go b/wrappers/golang_v3/curves/bls12381/main.go index 6320483cd..8f7ad0a02 100644 --- a/wrappers/golang_v3/curves/bls12381/main.go +++ b/wrappers/golang_v3/curves/bls12381/main.go @@ -1,4 +1,4 @@ package bls12381 -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bls12_381 -licicle_curve_bls12_381 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_field_bls12_381 -licicle_curve_bls12_381 -lstdc++ -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/curves/bn254/main.go b/wrappers/golang_v3/curves/bn254/main.go index 92fc43dd3..86a7664dc 100644 --- a/wrappers/golang_v3/curves/bn254/main.go +++ b/wrappers/golang_v3/curves/bn254/main.go @@ -1,4 +1,4 @@ package bn254 -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index 7011c0052..9b25f7782 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -231,7 +231,7 @@ func TestPrecomputePoints(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10} { + for _, power := range []int{10, 16} { for _, batchSize := range []int{1, 3, 16} { runtime.SetDevice(&DEVICE) diff --git a/wrappers/golang_v3/curves/bw6761/main.go b/wrappers/golang_v3/curves/bw6761/main.go index d93ca331e..a055689df 100644 --- a/wrappers/golang_v3/curves/bw6761/main.go +++ b/wrappers/golang_v3/curves/bw6761/main.go @@ -1,4 +1,4 @@ package bw6761 -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_bw6_761 -licicle_curve_bw6_761 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_field_bw6_761 -licicle_curve_bw6_761 -lstdc++ -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/curves/grumpkin/main.go b/wrappers/golang_v3/curves/grumpkin/main.go index 68f05d26c..edbfe8f23 100644 --- a/wrappers/golang_v3/curves/grumpkin/main.go +++ b/wrappers/golang_v3/curves/grumpkin/main.go @@ -1,4 +1,4 @@ package grumpkin -// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle_v3/build -licicle_field_grumpkin -licicle_curve_grumpkin -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_field_grumpkin -licicle_curve_grumpkin -lstdc++ -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/fields/babybear/main.go b/wrappers/golang_v3/fields/babybear/main.go index 117f7b8a3..892eafcee 100644 --- a/wrappers/golang_v3/fields/babybear/main.go +++ b/wrappers/golang_v3/fields/babybear/main.go @@ -1,4 +1,4 @@ package babybear -// #cgo LDFLAGS: -L${SRCDIR}/../../../icicle_v3/build -licicle_field_babybear -lstdc++ -Wl,-rpath=${SRCDIR}/../../../icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_field_babybear -lstdc++ -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl index 76f3c9884..de4b29d6a 100644 --- a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl +++ b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl @@ -1,4 +1,4 @@ package {{.PackageName}} -// #cgo LDFLAGS: -L${SRCDIR}/../../../../{{.UpDirs}}icicle_v3/build -licicle_field_{{.Field}} -licicle_curve_{{.Field}} -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../{{.UpDirs}}icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_field_{{.Field}} -licicle_curve_{{.Field}} -lstdc++ -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl index f97a377a5..f71b7aa71 100644 --- a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl +++ b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl @@ -1,4 +1,4 @@ package {{.PackageName}} -// #cgo LDFLAGS: -L${SRCDIR}/../../../{{.UpDirs}}icicle_v3/build -licicle_field_{{.Field}} -lstdc++ -Wl,-rpath=${SRCDIR}/../../../{{.UpDirs}}icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_field_{{.Field}} -lstdc++ -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/runtime/main.go b/wrappers/golang_v3/runtime/main.go index da22d0b19..c146ef740 100644 --- a/wrappers/golang_v3/runtime/main.go +++ b/wrappers/golang_v3/runtime/main.go @@ -1,4 +1,4 @@ package runtime -// #cgo LDFLAGS: -L${SRCDIR}/../../../icicle_v3/build -licicle_device -lstdc++ -lm -Wl,-rpath=${SRCDIR}/../../../icicle_v3/build +// #cgo LDFLAGS: -Lusr/local/ -licicle_device -lstdc++ -lm -Wl,-rpath=usr/local/ import "C" diff --git a/wrappers/golang_v3/runtime/runtime.go b/wrappers/golang_v3/runtime/runtime.go index a0a7e04a1..fad3b592f 100644 --- a/wrappers/golang_v3/runtime/runtime.go +++ b/wrappers/golang_v3/runtime/runtime.go @@ -18,7 +18,10 @@ func LoadBackend(path string, isRecursive bool) EIcicleError { } func LoadBackendFromEnv() EIcicleError { - path := os.Getenv("DEFAULT_BACKEND_INSTALL_DIR") + path, exists := os.LookupEnv("DEFAULT_BACKEND_INSTALL_DIR") + if !exists { + path = "usr/local/" + } return LoadBackend(path, true) } From 8852c9b39d2a40a3f4343af7d878ed6ad7e4554d Mon Sep 17 00:00:00 2001 From: nonam3e Date: Sun, 28 Jul 2024 09:04:10 +0000 Subject: [PATCH 24/38] rust fmt --- wrappers/rust_v3/icicle-core/src/curve.rs | 44 ++++++++----------- wrappers/rust_v3/icicle-core/src/field.rs | 2 +- wrappers/rust_v3/icicle-core/src/lib.rs | 2 +- wrappers/rust_v3/icicle-core/src/msm/mod.rs | 5 ++- wrappers/rust_v3/icicle-core/src/msm/tests.rs | 18 ++++---- wrappers/rust_v3/icicle-core/src/ntt/tests.rs | 2 +- .../icicle-core/src/polynomials/mod.rs | 11 +++-- .../rust_v3/icicle-core/src/vec_ops/mod.rs | 8 ++-- .../rust_v3/icicle-core/src/vec_ops/tests.rs | 7 ++- .../icicle-bls12-377/src/ecntt/mod.rs | 2 +- .../icicle-curves/icicle-bls12-377/src/lib.rs | 2 +- .../icicle-bls12-377/src/ntt/mod.rs | 2 +- .../icicle-bls12-381/src/ecntt/mod.rs | 2 +- .../icicle-curves/icicle-bls12-381/src/lib.rs | 2 +- .../icicle-bn254/src/ecntt/mod.rs | 2 +- .../icicle-curves/icicle-bn254/src/lib.rs | 2 +- .../icicle-fields/icicle-babybear/src/lib.rs | 2 +- .../icicle-babybear/src/ntt/mod.rs | 8 ++-- .../icicle-fields/icicle-stark252/src/lib.rs | 2 +- .../icicle-stark252/src/ntt/mod.rs | 11 +++-- wrappers/rust_v3/icicle-runtime/src/device.rs | 1 - wrappers/rust_v3/icicle-runtime/src/memory.rs | 18 ++++---- .../rust_v3/icicle-runtime/src/runtime.rs | 6 +-- 23 files changed, 83 insertions(+), 78 deletions(-) diff --git a/wrappers/rust_v3/icicle-core/src/curve.rs b/wrappers/rust_v3/icicle-core/src/curve.rs index 1c686618e..8b0f2cbe7 100644 --- a/wrappers/rust_v3/icicle-core/src/curve.rs +++ b/wrappers/rust_v3/icicle-core/src/curve.rs @@ -19,9 +19,19 @@ pub trait Curve: Debug + PartialEq + Copy + Clone { #[doc(hidden)] fn generate_random_affine_points(size: usize) -> Vec>; #[doc(hidden)] - fn convert_affine_montgomery(points: *mut Affine, len: usize, is_into: bool, stream: &IcicleStream) -> eIcicleError; + fn convert_affine_montgomery( + points: *mut Affine, + len: usize, + is_into: bool, + stream: &IcicleStream, + ) -> eIcicleError; #[doc(hidden)] - fn convert_projective_montgomery(points: *mut Projective, len: usize, is_into: bool, stream: &IcicleStream) -> eIcicleError; + fn convert_projective_montgomery( + points: *mut Projective, + len: usize, + is_into: bool, + stream: &IcicleStream, + ) -> eIcicleError; } /// A [projective](https://hyperelliptic.org/EFD/g1p/auto-shortw-projective.html) elliptic curve point. @@ -118,14 +128,14 @@ impl From> for Affine { impl MontgomeryConvertible for Affine { fn to_mont(values: &mut DeviceSlice, stream: &IcicleStream) -> eIcicleError { - if !values.is_on_active_device(){ + if !values.is_on_active_device() { panic!("values not allocated on an inactive device"); } C::convert_affine_montgomery(unsafe { values.as_mut_ptr() }, values.len(), true, stream) } fn from_mont(values: &mut DeviceSlice, stream: &IcicleStream) -> eIcicleError { - if !values.is_on_active_device(){ + if !values.is_on_active_device() { panic!("values not allocated on an inactive device"); } C::convert_affine_montgomery(unsafe { values.as_mut_ptr() }, values.len(), false, stream) @@ -134,14 +144,14 @@ impl MontgomeryConvertible for Affine { impl MontgomeryConvertible for Projective { fn to_mont(values: &mut DeviceSlice, stream: &IcicleStream) -> eIcicleError { - if !values.is_on_active_device(){ + if !values.is_on_active_device() { panic!("values not allocated on an inactive device"); } C::convert_projective_montgomery(unsafe { values.as_mut_ptr() }, values.len(), true, stream) } fn from_mont(values: &mut DeviceSlice, stream: &IcicleStream) -> eIcicleError { - if !values.is_on_active_device(){ + if !values.is_on_active_device() { panic!("values not allocated on an inactive device"); } C::convert_projective_montgomery(unsafe { values.as_mut_ptr() }, values.len(), false, stream) @@ -238,15 +248,7 @@ macro_rules! impl_curve { config.is_result_on_device = true; config.is_async = false; config.stream_handle = (&*stream).into(); - unsafe { - $curve_prefix_ident::_convert_affine_montgomery( - points, - len, - is_into, - &config, - points - ) - } + unsafe { $curve_prefix_ident::_convert_affine_montgomery(points, len, is_into, &config, points) } } fn convert_projective_montgomery( @@ -260,15 +262,7 @@ macro_rules! impl_curve { config.is_result_on_device = true; config.is_async = false; config.stream_handle = (&*stream).into(); - unsafe { - $curve_prefix_ident::_convert_projective_montgomery( - points, - len, - is_into, - &config, - points - ) - } + unsafe { $curve_prefix_ident::_convert_projective_montgomery(points, len, is_into, &config, points) } } } }; @@ -306,4 +300,4 @@ macro_rules! impl_curve_tests { } } }; -} \ No newline at end of file +} diff --git a/wrappers/rust_v3/icicle-core/src/field.rs b/wrappers/rust_v3/icicle-core/src/field.rs index dd10b35eb..4bcec6fe2 100644 --- a/wrappers/rust_v3/icicle-core/src/field.rs +++ b/wrappers/rust_v3/icicle-core/src/field.rs @@ -190,7 +190,7 @@ macro_rules! impl_scalar_field { } impl MontgomeryConvertibleField<$field_name> for $field_cfg { - fn to_mont(values: &mut DeviceSlice<$field_name>, stream: &IcicleStream) -> eIcicleError { + fn to_mont(values: &mut DeviceSlice<$field_name>, stream: &IcicleStream) -> eIcicleError { // check device slice is on active device if !values.is_on_active_device() { panic!("input not allocated on an inactive device"); diff --git a/wrappers/rust_v3/icicle-core/src/lib.rs b/wrappers/rust_v3/icicle-core/src/lib.rs index a7c318f60..dcb887bec 100644 --- a/wrappers/rust_v3/icicle-core/src/lib.rs +++ b/wrappers/rust_v3/icicle-core/src/lib.rs @@ -3,8 +3,8 @@ pub mod ecntt; pub mod field; pub mod msm; pub mod ntt; -pub mod vec_ops; pub mod polynomials; +pub mod vec_ops; #[doc(hidden)] pub mod test_utilities; diff --git a/wrappers/rust_v3/icicle-core/src/msm/mod.rs b/wrappers/rust_v3/icicle-core/src/msm/mod.rs index ea7af722c..9784b068e 100644 --- a/wrappers/rust_v3/icicle-core/src/msm/mod.rs +++ b/wrappers/rust_v3/icicle-core/src/msm/mod.rs @@ -33,7 +33,8 @@ pub struct MSMConfig { pub bitsize: i32, pub batch_size: i32, - pub are_bases_shared: bool, /// MSMs in batch share the bases. If false, expecting #bases==#scalars + pub are_bases_shared: bool, + /// MSMs in batch share the bases. If false, expecting #bases==#scalars are_scalars_on_device: bool, pub are_scalars_montgomery_form: bool, are_bases_on_device: bool, @@ -54,7 +55,7 @@ pub const IS_BIG_TRIANGLE: &str = "is_big_triangle"; impl Default for MSMConfig { fn default() -> Self { Self { - stream_handle: std::ptr::null_mut(), + stream_handle: std::ptr::null_mut(), precompute_factor: 1, c: 0, bitsize: 0, diff --git a/wrappers/rust_v3/icicle-core/src/msm/tests.rs b/wrappers/rust_v3/icicle-core/src/msm/tests.rs index f0ca66e01..a85efc322 100644 --- a/wrappers/rust_v3/icicle-core/src/msm/tests.rs +++ b/wrappers/rust_v3/icicle-core/src/msm/tests.rs @@ -2,12 +2,12 @@ use crate::curve::{Affine, Curve, Projective}; use crate::msm::{msm, precompute_bases, MSMConfig, LARGE_BUCKET_FACTOR, MSM}; use crate::test_utilities; use crate::traits::{FieldImpl, GenerateRandom, MontgomeryConvertible}; +use icicle_runtime::memory::HostOrDeviceSlice; use icicle_runtime::{ memory::{DeviceVec, HostSlice}, runtime, stream::IcicleStream, }; -use icicle_runtime::memory::HostOrDeviceSlice; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rand::thread_rng; @@ -101,7 +101,7 @@ where ::Config: GenerateRandom, { // let test_sizes = [1000, 1 << 16]; //TODO - uncomment this line after implementing fast msm - let test_sizes = [100]; + let test_sizes = [100]; // let batch_sizes = [1, 3, 1 << 4]; let batch_sizes = [1, 3]; //TODO - uncomment this line after implementing fast msm let mut stream = IcicleStream::create().unwrap(); @@ -181,10 +181,10 @@ where pub fn check_msm_batch_shared>() where -::Config: GenerateRandom, + ::Config: GenerateRandom, { // let test_sizes = [1000, 1 << 16]; //TODO - uncomment this line after implementing fast msm - let test_sizes = [100]; + let test_sizes = [100]; // let batch_sizes = [1, 3, 1 << 4]; let batch_sizes = [1, 3]; //TODO - uncomment this line after implementing fast msm let mut stream = IcicleStream::create().unwrap(); @@ -264,10 +264,10 @@ where pub fn check_msm_batch_not_shared>() where -::Config: GenerateRandom, + ::Config: GenerateRandom, { // let test_sizes = [1000, 1 << 16]; //TODO - uncomment this line after implementing fast msm - let test_sizes = [100]; + let test_sizes = [100]; // let batch_sizes = [1, 3, 1 << 4]; let batch_sizes = [3, 5]; //TODO - uncomment this line after implementing fast msm let mut stream = IcicleStream::create().unwrap(); @@ -351,12 +351,12 @@ where { // let test_sizes = [1 << 10, 10000]; // TODO - uncomment this line after implementing fast msm let test_sizes = [1 << 10]; // TODO - remove this line after implementing fast msm - // let test_threshold = 1 << 11; // TODO - uncomment this line after implementing fast msm - // let batch_sizes = [1, 3, 1 << 4]; // TODO - uncomment this line after implementing fast msm + // let test_threshold = 1 << 11; // TODO - uncomment this line after implementing fast msm + // let batch_sizes = [1, 3, 1 << 4]; // TODO - uncomment this line after implementing fast msm let batch_sizes = [1, 3]; // TODO - remove this line after implementing fast msm let rng = &mut thread_rng(); for test_size in test_sizes { - let test_threshold = test_size>>2; // TODO - remove this line after implementing fast msm + let test_threshold = test_size >> 2; // TODO - remove this line after implementing fast msm for batch_size in batch_sizes { let points = generate_random_affine_points_with_zeroes::(test_size * batch_size, 100); let mut scalars = vec![C::ScalarField::zero(); test_size * batch_size]; diff --git a/wrappers/rust_v3/icicle-core/src/ntt/tests.rs b/wrappers/rust_v3/icicle-core/src/ntt/tests.rs index 570a2526c..a2f9ee6e5 100644 --- a/wrappers/rust_v3/icicle-core/src/ntt/tests.rs +++ b/wrappers/rust_v3/icicle-core/src/ntt/tests.rs @@ -239,7 +239,7 @@ where let coset_generators = [ F::Config::generate_random(1)[0], get_root_of_unity::(test_size as u64), - F::one(), + F::one(), ]; for coset_gen in coset_generators { let mut scalars = F::Config::generate_random(test_size); diff --git a/wrappers/rust_v3/icicle-core/src/polynomials/mod.rs b/wrappers/rust_v3/icicle-core/src/polynomials/mod.rs index 3f7a86032..f053e0e1f 100644 --- a/wrappers/rust_v3/icicle-core/src/polynomials/mod.rs +++ b/wrappers/rust_v3/icicle-core/src/polynomials/mod.rs @@ -140,7 +140,7 @@ macro_rules! impl_univariate_polynomial_api { pub fn coeffs_mut_slice(&mut self) -> &mut DeviceSlice<$field> { unsafe { - let mut len: u64 = 0; + let mut len: u64 = 0; let mut coeffs_mut = get_coeffs_ptr(self.handle, &mut len); let s = slice::from_raw_parts_mut(coeffs_mut, len as usize); DeviceSlice::from_mut_slice(s) @@ -413,9 +413,12 @@ macro_rules! impl_polynomial_tests { $field:ident ) => { use super::*; - use icicle_core::ntt::{get_root_of_unity, initialize_domain, release_domain, NTTDomain, NTTInitDomainConfig, CUDA_NTT_FAST_TWIDDLES_MODE}; - use icicle_core::vec_ops::{add_scalars, mul_scalars, sub_scalars, VecOps, VecOpsConfig}; + use icicle_core::ntt::{ + get_root_of_unity, initialize_domain, release_domain, NTTDomain, NTTInitDomainConfig, + CUDA_NTT_FAST_TWIDDLES_MODE, + }; use icicle_core::test_utilities; + use icicle_core::vec_ops::{add_scalars, mul_scalars, sub_scalars, VecOps, VecOpsConfig}; use icicle_runtime::memory::{DeviceVec, HostSlice}; use std::sync::Once; @@ -497,7 +500,7 @@ macro_rules! impl_polynomial_tests { fn randomize_poly(size: usize) -> Poly { let coeffs = randomize_coeffs::<$field>(size); - Poly::from_coeffs(HostSlice::from_slice(&coeffs), size) + Poly::from_coeffs(HostSlice::from_slice(&coeffs), size) } static INIT: Once = Once::new(); diff --git a/wrappers/rust_v3/icicle-core/src/vec_ops/mod.rs b/wrappers/rust_v3/icicle-core/src/vec_ops/mod.rs index c52df188c..fb88cb7fb 100644 --- a/wrappers/rust_v3/icicle-core/src/vec_ops/mod.rs +++ b/wrappers/rust_v3/icicle-core/src/vec_ops/mod.rs @@ -88,13 +88,13 @@ fn check_vec_ops_args<'a, F>( } // check device slices are on active device - if a.is_on_device() && !a.is_on_active_device(){ + if a.is_on_device() && !a.is_on_active_device() { panic!("input a is allocated on an inactive device"); } - if b.is_on_device() && !b.is_on_active_device(){ + if b.is_on_device() && !b.is_on_active_device() { panic!("input b is allocated on an inactive device"); } - if result.is_on_device() && !result.is_on_active_device(){ + if result.is_on_device() && !result.is_on_active_device() { panic!("output is allocated on an inactive device"); } @@ -196,7 +196,7 @@ macro_rules! impl_vec_ops_field { ) => { mod $field_prefix_ident { - use crate::vec_ops::{$field, HostOrDeviceSlice}; + use crate::vec_ops::{$field, HostOrDeviceSlice}; use icicle_core::vec_ops::VecOpsConfig; use icicle_runtime::errors::eIcicleError; diff --git a/wrappers/rust_v3/icicle-core/src/vec_ops/tests.rs b/wrappers/rust_v3/icicle-core/src/vec_ops/tests.rs index 497b0deb0..4d7333857 100644 --- a/wrappers/rust_v3/icicle-core/src/vec_ops/tests.rs +++ b/wrappers/rust_v3/icicle-core/src/vec_ops/tests.rs @@ -1,7 +1,10 @@ #![allow(unused_imports)] use crate::test_utilities; use crate::traits::GenerateRandom; -use crate::vec_ops::{add_scalars, mul_scalars, sub_scalars, bit_reverse, bit_reverse_inplace, transpose_matrix, FieldImpl, VecOps, VecOpsConfig}; +use crate::vec_ops::{ + add_scalars, bit_reverse, bit_reverse_inplace, mul_scalars, sub_scalars, transpose_matrix, FieldImpl, VecOps, + VecOpsConfig, +}; use icicle_runtime::device::Device; use icicle_runtime::memory::{DeviceVec, HostSlice}; use icicle_runtime::{runtime, stream::IcicleStream}; @@ -108,7 +111,7 @@ where ::Config: VecOps + GenerateRandom, { test_utilities::test_set_main_device(); - + const LOG_SIZE: u32 = 20; const TEST_SIZE: usize = 1 << LOG_SIZE; let input_vec = F::Config::generate_random(TEST_SIZE); diff --git a/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/ecntt/mod.rs b/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/ecntt/mod.rs index 33960a055..5fd84e76d 100644 --- a/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/ecntt/mod.rs +++ b/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/ecntt/mod.rs @@ -10,7 +10,7 @@ pub(crate) mod tests { use crate::curve::{CurveCfg, ScalarField}; use icicle_core::ecntt::tests::*; - use icicle_core::impl_ecntt_tests; + use icicle_core::impl_ecntt_tests; impl_ecntt_tests!(ScalarField, CurveCfg); } diff --git a/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/lib.rs b/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/lib.rs index 57a87671d..b33cfe396 100644 --- a/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/lib.rs +++ b/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/lib.rs @@ -2,5 +2,5 @@ pub mod curve; pub mod ecntt; pub mod msm; pub mod ntt; +pub mod polynomials; pub mod vec_ops; -pub mod polynomials; \ No newline at end of file diff --git a/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/ntt/mod.rs b/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/ntt/mod.rs index cbd6ea164..c0600d074 100644 --- a/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/ntt/mod.rs +++ b/wrappers/rust_v3/icicle-curves/icicle-bls12-377/src/ntt/mod.rs @@ -16,6 +16,6 @@ pub(crate) mod tests { use icicle_core::impl_ntt_tests; use icicle_core::ntt::tests::*; use serial_test::{parallel, serial}; - + impl_ntt_tests!(ScalarField); } diff --git a/wrappers/rust_v3/icicle-curves/icicle-bls12-381/src/ecntt/mod.rs b/wrappers/rust_v3/icicle-curves/icicle-bls12-381/src/ecntt/mod.rs index e2e9da3ba..d1a795385 100644 --- a/wrappers/rust_v3/icicle-curves/icicle-bls12-381/src/ecntt/mod.rs +++ b/wrappers/rust_v3/icicle-curves/icicle-bls12-381/src/ecntt/mod.rs @@ -10,7 +10,7 @@ pub(crate) mod tests { use crate::curve::{CurveCfg, ScalarField}; use icicle_core::ecntt::tests::*; - use icicle_core::impl_ecntt_tests; + use icicle_core::impl_ecntt_tests; impl_ecntt_tests!(ScalarField, CurveCfg); } diff --git a/wrappers/rust_v3/icicle-curves/icicle-bls12-381/src/lib.rs b/wrappers/rust_v3/icicle-curves/icicle-bls12-381/src/lib.rs index 7dbb6c46c..b33cfe396 100644 --- a/wrappers/rust_v3/icicle-curves/icicle-bls12-381/src/lib.rs +++ b/wrappers/rust_v3/icicle-curves/icicle-bls12-381/src/lib.rs @@ -2,5 +2,5 @@ pub mod curve; pub mod ecntt; pub mod msm; pub mod ntt; -pub mod vec_ops; pub mod polynomials; +pub mod vec_ops; diff --git a/wrappers/rust_v3/icicle-curves/icicle-bn254/src/ecntt/mod.rs b/wrappers/rust_v3/icicle-curves/icicle-bn254/src/ecntt/mod.rs index 66151ea07..87b371b27 100644 --- a/wrappers/rust_v3/icicle-curves/icicle-bn254/src/ecntt/mod.rs +++ b/wrappers/rust_v3/icicle-curves/icicle-bn254/src/ecntt/mod.rs @@ -10,7 +10,7 @@ pub(crate) mod tests { use crate::curve::{CurveCfg, ScalarField}; use icicle_core::ecntt::tests::*; - use icicle_core::impl_ecntt_tests; + use icicle_core::impl_ecntt_tests; impl_ecntt_tests!(ScalarField, CurveCfg); } diff --git a/wrappers/rust_v3/icicle-curves/icicle-bn254/src/lib.rs b/wrappers/rust_v3/icicle-curves/icicle-bn254/src/lib.rs index 7dbb6c46c..b33cfe396 100644 --- a/wrappers/rust_v3/icicle-curves/icicle-bn254/src/lib.rs +++ b/wrappers/rust_v3/icicle-curves/icicle-bn254/src/lib.rs @@ -2,5 +2,5 @@ pub mod curve; pub mod ecntt; pub mod msm; pub mod ntt; -pub mod vec_ops; pub mod polynomials; +pub mod vec_ops; diff --git a/wrappers/rust_v3/icicle-fields/icicle-babybear/src/lib.rs b/wrappers/rust_v3/icicle-fields/icicle-babybear/src/lib.rs index c1c2a1899..a95ac089f 100644 --- a/wrappers/rust_v3/icicle-fields/icicle-babybear/src/lib.rs +++ b/wrappers/rust_v3/icicle-fields/icicle-babybear/src/lib.rs @@ -1,4 +1,4 @@ pub mod field; pub mod ntt; -pub mod vec_ops; pub mod polynomials; +pub mod vec_ops; diff --git a/wrappers/rust_v3/icicle-fields/icicle-babybear/src/ntt/mod.rs b/wrappers/rust_v3/icicle-fields/icicle-babybear/src/ntt/mod.rs index bc4342bdf..b41bbd82c 100644 --- a/wrappers/rust_v3/icicle-fields/icicle-babybear/src/ntt/mod.rs +++ b/wrappers/rust_v3/icicle-fields/icicle-babybear/src/ntt/mod.rs @@ -23,12 +23,12 @@ pub(crate) mod tests { impl_ntt_tests!(ScalarField); // Tests against risc0 and plonky3 - use super::{ExtensionField}; + use super::ExtensionField; use icicle_core::{ - ntt::{initialize_domain, ntt_inplace, release_domain, NTTConfig, NTTInitDomainConfig, NTTDir}, - traits::{FieldImpl, GenerateRandom} + ntt::{initialize_domain, ntt_inplace, release_domain, NTTConfig, NTTDir, NTTInitDomainConfig}, + traits::{FieldImpl, GenerateRandom}, }; - use icicle_runtime::{memory::HostSlice}; + use icicle_runtime::memory::HostSlice; use risc0_core::field::{ baby_bear::{Elem, ExtElem}, Elem as FieldElem, RootsOfUnity, diff --git a/wrappers/rust_v3/icicle-fields/icicle-stark252/src/lib.rs b/wrappers/rust_v3/icicle-fields/icicle-stark252/src/lib.rs index c1c2a1899..a95ac089f 100644 --- a/wrappers/rust_v3/icicle-fields/icicle-stark252/src/lib.rs +++ b/wrappers/rust_v3/icicle-fields/icicle-stark252/src/lib.rs @@ -1,4 +1,4 @@ pub mod field; pub mod ntt; -pub mod vec_ops; pub mod polynomials; +pub mod vec_ops; diff --git a/wrappers/rust_v3/icicle-fields/icicle-stark252/src/ntt/mod.rs b/wrappers/rust_v3/icicle-fields/icicle-stark252/src/ntt/mod.rs index 46d0a3dfd..fe92b55ea 100644 --- a/wrappers/rust_v3/icicle-fields/icicle-stark252/src/ntt/mod.rs +++ b/wrappers/rust_v3/icicle-fields/icicle-stark252/src/ntt/mod.rs @@ -15,9 +15,8 @@ pub(crate) mod tests { impl_ntt_tests!(ScalarField); - use icicle_core::{ - ntt::{initialize_domain, ntt_inplace, release_domain, NTTConfig, NTTInitDomainConfig, NTTDir}, + ntt::{initialize_domain, ntt_inplace, release_domain, NTTConfig, NTTDir, NTTInitDomainConfig}, traits::{FieldImpl, GenerateRandom}, }; use icicle_runtime::memory::HostSlice; @@ -39,9 +38,13 @@ pub(crate) mod tests { release_domain::().unwrap(); // release domain from previous tests, if exists - let log_sizes = [15, 20]; + let log_sizes = [15, 20]; let lw_root_of_unity = Stark252PrimeField::get_primitive_root_of_unity(log_sizes[log_sizes.len() - 1]).unwrap(); - initialize_domain(ScalarField::from_bytes_le(&lw_root_of_unity.to_bytes_le()), &NTTInitDomainConfig::default()).unwrap(); + initialize_domain( + ScalarField::from_bytes_le(&lw_root_of_unity.to_bytes_le()), + &NTTInitDomainConfig::default(), + ) + .unwrap(); for log_size in log_sizes { let ntt_size = 1 << log_size; diff --git a/wrappers/rust_v3/icicle-runtime/src/device.rs b/wrappers/rust_v3/icicle-runtime/src/device.rs index 01a596257..9248a805b 100644 --- a/wrappers/rust_v3/icicle-runtime/src/device.rs +++ b/wrappers/rust_v3/icicle-runtime/src/device.rs @@ -76,4 +76,3 @@ impl fmt::Debug for Device { .finish() } } - diff --git a/wrappers/rust_v3/icicle-runtime/src/memory.rs b/wrappers/rust_v3/icicle-runtime/src/memory.rs index a5f699ab7..a89139ae4 100644 --- a/wrappers/rust_v3/icicle-runtime/src/memory.rs +++ b/wrappers/rust_v3/icicle-runtime/src/memory.rs @@ -55,9 +55,11 @@ impl HostOrDeviceSlice for DeviceSlice { true } - fn is_on_active_device(&self) -> bool { - runtime::is_active_device_memory(self.0.as_ptr() as *const c_void) + runtime::is_active_device_memory( + self.0 + .as_ptr() as *const c_void, + ) } unsafe fn as_ptr(&self) -> *const T { @@ -125,11 +127,11 @@ impl DeviceSlice { self.len() == val.len(), "In copy from host, destination and source slices have different lengths" ); - + if self.is_empty() { return Ok(()); } - if !self.is_on_active_device(){ + if !self.is_on_active_device() { panic!("not allocated on an inactive device"); } @@ -148,7 +150,7 @@ impl DeviceSlice { if self.is_empty() { return Ok(()); } - if !self.is_on_active_device(){ + if !self.is_on_active_device() { panic!("not allocated on an inactive device"); } @@ -166,7 +168,7 @@ impl DeviceSlice { if self.is_empty() { return Ok(()); } - if !self.is_on_active_device(){ + if !self.is_on_active_device() { panic!("not allocated on an inactive device"); } @@ -190,10 +192,10 @@ impl DeviceSlice { if self.is_empty() { return Ok(()); } - if !self.is_on_active_device(){ + if !self.is_on_active_device() { panic!("not allocated on an inactive device"); } - + let size = size_of::() * self.len(); unsafe { runtime::icicle_copy_to_host_async( diff --git a/wrappers/rust_v3/icicle-runtime/src/runtime.rs b/wrappers/rust_v3/icicle-runtime/src/runtime.rs index c5bfc9248..ea670bc72 100644 --- a/wrappers/rust_v3/icicle-runtime/src/runtime.rs +++ b/wrappers/rust_v3/icicle-runtime/src/runtime.rs @@ -61,12 +61,12 @@ pub fn get_active_device() -> Result { unsafe { icicle_get_active_device(&mut device).wrap_value::(device) } } -pub fn is_host_memory(ptr: *const c_void) -> bool{ - unsafe {eIcicleError::Success == icicle_is_host_memory(ptr)} +pub fn is_host_memory(ptr: *const c_void) -> bool { + unsafe { eIcicleError::Success == icicle_is_host_memory(ptr) } } pub fn is_active_device_memory(ptr: *const c_void) -> bool { - unsafe {eIcicleError::Success == icicle_is_active_device_memory(ptr)} + unsafe { eIcicleError::Success == icicle_is_active_device_memory(ptr) } } pub fn get_device_count() -> Result { From 88cfe1b685317eef0f508a84ba784eea8819f409 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Mon, 29 Jul 2024 07:46:49 +0000 Subject: [PATCH 25/38] ci --- .github/workflows/v3_golang.yml | 4 ++-- wrappers/golang_v3/build.sh | 13 +++++++++---- wrappers/golang_v3/curves/bls12377/main.go | 2 +- wrappers/golang_v3/curves/bls12381/main.go | 2 +- wrappers/golang_v3/curves/bn254/main.go | 2 +- wrappers/golang_v3/curves/bw6761/main.go | 2 +- wrappers/golang_v3/curves/grumpkin/main.go | 2 +- wrappers/golang_v3/fields/babybear/main.go | 2 +- .../generator/curves/templates/main.go.tmpl | 2 +- .../generator/fields/templates/main.go.tmpl | 2 +- wrappers/golang_v3/runtime/main.go | 2 +- 11 files changed, 20 insertions(+), 15 deletions(-) diff --git a/.github/workflows/v3_golang.yml b/.github/workflows/v3_golang.yml index 1a0951f0e..385b07166 100644 --- a/.github/workflows/v3_golang.yml +++ b/.github/workflows/v3_golang.yml @@ -60,7 +60,7 @@ jobs: working-directory: ./wrappers/golang_v3 if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' # builds a single curve with the curve's specified build args - run: ./build.sh -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} + run: ./build.sh -cuda_backend=main -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} - name: Test working-directory: ./wrappers/golang_v3/curves if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' @@ -89,7 +89,7 @@ jobs: working-directory: ./wrappers/golang_v3 if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' # builds a single field with the fields specified build args - run: ./build.sh -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} + run: ./build.sh -cuda_backend=main -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} - name: Test working-directory: ./wrappers/golang_v3/fields if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' diff --git a/wrappers/golang_v3/build.sh b/wrappers/golang_v3/build.sh index a89bfb351..9bd53c232 100755 --- a/wrappers/golang_v3/build.sh +++ b/wrappers/golang_v3/build.sh @@ -13,6 +13,7 @@ BUILD_HASHES=( ) SUPPORTED_CURVES=("bn254" "bls12_377" "bls12_381" "bw6_761", "grumpkin") SUPPORTED_FIELDS=("babybear") # SUPPORTED_HASHES=("keccak") +CUDA_BACKEND=OFF BUILD_DIR="${ICICLE_BUILD_DIR:-$(realpath "$PWD/../../icicle_v3/build")}" DEFAULT_BACKEND_INSTALL_DIR="${DEFAULT_BACKEND_INSTALL_DIR:="/usr/local/"}" @@ -32,7 +33,8 @@ if [[ $1 == "-help" ]]; then echo " -field= The field that should be built. If \"all\" is supplied," echo " all fields will be built with any other supplied field options" echo " -field-ext Builds the field lib with the extension field enabled" - echo " -backend Path to the folder where libraries will be installed" + echo " -install_dir Path to the folder where libraries will be installed" + echo " -cuda_backend " echo " -devmode Enables devmode debugging and fast build times" echo " -cuda_version= The version of cuda to use for compiling" echo "" @@ -47,7 +49,10 @@ do cuda_version=$(echo "$arg" | cut -d'=' -f2) CUDA_COMPILER_PATH=/usr/local/cuda-$cuda_version/bin/nvcc ;; - -backend=*) + -cuda_backend=*) + CUDA_BACKEND=$(echo "$arg_lower" | cut -d'=' -f2) + ;; + -install_dir=*) DEFAULT_BACKEND_INSTALL_DIR=$(echo "$arg_lower" | cut -d'=' -f2) ;; -ecntt) @@ -107,7 +112,7 @@ do echo "G2=${G2_DEFINED}" >> build_config.txt echo "DEVMODE=${DEVMODE}" >> build_config.txt echo "DEFAULT_BACKEND_INSTALL_DIR=${DEFAULT_BACKEND_INSTALL_DIR}" >> build_config.txt - cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCMAKE_INSTALL_PREFIX=$DEFAULT_BACKEND_INSTALL_DIR -DCURVE=$CURVE -DG2=$G2_DEFINED -DECNTT=$ECNTT_DEFINED -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build + cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCMAKE_INSTALL_PREFIX=$DEFAULT_BACKEND_INSTALL_DIR -DCUDA_BACKEND=$CUDA_BACKEND -DCURVE=$CURVE -DG2=$G2_DEFINED -DECNTT=$ECNTT_DEFINED -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build cmake --build build --target install -j8 && rm build_config.txt done @@ -120,7 +125,7 @@ do echo "FIELD=${FIELD}" > build_config.txt echo "DEVMODE=${DEVMODE}" >> build_config.txt echo "DEFAULT_BACKEND_INSTALL_DIR=${DEFAULT_BACKEND_INSTALL_DIR}" >> build_config.txt - cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCMAKE_INSTALL_PREFIX=$DEFAULT_BACKEND_INSTALL_DIR -DFIELD=$FIELD -DEXT_FIELD=$EXT_FIELD -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build + cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCMAKE_INSTALL_PREFIX=$DEFAULT_BACKEND_INSTALL_DIR -DCUDA_BACKEND=$CUDA_BACKEND -DFIELD=$FIELD -DEXT_FIELD=$EXT_FIELD -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build cmake --build build --target install -j8 && rm build_config.txt done diff --git a/wrappers/golang_v3/curves/bls12377/main.go b/wrappers/golang_v3/curves/bls12377/main.go index f41ffc1e7..e1f0ad38b 100644 --- a/wrappers/golang_v3/curves/bls12377/main.go +++ b/wrappers/golang_v3/curves/bls12377/main.go @@ -1,4 +1,4 @@ package bls12377 -// #cgo LDFLAGS: -Lusr/local/ -licicle_field_bls12_377 -licicle_curve_bls12_377 -lstdc++ -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_bls12_377 -licicle_curve_bls12_377 -lstdc++ -Wl,-rpath=usr/local/lib/ import "C" diff --git a/wrappers/golang_v3/curves/bls12381/main.go b/wrappers/golang_v3/curves/bls12381/main.go index 8f7ad0a02..f95889fb8 100644 --- a/wrappers/golang_v3/curves/bls12381/main.go +++ b/wrappers/golang_v3/curves/bls12381/main.go @@ -1,4 +1,4 @@ package bls12381 -// #cgo LDFLAGS: -Lusr/local/ -licicle_field_bls12_381 -licicle_curve_bls12_381 -lstdc++ -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_bls12_381 -licicle_curve_bls12_381 -lstdc++ -Wl,-rpath=usr/local/lib/ import "C" diff --git a/wrappers/golang_v3/curves/bn254/main.go b/wrappers/golang_v3/curves/bn254/main.go index 86a7664dc..7bf1c39f0 100644 --- a/wrappers/golang_v3/curves/bn254/main.go +++ b/wrappers/golang_v3/curves/bn254/main.go @@ -1,4 +1,4 @@ package bn254 -// #cgo LDFLAGS: -Lusr/local/ -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=usr/local/lib/ import "C" diff --git a/wrappers/golang_v3/curves/bw6761/main.go b/wrappers/golang_v3/curves/bw6761/main.go index a055689df..aea676dee 100644 --- a/wrappers/golang_v3/curves/bw6761/main.go +++ b/wrappers/golang_v3/curves/bw6761/main.go @@ -1,4 +1,4 @@ package bw6761 -// #cgo LDFLAGS: -Lusr/local/ -licicle_field_bw6_761 -licicle_curve_bw6_761 -lstdc++ -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_bw6_761 -licicle_curve_bw6_761 -lstdc++ -Wl,-rpath=usr/local/lib/ import "C" diff --git a/wrappers/golang_v3/curves/grumpkin/main.go b/wrappers/golang_v3/curves/grumpkin/main.go index edbfe8f23..3169df67b 100644 --- a/wrappers/golang_v3/curves/grumpkin/main.go +++ b/wrappers/golang_v3/curves/grumpkin/main.go @@ -1,4 +1,4 @@ package grumpkin -// #cgo LDFLAGS: -Lusr/local/ -licicle_field_grumpkin -licicle_curve_grumpkin -lstdc++ -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_grumpkin -licicle_curve_grumpkin -lstdc++ -Wl,-rpath=usr/local/lib/ import "C" diff --git a/wrappers/golang_v3/fields/babybear/main.go b/wrappers/golang_v3/fields/babybear/main.go index 892eafcee..7ac375053 100644 --- a/wrappers/golang_v3/fields/babybear/main.go +++ b/wrappers/golang_v3/fields/babybear/main.go @@ -1,4 +1,4 @@ package babybear -// #cgo LDFLAGS: -Lusr/local/ -licicle_field_babybear -lstdc++ -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_babybear -lstdc++ -Wl,-rpath=usr/local/lib/ import "C" diff --git a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl index de4b29d6a..c8bbcf907 100644 --- a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl +++ b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl @@ -1,4 +1,4 @@ package {{.PackageName}} -// #cgo LDFLAGS: -Lusr/local/ -licicle_field_{{.Field}} -licicle_curve_{{.Field}} -lstdc++ -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_{{.Field}} -licicle_curve_{{.Field}} -lstdc++ -Wl,-rpath=usr/local/lib/ import "C" diff --git a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl index f71b7aa71..17f7c0980 100644 --- a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl +++ b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl @@ -1,4 +1,4 @@ package {{.PackageName}} -// #cgo LDFLAGS: -Lusr/local/ -licicle_field_{{.Field}} -lstdc++ -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_{{.Field}} -lstdc++ -Wl,-rpath=usr/local/lib/ import "C" diff --git a/wrappers/golang_v3/runtime/main.go b/wrappers/golang_v3/runtime/main.go index c146ef740..2094cc4d1 100644 --- a/wrappers/golang_v3/runtime/main.go +++ b/wrappers/golang_v3/runtime/main.go @@ -1,4 +1,4 @@ package runtime -// #cgo LDFLAGS: -Lusr/local/ -licicle_device -lstdc++ -lm -Wl,-rpath=usr/local/ +// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_device -lstdc++ -lm -Wl,-rpath=usr/local/lib/ import "C" From 957c79d9d830f2c269d6015e20c0866b5896a9f9 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Mon, 29 Jul 2024 08:24:29 +0000 Subject: [PATCH 26/38] ci without cuda --- .github/workflows/v3_golang.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/v3_golang.yml b/.github/workflows/v3_golang.yml index 385b07166..1a0951f0e 100644 --- a/.github/workflows/v3_golang.yml +++ b/.github/workflows/v3_golang.yml @@ -60,7 +60,7 @@ jobs: working-directory: ./wrappers/golang_v3 if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' # builds a single curve with the curve's specified build args - run: ./build.sh -cuda_backend=main -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} + run: ./build.sh -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} - name: Test working-directory: ./wrappers/golang_v3/curves if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' @@ -89,7 +89,7 @@ jobs: working-directory: ./wrappers/golang_v3 if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' # builds a single field with the fields specified build args - run: ./build.sh -cuda_backend=main -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} + run: ./build.sh -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} - name: Test working-directory: ./wrappers/golang_v3/fields if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' From ce7ca31901d3f7864e0b8774bf6ccec643c2b599 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Wed, 31 Jul 2024 09:37:20 +0000 Subject: [PATCH 27/38] ci fix --- .github/workflows/v3_golang.yml | 10 +++++-- wrappers/golang_v3/curves/bls12377/main.go | 2 +- wrappers/golang_v3/curves/bls12381/main.go | 2 +- wrappers/golang_v3/curves/bn254/main.go | 2 +- wrappers/golang_v3/curves/bw6761/main.go | 2 +- wrappers/golang_v3/curves/grumpkin/main.go | 2 +- wrappers/golang_v3/fields/babybear/main.go | 2 +- .../generator/curves/templates/main.go.tmpl | 2 +- .../generator/fields/templates/main.go.tmpl | 2 +- wrappers/golang_v3/runtime/main.go | 2 +- .../golang_v3/runtime/tests/runtime_test.go | 26 ------------------- 11 files changed, 17 insertions(+), 37 deletions(-) diff --git a/.github/workflows/v3_golang.yml b/.github/workflows/v3_golang.yml index 1a0951f0e..f5d6093ac 100644 --- a/.github/workflows/v3_golang.yml +++ b/.github/workflows/v3_golang.yml @@ -60,13 +60,16 @@ jobs: working-directory: ./wrappers/golang_v3 if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' # builds a single curve with the curve's specified build args - run: ./build.sh -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} + run: | + export DEFAULT_BACKEND_INSTALL_DIR=$PWD/../../build/ + ./build.sh -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} - name: Test working-directory: ./wrappers/golang_v3/curves if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' run: | CURVE=$(echo ${{ matrix.curve.name }} | sed -e 's/_//g') export CPATH=$CPATH:/usr/local/cuda/include + export DEFAULT_BACKEND_INSTALL_DIR=$PWD/../../../build/ go test ./$CURVE/tests -count=1 -failfast -p 2 -timeout 60m -v build-fields-linux: @@ -89,13 +92,16 @@ jobs: working-directory: ./wrappers/golang_v3 if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' # builds a single field with the fields specified build args - run: ./build.sh -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} + run: | + export DEFAULT_BACKEND_INSTALL_DIR=$PWD/../../build/ + ./build.sh -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} - name: Test working-directory: ./wrappers/golang_v3/fields if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' run: | FIELD=$(echo ${{ matrix.field.name }} | sed -e 's/_//g') export CPATH=$CPATH:/usr/local/cuda/include + export DEFAULT_BACKEND_INSTALL_DIR=$PWD/../../../build/ go test ./$FIELD/tests -count=1 -failfast -p 2 -timeout 60m -v # build-hashes-linux: diff --git a/wrappers/golang_v3/curves/bls12377/main.go b/wrappers/golang_v3/curves/bls12377/main.go index e1f0ad38b..bf86376cb 100644 --- a/wrappers/golang_v3/curves/bls12377/main.go +++ b/wrappers/golang_v3/curves/bls12377/main.go @@ -1,4 +1,4 @@ package bls12377 -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_bls12_377 -licicle_curve_bls12_377 -lstdc++ -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../../build/lib -licicle_field_bls12_377 -licicle_curve_bls12_377 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../build/lib import "C" diff --git a/wrappers/golang_v3/curves/bls12381/main.go b/wrappers/golang_v3/curves/bls12381/main.go index f95889fb8..81ca46886 100644 --- a/wrappers/golang_v3/curves/bls12381/main.go +++ b/wrappers/golang_v3/curves/bls12381/main.go @@ -1,4 +1,4 @@ package bls12381 -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_bls12_381 -licicle_curve_bls12_381 -lstdc++ -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../../build/lib -licicle_field_bls12_381 -licicle_curve_bls12_381 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../build/lib import "C" diff --git a/wrappers/golang_v3/curves/bn254/main.go b/wrappers/golang_v3/curves/bn254/main.go index 7bf1c39f0..6b381a42e 100644 --- a/wrappers/golang_v3/curves/bn254/main.go +++ b/wrappers/golang_v3/curves/bn254/main.go @@ -1,4 +1,4 @@ package bn254 -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../../build/lib -licicle_field_bn254 -licicle_curve_bn254 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../build/lib import "C" diff --git a/wrappers/golang_v3/curves/bw6761/main.go b/wrappers/golang_v3/curves/bw6761/main.go index aea676dee..70daf3898 100644 --- a/wrappers/golang_v3/curves/bw6761/main.go +++ b/wrappers/golang_v3/curves/bw6761/main.go @@ -1,4 +1,4 @@ package bw6761 -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_bw6_761 -licicle_curve_bw6_761 -lstdc++ -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../../build/lib -licicle_field_bw6_761 -licicle_curve_bw6_761 -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../build/lib import "C" diff --git a/wrappers/golang_v3/curves/grumpkin/main.go b/wrappers/golang_v3/curves/grumpkin/main.go index 3169df67b..2282e7210 100644 --- a/wrappers/golang_v3/curves/grumpkin/main.go +++ b/wrappers/golang_v3/curves/grumpkin/main.go @@ -1,4 +1,4 @@ package grumpkin -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_grumpkin -licicle_curve_grumpkin -lstdc++ -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../../build/lib -licicle_field_grumpkin -licicle_curve_grumpkin -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../build/lib import "C" diff --git a/wrappers/golang_v3/fields/babybear/main.go b/wrappers/golang_v3/fields/babybear/main.go index 7ac375053..e2fd712f1 100644 --- a/wrappers/golang_v3/fields/babybear/main.go +++ b/wrappers/golang_v3/fields/babybear/main.go @@ -1,4 +1,4 @@ package babybear -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_babybear -lstdc++ -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../../build/lib -licicle_field_babybear -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../build/lib import "C" diff --git a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl index c8bbcf907..e8b9104c7 100644 --- a/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl +++ b/wrappers/golang_v3/internal/generator/curves/templates/main.go.tmpl @@ -1,4 +1,4 @@ package {{.PackageName}} -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_{{.Field}} -licicle_curve_{{.Field}} -lstdc++ -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../../build/lib -licicle_field_{{.Field}} -licicle_curve_{{.Field}} -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../build/lib import "C" diff --git a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl index 17f7c0980..2b4e9d934 100644 --- a/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl +++ b/wrappers/golang_v3/internal/generator/fields/templates/main.go.tmpl @@ -1,4 +1,4 @@ package {{.PackageName}} -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_field_{{.Field}} -lstdc++ -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../../build/lib -licicle_field_{{.Field}} -lstdc++ -Wl,-rpath=${SRCDIR}/../../../../build/lib import "C" diff --git a/wrappers/golang_v3/runtime/main.go b/wrappers/golang_v3/runtime/main.go index 2094cc4d1..abcbb2e6d 100644 --- a/wrappers/golang_v3/runtime/main.go +++ b/wrappers/golang_v3/runtime/main.go @@ -1,4 +1,4 @@ package runtime -// #cgo LDFLAGS: -Lusr/local/lib/ -licicle_device -lstdc++ -lm -Wl,-rpath=usr/local/lib/ +// #cgo LDFLAGS: -L${SRCDIR}/../../../build/lib -licicle_device -lstdc++ -lm -Wl,-rpath=${SRCDIR}/../../../build/lib import "C" diff --git a/wrappers/golang_v3/runtime/tests/runtime_test.go b/wrappers/golang_v3/runtime/tests/runtime_test.go index 5925f0da5..be272f180 100644 --- a/wrappers/golang_v3/runtime/tests/runtime_test.go +++ b/wrappers/golang_v3/runtime/tests/runtime_test.go @@ -56,29 +56,3 @@ func TestActiveDevice(t *testing.T) { assert.Greater(t, memory1.Total, uint(0)) assert.Greater(t, memory1.Free, uint(0)) } - -// func TestDestroyStream(t *testing.T) { -// stream, err := runtime.CreateStream() -// assert.Equal(t, runtime.Success, err, "Unable to create stream due to %d", err) - -// err = runtime.DestroyStream(stream) -// assert.Equal(t, runtime.Success, err, "Unable to destroy stream due to %d", err) -// } - -// func TestSyncStream(t *testing.T) { -// stream, err := runtime.CreateStream() -// assert.Equal(t, runtime.Success, err, "Unable to create stream due to %d", err) - -// _, err = MallocAsync(200000, stream) -// assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) - -// dp, err := Malloc(20) -// assert.NotNil(t, dp) -// assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) - -// err = SynchronizeStream(&stream) -// assert.Equal(t, CudaSuccess, err, "Unable to sync stream due to %d", err) - -// err = DestroyStream(&stream) -// assert.Equal(t, CudaSuccess, err, "Unable to destroy stream due to %d", err) -// } From 7da5d7675eca511563862603e2f0d2c9ea61d0e8 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Wed, 31 Jul 2024 09:45:24 +0000 Subject: [PATCH 28/38] clang-format --- icicle_v3/backend/cpu/src/curve/cpu_msm.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/icicle_v3/backend/cpu/src/curve/cpu_msm.cpp b/icicle_v3/backend/cpu/src/curve/cpu_msm.cpp index d8fb2c2df..be0a4b6e9 100644 --- a/icicle_v3/backend/cpu/src/curve/cpu_msm.cpp +++ b/icicle_v3/backend/cpu/src/curve/cpu_msm.cpp @@ -18,7 +18,9 @@ cpu_msm(const Device& device, const S* scalars, const A* bases, int msm_size, co const S* batch_scalars = scalars + msm_size * batch_idx; const A* batch_bases = config.are_bases_shared ? bases : bases + msm_size * batch_idx; for (auto i = 0; i < msm_size; ++i) { - res = res + P::from_affine(config.are_points_montgomery_form ? A::from_montgomery(batch_bases[i]) : batch_bases[i]) * (config.are_scalars_montgomery_form ? S::from_montgomery(batch_scalars[i]) : batch_scalars[i]); + res = + res + P::from_affine(config.are_points_montgomery_form ? A::from_montgomery(batch_bases[i]) : batch_bases[i]) * + (config.are_scalars_montgomery_form ? S::from_montgomery(batch_scalars[i]) : batch_scalars[i]); } results[batch_idx] = res; } From 3c9a0ea530ed244477fb2a2eb297b67344fe8c93 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Wed, 31 Jul 2024 09:49:30 +0000 Subject: [PATCH 29/38] cuda backend pull attempt --- .github/workflows/v3_golang.yml | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/.github/workflows/v3_golang.yml b/.github/workflows/v3_golang.yml index f5d6093ac..9607f9c99 100644 --- a/.github/workflows/v3_golang.yml +++ b/.github/workflows/v3_golang.yml @@ -32,10 +32,32 @@ jobs: if: needs.check-changed-files.outputs.golang == 'true' run: if [[ $(go list ./... | xargs go fmt) ]]; then echo "Please run go fmt"; exit 1; fi + extract-cuda-backend-branch: + name: Extract cuda branch name + runs-on: ubuntu-22.04 + outputs: + cuda-backend-branch: ${{ steps.extract.outputs.cuda-backend-branch }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Extract Private Branch from PR Description + id: extract + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + DESCRIPTION=$(gh pr view ${{ github.event.pull_request.number }} --json body -q '.body') + echo "PR Description: $DESCRIPTION" + CUDA_BE_BRANCH=$(echo "$DESCRIPTION" | grep -oP 'cuda-backend-branch:\s*\K[^\s]+') || true + if [ -z "$CUDA_BE_BRANCH" ]; then + CUDA_BE_BRANCH="main" # Default branch if not specified + fi + echo "Extracted CUDA Backend Branch: $CUDA_BE_BRANCH" + echo "::set-output name=cuda-backend-branch::$CUDA_BE_BRANCH" + build-curves-linux: name: Build and test curves on Linux runs-on: [self-hosted, Linux, X64, icicle] - needs: [check-changed-files, check-format] + needs: [check-changed-files, check-format, extract-cuda-backend-branch] strategy: matrix: curve: @@ -62,7 +84,7 @@ jobs: # builds a single curve with the curve's specified build args run: | export DEFAULT_BACKEND_INSTALL_DIR=$PWD/../../build/ - ./build.sh -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} + ./build.sh -curve=${{ matrix.curve.name }} ${{ matrix.curve.build_args }} -cuda_backend=local - name: Test working-directory: ./wrappers/golang_v3/curves if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' @@ -75,7 +97,7 @@ jobs: build-fields-linux: name: Build and test fields on Linux runs-on: [self-hosted, Linux, X64, icicle] - needs: [check-changed-files, check-format] + needs: [check-changed-files, check-format, extract-cuda-backend-branch] strategy: matrix: field: @@ -94,7 +116,7 @@ jobs: # builds a single field with the fields specified build args run: | export DEFAULT_BACKEND_INSTALL_DIR=$PWD/../../build/ - ./build.sh -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} + ./build.sh -field=${{ matrix.field.name }} ${{ matrix.field.build_args }} -cuda_backend=local - name: Test working-directory: ./wrappers/golang_v3/fields if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' From 454dbd0515aea48f56c698d67ee67d698a54d6bd Mon Sep 17 00:00:00 2001 From: nonam3e Date: Wed, 31 Jul 2024 16:20:06 +0000 Subject: [PATCH 30/38] ci cuda checkout step --- .github/workflows/v3_golang.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/v3_golang.yml b/.github/workflows/v3_golang.yml index 9607f9c99..d1f7b7aae 100644 --- a/.github/workflows/v3_golang.yml +++ b/.github/workflows/v3_golang.yml @@ -74,6 +74,14 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@v4 + - name: Checkout CUDA Backend + uses: actions/checkout@v4 + with: + repository: ingonyama-zk/icicle-cuda-backend + path: ./icicle_v3/backend/cuda + token: ${{ secrets.GITHUB_TOKEN }} + ssh-key: ${{ secrets.CUDA_PULL_KEY }} + ref: ${{ needs.extract-branch.outputs.cuda-backend-branch }} - name: Setup go uses: actions/setup-go@v5 with: @@ -106,6 +114,14 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@v4 + - name: Checkout CUDA Backend + uses: actions/checkout@v4 + with: + repository: ingonyama-zk/icicle-cuda-backend + path: ./icicle_v3/backend/cuda + token: ${{ secrets.GITHUB_TOKEN }} + ssh-key: ${{ secrets.CUDA_PULL_KEY }} + ref: ${{ needs.extract-branch.outputs.cuda-backend-branch }} - name: Setup go uses: actions/setup-go@v5 with: From a73c150623c9bff37e30e611e68bd3a2adcbc462 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Thu, 1 Aug 2024 05:54:02 +0000 Subject: [PATCH 31/38] smaller batch size --- wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go | 8 ++++---- wrappers/golang_v3/curves/bls12377/tests/msm_test.go | 8 ++++---- wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go | 8 ++++---- wrappers/golang_v3/curves/bls12381/tests/msm_test.go | 8 ++++---- wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go | 8 ++++---- wrappers/golang_v3/curves/bn254/tests/msm_test.go | 8 ++++---- wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go | 8 ++++---- wrappers/golang_v3/curves/bw6761/tests/msm_test.go | 8 ++++---- wrappers/golang_v3/curves/grumpkin/tests/msm_test.go | 8 ++++---- .../internal/generator/msm/templates/msm_test.go.tmpl | 8 ++++---- 10 files changed, 40 insertions(+), 40 deletions(-) diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go index 644834221..4438e5e82 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go @@ -238,7 +238,7 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -272,7 +272,7 @@ func TestPrecomputePointsG2(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -317,7 +317,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -356,7 +356,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go index 91cde4e80..0ff57e333 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go @@ -198,7 +198,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -232,7 +232,7 @@ func TestPrecomputePoints(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -277,7 +277,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go index ac862a4a5..3333bdc7d 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go @@ -238,7 +238,7 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -272,7 +272,7 @@ func TestPrecomputePointsG2(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -317,7 +317,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -356,7 +356,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go index 57199c943..2d60f11c8 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go @@ -198,7 +198,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -232,7 +232,7 @@ func TestPrecomputePoints(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -277,7 +277,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go index d4a49120a..edd22c791 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go @@ -238,7 +238,7 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -272,7 +272,7 @@ func TestPrecomputePointsG2(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -317,7 +317,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -356,7 +356,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index 9b25f7782..148bf7b46 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -198,7 +198,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -232,7 +232,7 @@ func TestPrecomputePoints(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -277,7 +277,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go index aadf3daaf..14e2938e4 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go @@ -198,7 +198,7 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -232,7 +232,7 @@ func TestPrecomputePointsG2(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -277,7 +277,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go index 4fd4499ed..d87ae64d0 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go @@ -198,7 +198,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -232,7 +232,7 @@ func TestPrecomputePoints(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -277,7 +277,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go index ad3fa9aba..1af754a4b 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go @@ -93,7 +93,7 @@ func TestMSM(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -121,7 +121,7 @@ func TestPrecomputePoints(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -160,7 +160,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -193,7 +193,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl index d2b4756b4..fae2dca92 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl @@ -280,7 +280,7 @@ func TestMSM{{if eq .CurvePrefix "G2"}}G2{{end}}GnarkCryptoTypes(t *testing.T) { func TestMSM{{.CurvePrefix}}Batch(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power totalSize := size * batchSize @@ -315,7 +315,7 @@ func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -361,7 +361,7 @@ func TestPrecomputePointsSharedBases{{.CurvePrefix}}(t *testing.T) { cfg.PrecomputeFactor = precomputeFactor for _, power := range []int{10, 16} { - for _, batchSize := range []int{1, 3, 16} { + for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -401,7 +401,7 @@ func TestPrecomputePointsSharedBases{{.CurvePrefix}}(t *testing.T) { func TestMSM{{.CurvePrefix}}SkewedDistribution(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { runtime.SetDevice(&DEVICE) size := 1 << power From 3a5c2d9e4288c0a3869039944a4b5d31a9ade31e Mon Sep 17 00:00:00 2001 From: nonam3e Date: Thu, 1 Aug 2024 10:24:52 +0000 Subject: [PATCH 32/38] tests --- .../golang_v3/curves/bls12377/tests/g2_msm_test.go | 10 +++++----- wrappers/golang_v3/curves/bls12377/tests/msm_test.go | 10 +++++----- wrappers/golang_v3/curves/bls12377/tests/ntt_test.go | 4 ++-- .../golang_v3/curves/bls12381/tests/g2_msm_test.go | 10 +++++----- wrappers/golang_v3/curves/bls12381/tests/msm_test.go | 10 +++++----- wrappers/golang_v3/curves/bls12381/tests/ntt_test.go | 4 ++-- wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go | 10 +++++----- wrappers/golang_v3/curves/bn254/tests/msm_test.go | 10 +++++----- wrappers/golang_v3/curves/bn254/tests/ntt_test.go | 4 ++-- wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go | 10 +++++----- wrappers/golang_v3/curves/bw6761/tests/msm_test.go | 10 +++++----- wrappers/golang_v3/curves/bw6761/tests/ntt_test.go | 4 ++-- wrappers/golang_v3/curves/grumpkin/tests/msm_test.go | 10 +++++----- wrappers/golang_v3/fields/babybear/tests/ntt_test.go | 4 ++-- .../internal/generator/msm/templates/msm_test.go.tmpl | 10 +++++----- .../internal/generator/ntt/templates/ntt_test.go.tmpl | 4 ++-- 16 files changed, 62 insertions(+), 62 deletions(-) diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go index 4438e5e82..c6c2109c2 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go @@ -237,7 +237,7 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -271,7 +271,7 @@ func TestPrecomputePointsG2(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -356,7 +356,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -400,7 +400,7 @@ func TestMSMG2MultiDevice(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleBls12_377.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go index 0ff57e333..6036cb18a 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go @@ -197,7 +197,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -231,7 +231,7 @@ func TestPrecomputePoints(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -276,7 +276,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -360,7 +360,7 @@ func TestMSMMultiDevice(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleBls12_377.GenerateScalars(size) points := icicleBls12_377.GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go b/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go index 34b0a4de5..ef5ce0b1b 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/ntt_test.go @@ -157,8 +157,8 @@ func TestNttDeviceAsync(t *testing.T) { func TestNttBatch(t *testing.T) { cfg := ntt.GetDefaultNttConfig() - largestTestSize := 12 - largestBatchSize := 100 + largestTestSize := 10 + largestBatchSize := 20 scalars := bls12_377.GenerateScalars(1 << largestTestSize * largestBatchSize) for _, size := range []int{4, largestTestSize} { diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go index 3333bdc7d..cd9881bd7 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go @@ -237,7 +237,7 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -271,7 +271,7 @@ func TestPrecomputePointsG2(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -356,7 +356,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -400,7 +400,7 @@ func TestMSMG2MultiDevice(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleBls12_381.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go index 2d60f11c8..673926870 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go @@ -197,7 +197,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -231,7 +231,7 @@ func TestPrecomputePoints(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -276,7 +276,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -360,7 +360,7 @@ func TestMSMMultiDevice(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleBls12_381.GenerateScalars(size) points := icicleBls12_381.GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go b/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go index b43d7445d..a3dc3cf57 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/ntt_test.go @@ -157,8 +157,8 @@ func TestNttDeviceAsync(t *testing.T) { func TestNttBatch(t *testing.T) { cfg := ntt.GetDefaultNttConfig() - largestTestSize := 12 - largestBatchSize := 100 + largestTestSize := 10 + largestBatchSize := 20 scalars := bls12_381.GenerateScalars(1 << largestTestSize * largestBatchSize) for _, size := range []int{4, largestTestSize} { diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go index edd22c791..62f867ff3 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go @@ -237,7 +237,7 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -271,7 +271,7 @@ func TestPrecomputePointsG2(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -356,7 +356,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -400,7 +400,7 @@ func TestMSMG2MultiDevice(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleBn254.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index 148bf7b46..71d2173af 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -197,7 +197,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -231,7 +231,7 @@ func TestPrecomputePoints(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -276,7 +276,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -360,7 +360,7 @@ func TestMSMMultiDevice(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleBn254.GenerateScalars(size) points := icicleBn254.GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go index 78ff69641..29ff29c24 100644 --- a/wrappers/golang_v3/curves/bn254/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/ntt_test.go @@ -157,8 +157,8 @@ func TestNttDeviceAsync(t *testing.T) { func TestNttBatch(t *testing.T) { cfg := ntt.GetDefaultNttConfig() - largestTestSize := 12 - largestBatchSize := 100 + largestTestSize := 10 + largestBatchSize := 20 scalars := bn254.GenerateScalars(1 << largestTestSize * largestBatchSize) for _, size := range []int{4, largestTestSize} { diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go index 14e2938e4..328e3415d 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go @@ -197,7 +197,7 @@ func TestMSMG2GnarkCryptoTypes(t *testing.T) { func TestMSMG2Batch(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -231,7 +231,7 @@ func TestPrecomputePointsG2(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -276,7 +276,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBasesG2(t *testing.T) { func TestMSMG2SkewedDistribution(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -360,7 +360,7 @@ func TestMSMG2MultiDevice(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleBw6_761.GenerateScalars(size) points := g2.G2GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go index d87ae64d0..3de02922c 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go @@ -197,7 +197,7 @@ func TestMSMGnarkCryptoTypes(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -231,7 +231,7 @@ func TestPrecomputePoints(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -276,7 +276,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -316,7 +316,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -360,7 +360,7 @@ func TestMSMMultiDevice(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleBw6_761.GenerateScalars(size) points := icicleBw6_761.GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go b/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go index e90f32c33..122cb3ff1 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/ntt_test.go @@ -157,8 +157,8 @@ func TestNttDeviceAsync(t *testing.T) { func TestNttBatch(t *testing.T) { cfg := ntt.GetDefaultNttConfig() - largestTestSize := 12 - largestBatchSize := 100 + largestTestSize := 10 + largestBatchSize := 20 scalars := bw6_761.GenerateScalars(1 << largestTestSize * largestBatchSize) for _, size := range []int{4, largestTestSize} { diff --git a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go index 1af754a4b..81ab9cc05 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go @@ -92,7 +92,7 @@ func TestMSM(t *testing.T) { func TestMSMBatch(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -120,7 +120,7 @@ func TestPrecomputePoints(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -159,7 +159,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -193,7 +193,7 @@ func TestPrecomputePointsSharedBases(t *testing.T) { func TestMSMSkewedDistribution(t *testing.T) { cfg := msm.GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -236,7 +236,7 @@ func TestMSMMultiDevice(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicleGrumpkin.GenerateScalars(size) points := icicleGrumpkin.GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/fields/babybear/tests/ntt_test.go b/wrappers/golang_v3/fields/babybear/tests/ntt_test.go index d17c6b618..c4be50beb 100644 --- a/wrappers/golang_v3/fields/babybear/tests/ntt_test.go +++ b/wrappers/golang_v3/fields/babybear/tests/ntt_test.go @@ -84,8 +84,8 @@ func TestNttDeviceAsync(t *testing.T) { func TestNttBatch(t *testing.T) { cfg := ntt.GetDefaultNttConfig() - largestTestSize := 12 - largestBatchSize := 100 + largestTestSize := 10 + largestBatchSize := 20 scalars := babybear.GenerateScalars(1 << largestTestSize * largestBatchSize) for _, size := range []int{4, largestTestSize} { diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl index fae2dca92..7d0f877d1 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl @@ -279,7 +279,7 @@ func TestMSM{{if eq .CurvePrefix "G2"}}G2{{end}}GnarkCryptoTypes(t *testing.T) { {{end}} func TestMSM{{.CurvePrefix}}Batch(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() - for _, power := range []int{10, 16} { + for _, power := range []int{5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -314,7 +314,7 @@ func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{7, 8} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -360,7 +360,7 @@ func TestPrecomputePointsSharedBases{{.CurvePrefix}}(t *testing.T) { const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor - for _, power := range []int{10, 16} { + for _, power := range []int{4, 5, 6} { for _, batchSize := range []int{1, 3, 5} { runtime.SetDevice(&DEVICE) @@ -401,7 +401,7 @@ func TestPrecomputePointsSharedBases{{.CurvePrefix}}(t *testing.T) { func TestMSM{{.CurvePrefix}}SkewedDistribution(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10} { + for _, power := range []int{2, 3, 4, 5} { runtime.SetDevice(&DEVICE) size := 1 << power @@ -446,7 +446,7 @@ func TestMSM{{.CurvePrefix}}MultiDevice(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { size := 1 << power scalars := icicle{{capitalize .Curve}}.GenerateScalars(size) points := {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}GenerateAffinePoints(size) diff --git a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl index 14a2d4229..d076c335c 100644 --- a/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/ntt/templates/ntt_test.go.tmpl @@ -169,8 +169,8 @@ func TestNttDeviceAsync(t *testing.T) { func TestNttBatch(t *testing.T) { cfg := ntt.GetDefaultNttConfig() - largestTestSize := 12 - largestBatchSize := 100 + largestTestSize := 10 + largestBatchSize := 20 scalars := {{.Field}}.GenerateScalars(1 << largestTestSize * largestBatchSize) for _, size := range []int{4, largestTestSize} { From 9854bb229973d8c78f4906c41d641554f8c0dd5b Mon Sep 17 00:00:00 2001 From: nonam3e Date: Thu, 1 Aug 2024 14:23:01 +0000 Subject: [PATCH 33/38] tests --- wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go | 2 +- wrappers/golang_v3/curves/bls12377/tests/msm_test.go | 2 +- wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go | 2 +- wrappers/golang_v3/curves/bls12381/tests/msm_test.go | 2 +- wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go | 2 +- wrappers/golang_v3/curves/bn254/tests/msm_test.go | 2 +- wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go | 2 +- wrappers/golang_v3/curves/bw6761/tests/msm_test.go | 2 +- wrappers/golang_v3/curves/grumpkin/tests/msm_test.go | 2 +- .../golang_v3/internal/generator/msm/templates/msm_test.go.tmpl | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go index c6c2109c2..057589ca8 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go @@ -122,7 +122,7 @@ func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bls12377.G2Af func TestMSMG2(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go index 6036cb18a..2690a1d53 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go @@ -82,7 +82,7 @@ func convertIcicleAffineToG1Affine(iciclePoints []icicleBls12_377.Affine) []bls1 func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go index cd9881bd7..939314a52 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go @@ -122,7 +122,7 @@ func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bls12381.G2Af func TestMSMG2(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go index 673926870..41cea14ee 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go @@ -82,7 +82,7 @@ func convertIcicleAffineToG1Affine(iciclePoints []icicleBls12_381.Affine) []bls1 func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go index 62f867ff3..bb386703d 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go @@ -122,7 +122,7 @@ func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bn254.G2Affin func TestMSMG2(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index 71d2173af..b67b11a30 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -82,7 +82,7 @@ func convertIcicleAffineToG1Affine(iciclePoints []icicleBn254.Affine) []bn254.G1 func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go index 328e3415d..e5fb7c001 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go @@ -82,7 +82,7 @@ func convertIcicleAffineToG2Affine(iciclePoints []g2.G2Affine) []bw6761.G2Affine func TestMSMG2(t *testing.T) { cfg := g2.G2GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go index 3de02922c..51b9eb116 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go @@ -82,7 +82,7 @@ func convertIcicleAffineToG1Affine(iciclePoints []icicleBw6_761.Affine) []bw6761 func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go index 81ab9cc05..a8c326ae5 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go @@ -16,7 +16,7 @@ import ( func TestMSM(t *testing.T) { cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl index 7d0f877d1..fae1a6bfc 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl @@ -160,7 +160,7 @@ func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []{{toPackage . func TestMSM{{.CurvePrefix}}(t *testing.T) { cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() cfg.IsAsync = true - for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + for _, power := range []int{2, 3, 4, 5, 6} { runtime.SetDevice(&DEVICE) size := 1 << power From 47bf7c6f2950beed6b123a2b2326c484fda8c6b7 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Mon, 19 Aug 2024 09:41:45 +0000 Subject: [PATCH 34/38] update poseidon.md --- docs/docs/icicle/primitives/poseidon.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/docs/icicle/primitives/poseidon.md b/docs/docs/icicle/primitives/poseidon.md index 50963d367..61e0f82a2 100644 --- a/docs/docs/icicle/primitives/poseidon.md +++ b/docs/docs/icicle/primitives/poseidon.md @@ -2,8 +2,6 @@ TODO update for V3 -TODO update for V3 - [Poseidon](https://eprint.iacr.org/2019/458.pdf) is a popular hash in the ZK ecosystem primarily because its optimized to work over large prime fields, a common setting for ZK proofs, thereby minimizing the number of multiplicative operations required. Poseidon has also been specifically designed to be efficient when implemented within ZK circuits, Poseidon uses far less constraints compared to other hash functions like Keccak or SHA-256 in the context of ZK circuits. @@ -46,7 +44,7 @@ To generate a secure hash output, the algorithm goes through a series of "full r **Linear Transformation and Round Constants:** A linear transformation is performed and round constants are added. The linear transformation in partial rounds can be designed to be less computationally intensive (this is done by using a sparse matrix) than in full rounds, further optimizing the function's efficiency. -The user of Poseidon can often choose how many partial or full rounds he wishes to apply; more full rounds will increase security but degrade performance. The choice and balance are highly dependent on the use case. +The user of Poseidon can often choose how many partial or full rounds he wishes to apply; more full rounds will increase security but degrade performance. The choice and balance is highly dependent on the use case. ## Using Poseidon @@ -64,7 +62,7 @@ So for Poseidon of arity 2 and input of size 1024 * 2, we would expect 1024 elem Poseidon is extremely customizable and using different constants will produce different hashes, security levels and performance results. -We support pre-calculated and optimized constants for each of the [supported curves](../core#supported-curves-and-operations). The constants can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants) and are labeled clearly per curve `_poseidon.h`. +We support pre-calculated and optimized constants for each of the [supported curves](../core#supported-curves-and-operations).The constants can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants) and are labeled clearly per curve `_poseidon.h`. If you wish to generate your own constants you can use our python script which can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/icicle/include/poseidon/constants/generate_parameters.py). @@ -139,7 +137,7 @@ impl<'a> Default for HashConfig<'a> { } ``` -In the example above `Poseidon::load(arity, &ctx).unwrap();` is used which will load the correct constants based on arity and curve. It's possible to [generate](#constants) your own constants and load them. +In the example above `Poseidon::load(arity, &ctx).unwrap();` is used which will load the correct constants based on arity and curve. Its possible to [generate](#constants) your own constants and load them. ```rust let ctx = get_default_device_context(); @@ -217,4 +215,4 @@ The benchmarks include copying data from and to the device. | ----------- | ----------- | ----------- | 10 | 9.4 seconds | 13.6 seconds | 20 | 9.5 seconds | 13.6 seconds -| 29 | 13.7 seconds | 13.6 seconds +| 29 | 13.7 seconds | 13.6 seconds \ No newline at end of file From 2f59425b05d35832c76bd592e6594f0d0d5004ea Mon Sep 17 00:00:00 2001 From: nonam3e Date: Mon, 19 Aug 2024 14:20:29 +0000 Subject: [PATCH 35/38] skip cpu precompute test --- wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go | 3 +++ wrappers/golang_v3/curves/bls12377/tests/msm_test.go | 3 +++ wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go | 3 +++ wrappers/golang_v3/curves/bls12381/tests/msm_test.go | 3 +++ wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go | 3 +++ wrappers/golang_v3/curves/bn254/tests/msm_test.go | 3 +++ wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go | 3 +++ wrappers/golang_v3/curves/bw6761/tests/msm_test.go | 3 +++ wrappers/golang_v3/curves/grumpkin/tests/msm_test.go | 3 +++ .../internal/generator/msm/templates/msm_test.go.tmpl | 3 +++ 10 files changed, 30 insertions(+) diff --git a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go index 057589ca8..cd036d2f2 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/g2_msm_test.go @@ -267,6 +267,9 @@ func TestMSMG2Batch(t *testing.T) { } func TestPrecomputePointsG2(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := g2.G2GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go index 2690a1d53..bab33b04d 100644 --- a/wrappers/golang_v3/curves/bls12377/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12377/tests/msm_test.go @@ -227,6 +227,9 @@ func TestMSMBatch(t *testing.T) { } func TestPrecomputePoints(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := msm.GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go index 939314a52..d8bf14750 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/g2_msm_test.go @@ -267,6 +267,9 @@ func TestMSMG2Batch(t *testing.T) { } func TestPrecomputePointsG2(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := g2.G2GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go index 41cea14ee..c1520e315 100644 --- a/wrappers/golang_v3/curves/bls12381/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bls12381/tests/msm_test.go @@ -227,6 +227,9 @@ func TestMSMBatch(t *testing.T) { } func TestPrecomputePoints(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := msm.GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go index bb386703d..aa4625770 100644 --- a/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/g2_msm_test.go @@ -267,6 +267,9 @@ func TestMSMG2Batch(t *testing.T) { } func TestPrecomputePointsG2(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := g2.G2GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/curves/bn254/tests/msm_test.go b/wrappers/golang_v3/curves/bn254/tests/msm_test.go index b67b11a30..9c1520b03 100644 --- a/wrappers/golang_v3/curves/bn254/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bn254/tests/msm_test.go @@ -227,6 +227,9 @@ func TestMSMBatch(t *testing.T) { } func TestPrecomputePoints(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := msm.GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go index e5fb7c001..0c1fa0623 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/g2_msm_test.go @@ -227,6 +227,9 @@ func TestMSMG2Batch(t *testing.T) { } func TestPrecomputePointsG2(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := g2.G2GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go index 51b9eb116..4ef230b42 100644 --- a/wrappers/golang_v3/curves/bw6761/tests/msm_test.go +++ b/wrappers/golang_v3/curves/bw6761/tests/msm_test.go @@ -227,6 +227,9 @@ func TestMSMBatch(t *testing.T) { } func TestPrecomputePoints(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := msm.GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go index a8c326ae5..d594c539b 100644 --- a/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go +++ b/wrappers/golang_v3/curves/grumpkin/tests/msm_test.go @@ -116,6 +116,9 @@ func TestMSMBatch(t *testing.T) { } func TestPrecomputePoints(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := msm.GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor diff --git a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl index fae1a6bfc..06d5cf25c 100644 --- a/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl +++ b/wrappers/golang_v3/internal/generator/msm/templates/msm_test.go.tmpl @@ -310,6 +310,9 @@ func TestMSM{{.CurvePrefix}}Batch(t *testing.T) { } func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) { + if DEVICE.GetDeviceType() == "CPU" { + t.Skip("Skipping cpu test") + } cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig() const precomputeFactor = 8 cfg.PrecomputeFactor = precomputeFactor From 9b00697b80414f00c4525fa1331500a50cc72010 Mon Sep 17 00:00:00 2001 From: nonam3e Date: Mon, 19 Aug 2024 14:26:52 +0000 Subject: [PATCH 36/38] fix typos --- docs/docs/icicle/benchmarks.md | 4 ++-- docs/docs/icicle/primitives/ntt.md | 4 ++-- docs/docs/icicle/programmers_guide/rust.md | 2 +- docs/docs/icicle/rust-bindings.md | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/docs/icicle/benchmarks.md b/docs/docs/icicle/benchmarks.md index b4cabc167..8960643a0 100644 --- a/docs/docs/icicle/benchmarks.md +++ b/docs/docs/icicle/benchmarks.md @@ -1,3 +1,3 @@ -# Benchamrks +# Benchmarks -TODO explain which benchamrks exist, how to run them for a given device \ No newline at end of file +TODO explain which benchmarks exist, how to run them for a given device \ No newline at end of file diff --git a/docs/docs/icicle/primitives/ntt.md b/docs/docs/icicle/primitives/ntt.md index ce618c158..b567d4ea9 100644 --- a/docs/docs/icicle/primitives/ntt.md +++ b/docs/docs/icicle/primitives/ntt.md @@ -56,7 +56,7 @@ enum class Ordering { ### `NTTConfig` Struct -The `NTTConfig` struct configures teh NTT operation. It allows customization of parameters like the batch size, column batch computation, order of inputs and outputs etc. +The `NTTConfig` struct configures the NTT operation. It allows customization of parameters like the batch size, column batch computation, order of inputs and outputs etc. ```cpp template @@ -107,7 +107,7 @@ template eIcicleError ntt_init_domain(const S& primitive_root, const NTTInitDomainConfig& config); ``` -To retrive a root of unity from the domain or release it: +To retrieve a root of unity from the domain or release it: ```cpp template eIcicleError ntt_release_domain(); template S get_root_of_unity(uint64_t max_size); diff --git a/docs/docs/icicle/programmers_guide/rust.md b/docs/docs/icicle/programmers_guide/rust.md index 63504ee59..4c0c0a9db 100644 --- a/docs/docs/icicle/programmers_guide/rust.md +++ b/docs/docs/icicle/programmers_guide/rust.md @@ -66,7 +66,7 @@ Asynchronous memory operations can be performed using streams. This allows for n use icicle_runtime::stream::IcicleStream; use icicle_runtime::memory::DeviceVec; -let mut stream = IcicleStream::create().unwrap(); // mutability is for the destory() method +let mut stream = IcicleStream::create().unwrap(); // mutability is for the destroy() method // Allocate 1024 elements asynchronously on the device let mut device_memory: DeviceVec = DeviceVec::::device_malloc_async(1024, &stream).unwrap(); diff --git a/docs/docs/icicle/rust-bindings.md b/docs/docs/icicle/rust-bindings.md index 431755ff9..bbfb16d9c 100644 --- a/docs/docs/icicle/rust-bindings.md +++ b/docs/docs/icicle/rust-bindings.md @@ -27,10 +27,10 @@ When you build your project ICICLE will be built as part of the build command. ## How do the rust bindings work? -The rust bindings are rust crates that wrap the ICICLE Core libraries (C++). Each crate can wrap one or more ICICLE core libraries. They are built too when buliding the crate. +The rust bindings are rust crates that wrap the ICICLE Core libraries (C++). Each crate can wrap one or more ICICLE core libraries. They are built too when building the crate. :::note -Since ICICLE V3, core libraies are shared-libraries. This means that they must be installed in a directory that can be found by the linker. In addition, installing an application that depends on ICICLE must make sure to install ICICLE or have it installed on the target machine. +Since ICICLE V3, core libraries are shared-libraries. This means that they must be installed in a directory that can be found by the linker. In addition, installing an application that depends on ICICLE must make sure to install ICICLE or have it installed on the target machine. ::: ## Supported curves, fields and operations From 9f08507939c613e18a847b6af2075be7169293df Mon Sep 17 00:00:00 2001 From: nonam3e Date: Mon, 19 Aug 2024 14:31:10 +0000 Subject: [PATCH 37/38] cargo fmt --- docs/docs/icicle/rust-bindings/ntt.md | 2 +- .../rust_v3/icicle-core/src/vec_ops/tests.rs | 20 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/docs/icicle/rust-bindings/ntt.md b/docs/docs/icicle/rust-bindings/ntt.md index 950fe0b4a..3933fce8d 100644 --- a/docs/docs/icicle/rust-bindings/ntt.md +++ b/docs/docs/icicle/rust-bindings/ntt.md @@ -71,7 +71,7 @@ println!("Generating random inputs on host for bn254..."); let scalars = Bn254ScalarCfg::generate_random(size); let mut ntt_results = DeviceVec::::device_malloc(size).unwrap(); -// constructin NTT domain +// constructing NTT domain initialize_domain( ntt::get_root_of_unity::( size.try_into() diff --git a/wrappers/rust_v3/icicle-core/src/vec_ops/tests.rs b/wrappers/rust_v3/icicle-core/src/vec_ops/tests.rs index 9b1e8476e..6762f06c9 100644 --- a/wrappers/rust_v3/icicle-core/src/vec_ops/tests.rs +++ b/wrappers/rust_v3/icicle-core/src/vec_ops/tests.rs @@ -2,8 +2,8 @@ use crate::test_utilities; use crate::traits::GenerateRandom; use crate::vec_ops::{ - add_scalars, accumulate_scalars, bit_reverse, bit_reverse_inplace, mul_scalars, sub_scalars, transpose_matrix, FieldImpl, VecOps, - VecOpsConfig, + accumulate_scalars, add_scalars, bit_reverse, bit_reverse_inplace, mul_scalars, sub_scalars, transpose_matrix, + FieldImpl, VecOps, VecOpsConfig, }; use icicle_runtime::device::Device; use icicle_runtime::memory::{DeviceVec, HostSlice}; @@ -73,7 +73,9 @@ where assert_eq!(result_main.as_slice(), result_ref.as_slice()); - stream.destroy().unwrap(); + stream + .destroy() + .unwrap(); } pub fn check_vec_ops_scalars_sub(test_size: usize) @@ -102,7 +104,9 @@ where assert_eq!(result_main.as_slice(), result_ref.as_slice()); - stream.destroy().unwrap(); + stream + .destroy() + .unwrap(); } pub fn check_vec_ops_scalars_mul(test_size: usize) @@ -131,7 +135,9 @@ where assert_eq!(result_main.as_slice(), result_ref.as_slice()); - stream.destroy().unwrap(); + stream + .destroy() + .unwrap(); } pub fn check_vec_ops_scalars_accumulate(test_size: usize) @@ -159,7 +165,9 @@ where assert_eq!(a_clone_slice.as_slice(), a_main_slice.as_slice()); - stream.destroy().unwrap(); + stream + .destroy() + .unwrap(); } pub fn check_matrix_transpose() From a044618aad2430c5d2ce9f9e2862a764db9109fa Mon Sep 17 00:00:00 2001 From: nonam3e Date: Mon, 19 Aug 2024 18:30:28 +0000 Subject: [PATCH 38/38] change constant name --- wrappers/rust_v3/icicle-core/src/msm/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wrappers/rust_v3/icicle-core/src/msm/tests.rs b/wrappers/rust_v3/icicle-core/src/msm/tests.rs index 1cddac1d4..b6487700a 100644 --- a/wrappers/rust_v3/icicle-core/src/msm/tests.rs +++ b/wrappers/rust_v3/icicle-core/src/msm/tests.rs @@ -193,7 +193,7 @@ where cfg.stream_handle = *stream; cfg.is_async = true; cfg.ext - .set_int(LARGE_BUCKET_FACTOR, 5); + .set_int(CUDA_MSM_LARGE_BUCKET_FACTOR, 5); cfg.c = 4; runtime::warmup(&stream).unwrap(); stream @@ -276,7 +276,7 @@ where cfg.stream_handle = *stream; cfg.is_async = true; cfg.ext - .set_int(LARGE_BUCKET_FACTOR, 5); + .set_int(CUDA_MSM_LARGE_BUCKET_FACTOR, 5); cfg.c = 4; runtime::warmup(&stream).unwrap(); stream