From 5c8c24bdfa1a5657f7890a5f295302fa9a8845af Mon Sep 17 00:00:00 2001 From: yarkin Date: Thu, 26 Oct 2023 13:19:09 +0800 Subject: [PATCH 01/40] Add some tests to cover corner cases. Those tests are supposed to pass without code modification. --- test/unittests.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/test/unittests.cpp b/test/unittests.cpp index 8ea7bbc..88abf48 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -204,6 +204,70 @@ void TestFieldElementEquality() } } +void TestFieldElementArithmeticCornerCases() { + const char* testVectorInput[] = { + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAA", // p-1 + "1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB", // p + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }; + + const char* testVectorExpectedSquare[] = { + "19adf63210c8e7b878a258c2f7031601413d6f0c9a02fab49db5bbff9268f1a76fe6e68be46104ec7ccb1f341c2d6ca3", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }; + + const char* testVectorExpectedAdd[] = { + "11ebab9dbb81e28c6cf28d7901622c038b256521ed1f9bcb57605e0db0ddbb51b93c0018d6c40005321300000006554d", + "1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaa9", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }; + + auto testSqureMul = [](const char* in, const char* expectedSquare, const char* expectedAdd) { + // Input should be convert to Montgomery form, so "raw" = false + auto input = fp::fromBytesBE(hexToBytes<48>(in), false, false); + // Expected result will be compared against numbers converted back from Montgomery form, so "raw" = true + auto fpExpectedSquare = fp::fromBytesBE(hexToBytes<48>(expectedSquare), false, true); + auto fpExpectedAdd = fp::fromBytesBE(hexToBytes<48>(expectedAdd), false, true); + + fp s,m,a; + + _square(&s, &*input); + _mul(&m, &*input, &*input); + _add(&a, &*input, &*input); + + s = s.fromMont(); + m = m.fromMont(); + a = a.fromMont(); + + if(!s.equal(m)) + { + throw invalid_argument("square != mul self"); + } + + if(!s.equal(*fpExpectedSquare)) + { + throw invalid_argument("square != expected"); + } + + if(!a.equal(*fpExpectedAdd)) + { + throw invalid_argument("add != expected"); + } + + }; + + for (int i = 0; i < sizeof(testVectorInput) / sizeof(const char*); ++i) { + testSqureMul(testVectorInput[i], testVectorExpectedSquare[i], testVectorExpectedAdd[i]); + } +} + void TestFieldElementHelpers() { // fe @@ -1760,6 +1824,7 @@ int main() TestFieldElementValidation(); TestFieldElementEquality(); + TestFieldElementArithmeticCornerCases(); TestFieldElementHelpers(); TestFieldElementSerialization(); TestFieldElementByteInputs(); From 5352bba3412bb69d43e53f0b3533dae5a6ca697d Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 31 Oct 2023 22:27:21 +0800 Subject: [PATCH 02/40] Always check if fp is valid when deserializing bytes. --- src/fp.cpp | 6 ++++-- test/unittests.cpp | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/fp.cpp b/src/fp.cpp index 01974e6..8155591 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -19,16 +19,18 @@ fp::fp(const fp& e) : d{e.d[0], e.d[1], e.d[2], e.d[3], e.d[4], e.d[5]} optional fp::fromBytesBE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. But we reserve the flag. fp e = fp(scalar::fromBytesBE<6>(in)); - if(check && !e.isValid()) return {}; + if(!e.isValid()) return {}; if(raw) return e; else return e.toMont(); } optional fp::fromBytesLE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. But we reserve the flag. fp e = fp(scalar::fromBytesLE<6>(in)); - if(check && !e.isValid()) return {}; + if(!e.isValid()) return {}; if(raw) return e; else return e.toMont(); } diff --git a/test/unittests.cpp b/test/unittests.cpp index 88abf48..d04d920 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -214,17 +214,17 @@ void TestFieldElementArithmeticCornerCases() { }; const char* testVectorExpectedSquare[] = { - "19adf63210c8e7b878a258c2f7031601413d6f0c9a02fab49db5bbff9268f1a76fe6e68be46104ec7ccb1f341c2d6ca3", + "NA", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "NA", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }; const char* testVectorExpectedAdd[] = { - "11ebab9dbb81e28c6cf28d7901622c038b256521ed1f9bcb57605e0db0ddbb51b93c0018d6c40005321300000006554d", + "NA", "1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaa9", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "NA", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }; @@ -232,6 +232,14 @@ void TestFieldElementArithmeticCornerCases() { auto testSqureMul = [](const char* in, const char* expectedSquare, const char* expectedAdd) { // Input should be convert to Montgomery form, so "raw" = false auto input = fp::fromBytesBE(hexToBytes<48>(in), false, false); + + if (0 == strcmp("NA", expectedSquare)) { + if (input) { + throw invalid_argument("input should be invalid but not"); + } + return; + } + // Expected result will be compared against numbers converted back from Montgomery form, so "raw" = true auto fpExpectedSquare = fp::fromBytesBE(hexToBytes<48>(expectedSquare), false, true); auto fpExpectedAdd = fp::fromBytesBE(hexToBytes<48>(expectedAdd), false, true); From aa71ed21676b0c6a4575c276edc92a3499984523 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 31 Oct 2023 22:54:16 +0800 Subject: [PATCH 03/40] Add benchmark for multiExp functions. --- bench/eth_bench.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/bench/eth_bench.cpp b/bench/eth_bench.cpp index 6e93967..44ec38a 100644 --- a/bench/eth_bench.cpp +++ b/bench/eth_bench.cpp @@ -118,6 +118,28 @@ void benchG1Mul() { endStopwatch(testName, start, numIters); } +void benchG1MultiExp() { + string testName = "G2 MultiExp"; + const int numIters = 10000; + g1 p = random_g1(); + vector bases = {p,p,p,p,p,p,p,p}; + vector> scalars = { + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff} + }; + auto start = startStopwatch(); + for (int i = 0; i < numIters; i++) { + g1::multiExp(bases, scalars); + } + endStopwatch(testName, start, numIters); +} + void benchG2Add() { string testName = "G2 Addition"; const int numIters = 1000000; @@ -145,6 +167,28 @@ void benchG2Mul() { endStopwatch(testName, start, numIters); } +void benchG2MultiExp() { + string testName = "G2 MultiExp"; + const int numIters = 10000; + g2 p = random_g2(); + vector bases = {p,p,p,p,p,p,p,p}; + vector> scalars = { + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, + {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff} + }; + auto start = startStopwatch(); + for (int i = 0; i < numIters; i++) { + g2::multiExp(bases, scalars); + } + endStopwatch(testName, start, numIters); +} + void benchPairing() { string testName = "Pairing"; const int numIters = 10000; @@ -165,7 +209,9 @@ int main(int argc, char* argv[]) { benchG1Add(); benchG1Mul(); + benchG1MultiExp(); benchG2Add(); benchG2Mul(); + benchG2MultiExp(); benchPairing(); } \ No newline at end of file From 13ff18f06f64782ac8d189ca0074d3899dfabb5b Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 1 Nov 2023 00:18:57 +0800 Subject: [PATCH 04/40] Add some garbage tests for g1/g2 serialization. --- test/unittests.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/test/unittests.cpp b/test/unittests.cpp index d04d920..78bcfc9 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -239,7 +239,7 @@ void TestFieldElementArithmeticCornerCases() { } return; } - + // Expected result will be compared against numbers converted back from Montgomery form, so "raw" = true auto fpExpectedSquare = fp::fromBytesBE(hexToBytes<48>(expectedSquare), false, true); auto fpExpectedAdd = fp::fromBytesBE(hexToBytes<48>(expectedAdd), false, true); @@ -463,6 +463,41 @@ void TestG1Serialization() } } +void TestG1SerializationGarbage() { + array buf; + buf.fill(0xff); + for (int i = 0 ; i < 4; ++i ) { + auto a = g1::fromJacobianBytesBE(buf, i < 2, i%2); + if(a) + { + throw invalid_argument("g1, jacobianBE: serialization not catching invalid input"); + } + auto b = g1::fromJacobianBytesLE(buf, i < 2, i%2); + if(b) + { + throw invalid_argument("g1, jacobianLE: serialization not catching invalid input"); + } + } + for (int i = 0 ; i < 4; ++i ) { + auto a = g1::fromAffineBytesBE(std::span{buf.begin(),96}, i < 2, i%2); + if(a) + { + throw invalid_argument("g1, affineBE: serialization not catching invalid input"); + } + auto b = g1::fromAffineBytesLE(std::span{buf.begin(),96}, i < 2, i%2); + if(b) + { + throw invalid_argument("g1, affineLE: serialization not catching invalid input"); + } + } + + auto a = g1::fromCompressedBytesBE(std::span{buf.begin(),48}); + if(a) + { + throw invalid_argument("g1, compressedBE: serialization not catching invalid input"); + } +} + void TestG1IsOnCurve() { g1 zero = g1::zero(); @@ -810,6 +845,41 @@ void TestG2Serialization() } } +void TestG2SerializationGarbage() { + array buf; + buf.fill(0xff); + for (int i = 0 ; i < 4; ++i ) { + auto a = g2::fromJacobianBytesBE(buf, i < 2, i%2); + if(a) + { + throw invalid_argument("g2, jacobianBE: serialization not catching invalid input"); + } + auto b = g2::fromJacobianBytesLE(buf, i < 2, i%2); + if(b) + { + throw invalid_argument("g2, jacobianLE: serialization not catching invalid input"); + } + } + for (int i = 0 ; i < 4; ++i ) { + auto a = g2::fromAffineBytesBE(std::span{buf.begin(),192}, i < 2, i%2); + if(a) + { + throw invalid_argument("g2, affineBE: serialization not catching invalid input"); + } + auto b = g2::fromAffineBytesLE(std::span{buf.begin(),192}, i < 2, i%2); + if(b) + { + throw invalid_argument("g2, affineLE: serialization not catching invalid input"); + } + } + + auto a = g2::fromCompressedBytesBE(std::span{buf.begin(),96}); + if(a) + { + throw invalid_argument("g2, compressedBE: serialization not catching invalid input"); + } +} + void TestG2IsOnCurve() { g2 zero = g2::zero(); From 0026605aba49f86914b63bc6eca3ac7711d00c0a Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 1 Nov 2023 00:32:54 +0800 Subject: [PATCH 05/40] Fix one missing sanity check and test cases. --- src/g.cpp | 1 + test/unittests.cpp | 15 +++------------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/g.cpp b/src/g.cpp index fae06fc..9f48768 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -68,6 +68,7 @@ optional g1::fromAffineBytesLE(const span in, const bool { optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), check, raw); optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), check, raw); + if(!x.has_value() || !y.has_value()) return {}; // check if given input points to infinity if(x.value().isZero() && y.value().isZero()) { diff --git a/test/unittests.cpp b/test/unittests.cpp index 78bcfc9..0b27462 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -478,6 +478,7 @@ void TestG1SerializationGarbage() { throw invalid_argument("g1, jacobianLE: serialization not catching invalid input"); } } + for (int i = 0 ; i < 4; ++i ) { auto a = g1::fromAffineBytesBE(std::span{buf.begin(),96}, i < 2, i%2); if(a) @@ -490,12 +491,6 @@ void TestG1SerializationGarbage() { throw invalid_argument("g1, affineLE: serialization not catching invalid input"); } } - - auto a = g1::fromCompressedBytesBE(std::span{buf.begin(),48}); - if(a) - { - throw invalid_argument("g1, compressedBE: serialization not catching invalid input"); - } } void TestG1IsOnCurve() @@ -872,12 +867,6 @@ void TestG2SerializationGarbage() { throw invalid_argument("g2, affineLE: serialization not catching invalid input"); } } - - auto a = g2::fromCompressedBytesBE(std::span{buf.begin(),96}); - if(a) - { - throw invalid_argument("g2, compressedBE: serialization not catching invalid input"); - } } void TestG2IsOnCurve() @@ -1908,6 +1897,7 @@ int main() TestFieldElementByteInputs(); TestG1Serialization(); + TestG1SerializationGarbage(); TestG1IsOnCurve(); TestG1AdditiveProperties(); TestG1MultiplicativePropertiesExpected(); @@ -1917,6 +1907,7 @@ int main() TestG1MapToCurve(); TestG2Serialization(); + TestG2SerializationGarbage(); TestG2IsOnCurve(); TestG2AdditiveProperties(); TestG2MultiplicativeProperties(); From 20eab24316b55f3a2c49117f9709d162b0b3f017 Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 1 Nov 2023 00:41:18 +0800 Subject: [PATCH 06/40] Add missing sanity check in g2::fromCompressedBytesBE --- src/g.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/g.cpp b/src/g.cpp index 9f48768..f4a640a 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -780,7 +780,11 @@ optional g2::fromCompressedBytesBE(const span in) bool ysign = ((in[0] >> 5) & 1) == 1; g2 p; scalar::fromBytesBE(span(&in[0], &in[48]), p.x.c1.d); - p.x.c0 = fp::fromBytesBE(span(&in[48], &in[96])).value(); + auto c0 = fp::fromBytesBE(span(&in[48], &in[96])); + if (!c0) { + return {}; + } + p.x.c0 = c0.value(); // erase 3 msbs from given input and perform validity check p.x.c1.d[5] &= 0x1FFFFFFFFFFFFFFF; p.x.c1 = p.x.c1.toMont(); From 443dc10fe92e031657cd23895130ebfa7d869798 Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 1 Nov 2023 13:38:42 +0800 Subject: [PATCH 07/40] Alternative way to enforce validation of deserialization. --- include/bls12-381/fp.hpp | 16 ++++++++-------- src/fp.cpp | 4 ++-- src/g.cpp | 40 ++++++++++++++++++++-------------------- test/unittests.cpp | 2 +- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/include/bls12-381/fp.hpp b/include/bls12-381/fp.hpp index 736acc9..26df4f5 100644 --- a/include/bls12-381/fp.hpp +++ b/include/bls12-381/fp.hpp @@ -20,8 +20,8 @@ class fp fp(); fp(const std::array& d); fp(const fp& e); - static std::optional fromBytesBE(const std::span in, const bool check = false, const bool raw = false); - static std::optional fromBytesLE(const std::span in, const bool check = false, const bool raw = false); + static std::optional fromBytesBE(const std::span in, const bool check = true, const bool raw = false); + static std::optional fromBytesLE(const std::span in, const bool check = true, const bool raw = false); void toBytesBE(const std::span out, const bool raw = false) const; void toBytesLE(const std::span out, const bool raw = false) const; std::array toBytesBE(const bool raw = false) const; @@ -73,8 +73,8 @@ class fp2 fp2(); fp2(const std::array& e2); fp2(const fp2& e); - static std::optional fromBytesBE(const std::span in, const bool check = false, const bool raw = false); - static std::optional fromBytesLE(const std::span in, const bool check = false, const bool raw = false); + static std::optional fromBytesBE(const std::span in, const bool check = true, const bool raw = false); + static std::optional fromBytesLE(const std::span in, const bool check = true, const bool raw = false); void toBytesBE(const std::span out, const bool raw = false) const; void toBytesLE(const std::span out, const bool raw = false) const; std::array toBytesBE(const bool raw = false) const; @@ -129,8 +129,8 @@ class fp6 fp6(); fp6(const std::array& e3); fp6(const fp6& e); - static std::optional fromBytesBE(const std::span in, const bool check = false, const bool raw = false); - static std::optional fromBytesLE(const std::span in, const bool check = false, const bool raw = false); + static std::optional fromBytesBE(const std::span in, const bool check = true, const bool raw = false); + static std::optional fromBytesLE(const std::span in, const bool check = true, const bool raw = false); void toBytesBE(const std::span out, const bool raw = false) const; void toBytesLE(const std::span out, const bool raw = false) const; std::array toBytesBE(const bool raw = false) const; @@ -176,8 +176,8 @@ class fp12 fp12(); fp12(const std::array& e2); fp12(const fp12& e); - static std::optional fromBytesBE(const std::span in, const bool check = false, const bool raw = false); - static std::optional fromBytesLE(const std::span in, const bool check = false, const bool raw = false); + static std::optional fromBytesBE(const std::span in, const bool check = true, const bool raw = false); + static std::optional fromBytesLE(const std::span in, const bool check = true, const bool raw = false); void toBytesBE(const std::span out, const bool raw = false) const; void toBytesLE(const std::span out, const bool raw = false) const; std::array toBytesBE(const bool raw = false) const; diff --git a/src/fp.cpp b/src/fp.cpp index 8155591..460637b 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -21,7 +21,7 @@ optional fp::fromBytesBE(const span in, const bool check, { // We decided to always validate the input here. But we reserve the flag. fp e = fp(scalar::fromBytesBE<6>(in)); - if(!e.isValid()) return {}; + if(check && !e.isValid()) return {}; if(raw) return e; else return e.toMont(); } @@ -30,7 +30,7 @@ optional fp::fromBytesLE(const span in, const bool check, { // We decided to always validate the input here. But we reserve the flag. fp e = fp(scalar::fromBytesLE<6>(in)); - if(!e.isValid()) return {}; + if(check && !e.isValid()) return {}; if(raw) return e; else return e.toMont(); } diff --git a/src/g.cpp b/src/g.cpp index f4a640a..64627ef 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -19,9 +19,9 @@ g1::g1(const g1& e) : x(e.x), y(e.y), z(e.z) optional g1::fromJacobianBytesBE(const span in, const bool check, const bool raw) { - optional x = fp::fromBytesBE(span(&in[ 0], &in[ 48]), check, raw); - optional y = fp::fromBytesBE(span(&in[48], &in[ 96]), check, raw); - optional z = fp::fromBytesBE(span(&in[96], &in[144]), check, raw); + optional x = fp::fromBytesBE(span(&in[ 0], &in[ 48]), true, raw); + optional y = fp::fromBytesBE(span(&in[48], &in[ 96]), true, raw); + optional z = fp::fromBytesBE(span(&in[96], &in[144]), true, raw); if(!x.has_value() || !y.has_value() || !z.has_value()) return {}; g1 p = g1({x.value(), y.value(), z.value()}); if(check && !p.isOnCurve()) @@ -33,9 +33,9 @@ optional g1::fromJacobianBytesBE(const span in, const bo optional g1::fromJacobianBytesLE(const span in, const bool check, const bool raw) { - optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), check, raw); - optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), check, raw); - optional z = fp::fromBytesLE(span(&in[96], &in[144]), check, raw); + optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), true, raw); + optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), true, raw); + optional z = fp::fromBytesLE(span(&in[96], &in[144]), true, raw); if(!x.has_value() || !y.has_value() || !z.has_value()) return {}; g1 p = g1({x.value(), y.value(), z.value()}); if(check && !p.isOnCurve()) @@ -47,8 +47,8 @@ optional g1::fromJacobianBytesLE(const span in, const bo optional g1::fromAffineBytesBE(const span in, const bool check, const bool raw) { - optional x = fp::fromBytesBE(span(&in[ 0], &in[ 48]), check, raw); - optional y = fp::fromBytesBE(span(&in[48], &in[ 96]), check, raw); + optional x = fp::fromBytesBE(span(&in[ 0], &in[ 48]), true, raw); + optional y = fp::fromBytesBE(span(&in[48], &in[ 96]), true, raw); if(!x.has_value() || !y.has_value()) return {}; // check if given input points to infinity if(x.value().isZero() && y.value().isZero()) @@ -66,8 +66,8 @@ optional g1::fromAffineBytesBE(const span in, const bool optional g1::fromAffineBytesLE(const span in, const bool check, const bool raw) { - optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), check, raw); - optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), check, raw); + optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), true, raw); + optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), true, raw); if(!x.has_value() || !y.has_value()) return {}; // check if given input points to infinity if(x.value().isZero() && y.value().isZero()) @@ -700,9 +700,9 @@ g2::g2(const g2& e) : x(e.x), y(e.y), z(e.z) optional g2::fromJacobianBytesBE(const span in, const bool check, const bool raw) { - optional x = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), check, raw); - optional y = fp2::fromBytesBE(span(&in[ 96], &in[192]), check, raw); - optional z = fp2::fromBytesBE(span(&in[192], &in[288]), check, raw); + optional x = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), true, raw); + optional y = fp2::fromBytesBE(span(&in[ 96], &in[192]), true, raw); + optional z = fp2::fromBytesBE(span(&in[192], &in[288]), true, raw); if(!x.has_value() || !y.has_value() || !z.has_value()) return {}; g2 p = g2({x.value(), y.value(), z.value()}); if(check && !p.isOnCurve()) @@ -714,9 +714,9 @@ optional g2::fromJacobianBytesBE(const span in, const bo optional g2::fromJacobianBytesLE(const span in, const bool check, const bool raw) { - optional x = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), check, raw); - optional y = fp2::fromBytesLE(span(&in[ 96], &in[192]), check, raw); - optional z = fp2::fromBytesLE(span(&in[192], &in[288]), check, raw); + optional x = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), true, raw); + optional y = fp2::fromBytesLE(span(&in[ 96], &in[192]), true, raw); + optional z = fp2::fromBytesLE(span(&in[192], &in[288]), true, raw); if(!x.has_value() || !y.has_value() || !z.has_value()) return {}; g2 p = g2({x.value(), y.value(), z.value()}); if(check && !p.isOnCurve()) @@ -728,8 +728,8 @@ optional g2::fromJacobianBytesLE(const span in, const bo optional g2::fromAffineBytesBE(const span in, const bool check, const bool raw) { - optional x = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), check, raw); - optional y = fp2::fromBytesBE(span(&in[ 96], &in[192]), check, raw); + optional x = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), true, raw); + optional y = fp2::fromBytesBE(span(&in[ 96], &in[192]), true, raw); if(!x.has_value() || !y.has_value()) return {}; // check if given input points to infinity if(x.value().isZero() && y.value().isZero()) @@ -747,8 +747,8 @@ optional g2::fromAffineBytesBE(const span in, const bool optional g2::fromAffineBytesLE(const span in, const bool check, const bool raw) { - optional x = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), check, raw); - optional y = fp2::fromBytesLE(span(&in[ 96], &in[192]), check, raw); + optional x = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), true, raw); + optional y = fp2::fromBytesLE(span(&in[ 96], &in[192]), true, raw); if(!x.has_value() || !y.has_value()) return {}; // check if given input points to infinity if(x.value().isZero() && y.value().isZero()) diff --git a/test/unittests.cpp b/test/unittests.cpp index 0b27462..d019132 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -231,7 +231,7 @@ void TestFieldElementArithmeticCornerCases() { auto testSqureMul = [](const char* in, const char* expectedSquare, const char* expectedAdd) { // Input should be convert to Montgomery form, so "raw" = false - auto input = fp::fromBytesBE(hexToBytes<48>(in), false, false); + auto input = fp::fromBytesBE(hexToBytes<48>(in), true, false); if (0 == strcmp("NA", expectedSquare)) { if (input) { From b80ff4c03e2e1ba7b3e4843748986e3caa32a7df Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 1 Nov 2023 14:07:12 +0800 Subject: [PATCH 08/40] Rename multiExp and mulScalar. --- bench/eth_bench.cpp | 24 +++---- include/bls12-381/g.hpp | 8 +-- include/bls12-381/scalar.hpp | 4 +- src/g.cpp | 18 +++--- src/signatures.cpp | 10 +-- test/unittests.cpp | 118 +++++++++++++++++------------------ 6 files changed, 91 insertions(+), 91 deletions(-) diff --git a/bench/eth_bench.cpp b/bench/eth_bench.cpp index 44ec38a..9615f48 100644 --- a/bench/eth_bench.cpp +++ b/bench/eth_bench.cpp @@ -82,13 +82,13 @@ fp12 random_fe12() g1 random_g1() { array k = random_scalar(); - return g1::one().mulScalar(k); + return g1::one().scale(k); } g2 random_g2() { array k = random_scalar(); - return g2::one().mulScalar(k); + return g2::one().scale(k); } void benchG1Add() { @@ -113,13 +113,13 @@ void benchG1Mul() { auto start = startStopwatch(); for (int i = 0; i < numIters; i++) { - p.mulScalar(s); + p.scale(s); } endStopwatch(testName, start, numIters); } -void benchG1MultiExp() { - string testName = "G2 MultiExp"; +void benchG1WeightedSum() { + string testName = "G2 WeightedSum"; const int numIters = 10000; g1 p = random_g1(); vector bases = {p,p,p,p,p,p,p,p}; @@ -135,7 +135,7 @@ void benchG1MultiExp() { }; auto start = startStopwatch(); for (int i = 0; i < numIters; i++) { - g1::multiExp(bases, scalars); + g1::weightedSum(bases, scalars); } endStopwatch(testName, start, numIters); } @@ -162,13 +162,13 @@ void benchG2Mul() { auto start = startStopwatch(); for (int i = 0; i < numIters; i++) { - p.mulScalar(s); + p.scale(s); } endStopwatch(testName, start, numIters); } -void benchG2MultiExp() { - string testName = "G2 MultiExp"; +void benchG2WeightedSum() { + string testName = "G2 WeightedSum"; const int numIters = 10000; g2 p = random_g2(); vector bases = {p,p,p,p,p,p,p,p}; @@ -184,7 +184,7 @@ void benchG2MultiExp() { }; auto start = startStopwatch(); for (int i = 0; i < numIters; i++) { - g2::multiExp(bases, scalars); + g2::weightedSum(bases, scalars); } endStopwatch(testName, start, numIters); } @@ -209,9 +209,9 @@ int main(int argc, char* argv[]) { benchG1Add(); benchG1Mul(); - benchG1MultiExp(); + benchG1WeightedSum(); benchG2Add(); benchG2Mul(); - benchG2MultiExp(); + benchG2WeightedSum(); benchPairing(); } \ No newline at end of file diff --git a/include/bls12-381/g.hpp b/include/bls12-381/g.hpp index 836d876..748e8c0 100644 --- a/include/bls12-381/g.hpp +++ b/include/bls12-381/g.hpp @@ -54,10 +54,10 @@ class g1 g1 dbl() const; g1 neg() const; g1 sub(const g1& e) const; - template g1 mulScalar(const std::array& s) const; + template g1 scale(const std::array& s) const; g1 clearCofactor() const; g1 glvEndomorphism() const; - static std::optional multiExp(const std::vector& points, const std::vector>& scalars, std::function yield = std::function()); + static std::optional weightedSum(const std::vector& points, const std::vector>& scalars, std::function yield = std::function()); static g1 mapToCurve(const fp& e); static std::tuple swuMapG1(const fp& e); static void isogenyMapG1(fp& x, fp& y); @@ -108,10 +108,10 @@ class g2 g2 neg() const; g2 sub(const g2& e) const; g2 psi() const; - template g2 mulScalar(const std::array& s) const; + template g2 scale(const std::array& s) const; g2 clearCofactor() const; g2 frobeniusMap(int64_t power) const; - static std::optional multiExp(const std::vector& points, const std::vector>& scalars, std::function yield = std::function()); + static std::optional weightedSum(const std::vector& points, const std::vector>& scalars, std::function yield = std::function()); static g2 mapToCurve(const fp2& e); static std::tuple swuMapG2(const fp2& e); //static void isogenyMapG2(fp2& x, fp2& y); diff --git a/include/bls12-381/scalar.hpp b/include/bls12-381/scalar.hpp index 0d161e9..3ff2f88 100644 --- a/include/bls12-381/scalar.hpp +++ b/include/bls12-381/scalar.hpp @@ -327,7 +327,7 @@ fp12 fp12::cyclotomicExp(const std::array& s) const } template -g1 g1::mulScalar(const std::array& s) const +g1 g1::scale(const std::array& s) const { g1 q = g1({fp::zero(), fp::zero(), fp::zero()}); g1 n = *this; @@ -344,7 +344,7 @@ g1 g1::mulScalar(const std::array& s) const } template -g2 g2::mulScalar(const std::array& s) const +g2 g2::scale(const std::array& s) const { g2 q = g2({fp2::zero(), fp2::zero(), fp2::zero()}); g2 n = *this; diff --git a/src/g.cpp b/src/g.cpp index 64627ef..192a997 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -272,7 +272,7 @@ bool g1::inCorrectSubgroup() const t1 = t1.dbl(); t1 = t1.sub(*this); t1 = t1.sub(t0); - t1 = t1.mulScalar<2>({0x0000000055555555, 0x396c8c005555e156}); + t1 = t1.scale<2>({0x0000000055555555, 0x396c8c005555e156}); t1 = t1.sub(t0); return t1.isZero(); } @@ -423,7 +423,7 @@ g1 g1::sub(const g1& e) const g1 g1::clearCofactor() const { - return this->mulScalar(cofactorEFF); + return this->scale(cofactorEFF); } g1 g1::glvEndomorphism() const @@ -437,10 +437,10 @@ g1 g1::glvEndomorphism() const return t; } -// MultiExp calculates multi exponentiation. Given pairs of G1 point and scalar values +// WeightedSum calculates multi exponentiation. Given pairs of G1 point and scalar values // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n // Length of points and scalars are expected to be equal, otherwise NONE is returned. -optional g1::multiExp(const vector& points, const vector>& scalars, std::function yield) +optional g1::weightedSum(const vector& points, const vector>& scalars, std::function yield) { if(points.size() != scalars.size()) { @@ -957,7 +957,7 @@ bool g2::inCorrectSubgroup() const t0 = t0.psi(); t1 = t0.neg(); // - ψ^2(P) t0 = t0.psi(); // ψ^3(P) - t0 = t0.mulScalar(cofactorEFF); // - x ψ^3(P) + t0 = t0.scale(cofactorEFF); // - x ψ^3(P) t0 = t0.neg(); t0 = t0.add(t1); @@ -1125,11 +1125,11 @@ g2 g2::clearCofactor() const { g2 t0, t1, t2, t3; // Compute t0 = xP - t0 = mulScalar(cofactorEFF); + t0 = scale(cofactorEFF); // cofactorEFF has the MSB set, so relic has the sign bit set and negates the y coordinate t0 = t0.neg(); // Compute t1 = [x^2]P - t1 = t0.mulScalar(cofactorEFF); + t1 = t0.scale(cofactorEFF); // cofactorEFF has the MSB set, so relic has the sign bit set and negates the y coordinate t1 = t1.neg(); @@ -1169,10 +1169,10 @@ g2 g2::frobeniusMap(int64_t power) const return r; } -// MultiExp calculates multi exponentiation. Given pairs of G2 point and scalar values +// WeightedSum calculates multi exponentiation. Given pairs of G2 point and scalar values // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n // Length of points and scalars are expected to be equal, otherwise NONE is returned. -optional g2::multiExp(const vector& points, const vector>& scalars, std::function yield) +optional g2::weightedSum(const vector& points, const vector>& scalars, std::function yield) { if(points.size() != scalars.size()) { diff --git a/src/signatures.cpp b/src/signatures.cpp index b60fa90..eda8b4a 100644 --- a/src/signatures.cpp +++ b/src/signatures.cpp @@ -352,7 +352,7 @@ g1 derive_child_g1_unhardened( bn_divn_safe(quotient, remainder, nonce, fp::Q); - return pk.add(g1::one().mulScalar(remainder)); + return pk.add(g1::one().scale(remainder)); } g2 derive_child_g2_unhardened( @@ -378,7 +378,7 @@ g2 derive_child_g2_unhardened( bn_divn_safe(quotient, remainder, nonce, fp::Q); - return pk.add(g2::one().mulScalar(remainder)); + return pk.add(g2::one().scale(remainder)); } array aggregate_secret_keys(const vector>& sks) @@ -437,7 +437,7 @@ array sk_from_bytes( g1 public_key(const array& sk) { - return g1::one().mulScalar(sk).affine(); + return g1::one().scale(sk).affine(); } // Construct an extensible-output function based on SHA256 @@ -532,7 +532,7 @@ g2 sign( ) { g2 p = fromMessage(msg, CIPHERSUITE_ID); - return p.mulScalar(sk); + return p.scale(sk); } bool verify( @@ -632,7 +632,7 @@ g2 pop_prove(const array& sk) g1 pk = public_key(sk); array msg = pk.toCompressedBytesBE(); g2 hashed_key = fromMessage(vector(msg.begin(), msg.end()), POP_CIPHERSUITE_ID); - return hashed_key.mulScalar(sk); + return hashed_key.scale(sk); } bool pop_verify( diff --git a/test/unittests.cpp b/test/unittests.cpp index d019132..e0733fc 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -66,13 +66,13 @@ fp12 random_fe12() g1 random_g1() { array k = random_scalar(); - return g1::one().mulScalar(k); + return g1::one().scale(k); } g2 random_g2() { array k = random_scalar(); - return g2::one().mulScalar(k); + return g2::one().scale(k); } void TestScalar() @@ -619,34 +619,34 @@ void TestG1MultiplicativePropertiesExpected() array s2 = tv[i].s2; array s3; array sone = {1, 0, 0, 0}; - t0 = zero.mulScalar(s1); + t0 = zero.scale(s1); if(!t0.equal(zero)) { throw invalid_argument(" 0 ^ s == 0"); } - t0 = a.mulScalar(sone); + t0 = a.scale(sone); if(!t0.equal(a)) { throw invalid_argument(" a ^ 1 == a"); } - t0 = zero.mulScalar(s1); + t0 = zero.scale(s1); if(!t0.equal(zero)) { throw invalid_argument(" 0 ^ s == a"); } - t0 = a.mulScalar(s1); - t0 = t0.mulScalar(s2); + t0 = a.scale(s1); + t0 = t0.scale(s2); s3 = scalar::mul<10, 4, 4>(s1, s2); - t1 = a.mulScalar(s3); + t1 = a.scale(s3); if(!t0.equal(t1)) { throw invalid_argument("G1: (a ^ s1) ^ s2 == a ^ (s1 * s2)"); } - t0 = a.mulScalar(s1); - t1 = a.mulScalar(s2); + t0 = a.scale(s1); + t1 = a.scale(s2); t0 = t0.add(t1); s3 = scalar::add<10, 4, 4>(s1, s2); - t1 = a.mulScalar(s3); + t1 = a.scale(s3); if(!t0.equal(t1)) { throw invalid_argument(" (a ^ s1) + (a ^ s2) == a ^ (s1 + s2)"); @@ -665,34 +665,34 @@ void TestG1MultiplicativeProperties() array s2 = random_scalar(); array s3; array sone = {1, 0, 0, 0}; - t0 = zero.mulScalar(s1); + t0 = zero.scale(s1); if(!t0.equal(zero)) { throw invalid_argument(" 0 ^ s == 0"); } - t0 = a.mulScalar(sone); + t0 = a.scale(sone); if(!t0.equal(a)) { throw invalid_argument(" a ^ 1 == a"); } - t0 = zero.mulScalar(s1); + t0 = zero.scale(s1); if(!t0.equal(zero)) { throw invalid_argument(" 0 ^ s == a"); } - t0 = a.mulScalar(s1); - t0 = t0.mulScalar(s2); + t0 = a.scale(s1); + t0 = t0.scale(s2); s3 = scalar::mul<10, 4, 4>(s1, s2); - t1 = a.mulScalar(s3); + t1 = a.scale(s3); if(!t0.equal(t1)) { throw invalid_argument("G1: (a ^ s1) ^ s2 == a ^ (s1 * s2)"); } - t0 = a.mulScalar(s1); - t1 = a.mulScalar(s2); + t0 = a.scale(s1); + t1 = a.scale(s2); t0 = t0.add(t1); s3 = scalar::add<10, 4, 4>(s1, s2); - t1 = a.mulScalar(s3); + t1 = a.scale(s3); if(!t0.equal(t1)) { throw invalid_argument(" (a ^ s1) + (a ^ s2) == a ^ (s1 + s2)"); @@ -700,7 +700,7 @@ void TestG1MultiplicativeProperties() } } -void TestG1MultiExpExpected() +void TestG1WeightedSumExpected() { g1 one = g1::one(); vector> scalars = { @@ -709,15 +709,15 @@ void TestG1MultiExpExpected() }; vector bases = {one, one}; g1 expected, result; - expected = one.mulScalar<1>({5}); - result = g1::multiExp(bases, scalars).value(); + expected = one.scale<1>({5}); + result = g1::weightedSum(bases, scalars).value(); if(!expected.equal(result)) { - throw invalid_argument("TestG1MultiExpExpected: bad multi-exponentiation"); + throw invalid_argument("TestG1WeightedSumExpected: bad multi-exponentiation"); } } -void TestG1MultiExpBatch() +void TestG1WeightedSumBatch() { g1 one = g1::one(); int64_t n = 1000; @@ -729,16 +729,16 @@ void TestG1MultiExpBatch() { scalars.insert(scalars.begin(), array{static_cast(rand()%100000), 0, 0, 0}); bases.push_back(g1::zero()); - bases[i] = one.mulScalar(scalars[0]); + bases[i] = one.scale(scalars[0]); } // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) g1 expected, tmp; for(int64_t i = 0; i < n; i++) { - tmp = bases[i].mulScalar(scalars[i]); + tmp = bases[i].scale(scalars[i]); expected = expected.add(tmp); } - g1 result = g1::multiExp(bases, scalars).value(); + g1 result = g1::weightedSum(bases, scalars).value(); if(!expected.equal(result)) { throw invalid_argument("bad multi-exponentiation"); @@ -978,34 +978,34 @@ void TestG2MultiplicativeProperties() array s2 = random_scalar(); array s3; array sone = {1, 0, 0, 0}; - t0 = zero.mulScalar(s1); + t0 = zero.scale(s1); if(!t0.equal(zero)) { throw invalid_argument(" 0 ^ s == 0"); } - t0 = a.mulScalar(sone); + t0 = a.scale(sone); if(!t0.equal(a)) { throw invalid_argument(" a ^ 1 == a"); } - t0 = zero.mulScalar(s1); + t0 = zero.scale(s1); if(!t0.equal(zero)) { throw invalid_argument(" 0 ^ s == a"); } - t0 = a.mulScalar(s1); - t0 = t0.mulScalar(s2); + t0 = a.scale(s1); + t0 = t0.scale(s2); s3 = scalar::mul<10, 4, 4>(s1, s2); - t1 = a.mulScalar(s3); + t1 = a.scale(s3); if(!t0.equal(t1)) { throw invalid_argument("G2: (a ^ s1) ^ s2 == a ^ (s1 * s2)"); } - t0 = a.mulScalar(s1); - t1 = a.mulScalar(s2); + t0 = a.scale(s1); + t1 = a.scale(s2); t0 = t0.add(t1); s3 = scalar::add<10, 4, 4>(s1, s2); - t1 = a.mulScalar(s3); + t1 = a.scale(s3); if(!t0.equal(t1)) { throw invalid_argument(" (a ^ s1) + (a ^ s2) == a ^ (s1 + s2)"); @@ -1013,7 +1013,7 @@ void TestG2MultiplicativeProperties() } } -void TestG2MultiExpExpected() +void TestG2WeightedSumExpected() { g2 one = g2::one(); vector> scalars = { @@ -1022,15 +1022,15 @@ void TestG2MultiExpExpected() }; vector bases = {one, one}; g2 expected, result; - expected = one.mulScalar<1>({5}); - result = g2::multiExp(bases, scalars).value(); + expected = one.scale<1>({5}); + result = g2::weightedSum(bases, scalars).value(); if(!expected.equal(result)) { throw invalid_argument("bad multi-exponentiation"); } } -void TestG2MultiExpBatch() +void TestG2WeightedSumBatch() { g2 one = g2::one(); int64_t n = 1000; @@ -1042,16 +1042,16 @@ void TestG2MultiExpBatch() { scalars.insert(scalars.begin(), array{static_cast(rand()%100000), 0, 0, 0}); bases.push_back(g2::zero()); - bases[i] = one.mulScalar(scalars[0]); + bases[i] = one.scale(scalars[0]); } // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) g2 expected, tmp; for(int64_t i = 0; i < n; i++) { - tmp = bases[i].mulScalar(scalars[i]); + tmp = bases[i].scale(scalars[i]); expected = expected.add(tmp); } - g2 result = g2::multiExp(bases, scalars).value(); + g2 result = g2::weightedSum(bases, scalars).value(); if(!expected.equal(result)) { throw invalid_argument("bad multi-exponentiation"); @@ -1224,8 +1224,8 @@ void TestPairingBilinearity() vector> v; pairing::add_pair(v, G1, G2); fp12 e0 = pairing::calculate(v); - g1 P1 = G1.mulScalar(a); - g2 P2 = G2.mulScalar(b); + g1 P1 = G1.scale(a); + g2 P2 = G2.scale(b); v = {}; pairing::add_pair(v, P1, P2); fp12 e1 = pairing::calculate(v); @@ -1246,13 +1246,13 @@ void TestPairingBilinearity() // LHS g1 G1 = g1::one(); g2 G2 = g2::one(); - G1 = G1.mulScalar(c); + G1 = G1.scale(c); pairing::add_pair(v, G1, G2); // RHS g1 P1 = g1::one(); g2 P2 = g2::one(); - P1 = P1.mulScalar(a); - P2 = P2.mulScalar(b); + P1 = P1.scale(a); + P2 = P2.scale(b); P1 = P1.neg(); pairing::add_pair(v, P1, P2); // should be one @@ -1272,13 +1272,13 @@ void TestPairingBilinearity() // LHS g1 G1 = g1::one(); g2 G2 = g2::one(); - G2 = G2.mulScalar(c); + G2 = G2.scale(c); pairing::add_pair(v, G1, G2); // RHS g1 H1 = g1::one(); g2 H2 = g2::one(); - H1 = H1.mulScalar(a); - H2 = H2.mulScalar(b); + H1 = H1.scale(a); + H2 = H2.scale(b); H1 = H1.neg(); pairing::add_pair(v, H1, H2); // should be one @@ -1304,8 +1304,8 @@ void TestPairingMulti() array a2 = random_scalar(); g1 P1 = g1::one(); g2 P2 = g2::one(); - P1 = P1.mulScalar(a1); - P2 = P2.mulScalar(a2); + P1 = P1.scale(a1); + P2 = P2.scale(a2); pairing::add_pair(v, P1, P2); // accumulate targetExp // t += (ai1 * ai2) @@ -1316,7 +1316,7 @@ void TestPairingMulti() // e(t * G1, G2) g1 T1 = g1::one(); g2 T2 = g2::one(); - T1 = T1.mulScalar(targetExp); + T1 = T1.scale(targetExp); T1 = T1.neg(); pairing::add_pair(v, T1, T2); if(!pairing::calculate(v).isOne()) @@ -1902,8 +1902,8 @@ int main() TestG1AdditiveProperties(); TestG1MultiplicativePropertiesExpected(); TestG1MultiplicativeProperties(); - TestG1MultiExpExpected(); - TestG1MultiExpBatch(); + TestG1WeightedSumExpected(); + TestG1WeightedSumBatch(); TestG1MapToCurve(); TestG2Serialization(); @@ -1911,8 +1911,8 @@ int main() TestG2IsOnCurve(); TestG2AdditiveProperties(); TestG2MultiplicativeProperties(); - TestG2MultiExpExpected(); - TestG2MultiExpBatch(); + TestG2WeightedSumExpected(); + TestG2WeightedSumBatch(); TestG2MapToCurve(); TestPairingExpected(); From dc4d6a6ecd7ce41007d409017def9ffd5b0b1c38 Mon Sep 17 00:00:00 2001 From: yarkin Date: Thu, 2 Nov 2023 22:32:38 +0800 Subject: [PATCH 09/40] Rename multiple functions --- include/bls12-381/arithmetic.hpp | 12 +- include/bls12-381/fp.hpp | 30 +-- include/bls12-381/g.hpp | 8 +- include/bls12-381/scalar.hpp | 14 +- src/arithmetic.cpp | 34 ++-- src/fp.cpp | 326 +++++++++++++++---------------- src/g.cpp | 286 +++++++++++++-------------- src/pairing.cpp | 76 +++---- src/signatures.cpp | 6 +- test/unittests.cpp | 68 +++---- 10 files changed, 430 insertions(+), 430 deletions(-) diff --git a/include/bls12-381/arithmetic.hpp b/include/bls12-381/arithmetic.hpp index eb4cb5b..063c9c5 100644 --- a/include/bls12-381/arithmetic.hpp +++ b/include/bls12-381/arithmetic.hpp @@ -18,18 +18,18 @@ void _laddAssign(fp* x, const fp* y); void _double(fp* z, const fp* x); void _doubleAssign(fp* z); void _ldouble(fp* z, const fp* x); -void _sub(fp* z, const fp* x, const fp* y); -void _subAssign(fp* z, const fp* x); -void _lsubAssign(fp* z, const fp* x); -void _neg(fp* z, const fp* x); +void _subtract(fp* z, const fp* x, const fp* y); +void _subtractAssign(fp* z, const fp* x); +void _lsubtractAssign(fp* z, const fp* x); +void _negate(fp* z, const fp* x); void _square(fp* z, const fp* x); #if defined(__x86_64__) && defined(__ELF__) -extern void _mul(fp*, const fp*, const fp*); +extern void _multiply(fp*, const fp*, const fp*); #elif defined(__x86_64__) extern void (*_mul)(fp*, const fp*, const fp*); #else -void _mul(fp*, const fp*, const fp*); +void _multiply(fp*, const fp*, const fp*); #endif // Add64 returns the sum with carry of x, y and carry: sum = x + y + carry. diff --git a/include/bls12-381/fp.hpp b/include/bls12-381/fp.hpp index 26df4f5..1a8e38f 100644 --- a/include/bls12-381/fp.hpp +++ b/include/bls12-381/fp.hpp @@ -91,12 +91,12 @@ class fp2 fp2 dbl() const; void doubleAssign(); fp2 ldouble() const; - fp2 sub(const fp2& e) const; - void subAssign(const fp2& e); - fp2 neg() const; - fp2 conj() const; - fp2 mul(const fp2& e) const; - void mulAssign(const fp2& e); + fp2 subtract(const fp2& e) const; + void subtractAssign(const fp2& e); + fp2 negate() const; + fp2 conjugate() const; + fp2 multiply(const fp2& e) const; + void multiplyAssign(const fp2& e); fp2 square() const; void squareAssign(); fp2 mulByNonResidue() const; @@ -144,11 +144,11 @@ class fp6 void addAssign(const fp6& e); fp6 dbl() const; void doubleAssign(); - fp6 sub(const fp6& e) const; - void subAssign(const fp6& e); - fp6 neg() const; - fp6 mul(const fp6& e) const; - void mulAssign(const fp6& e); + fp6 subtract(const fp6& e) const; + void subtractAssign(const fp6& e); + fp6 negate() const; + fp6 multiply(const fp6& e) const; + void multiplyAssign(const fp6& e); fp6 square() const; void mulBy01Assign(const fp2& e0, const fp2& e1); fp6 mulBy01(const fp2& e0, const fp2& e1) const; @@ -190,13 +190,13 @@ class fp12 bool equal(const fp12& e) const; fp12 add(const fp12& e) const; fp12 dbl() const; - fp12 sub(const fp12& e) const; - fp12 neg() const; + fp12 subtract(const fp12& e) const; + fp12 negate() const; fp12 conjugate() const; fp12 square() const; fp12 cyclotomicSquare() const; - fp12 mul(const fp12& e) const; - void mulAssign(const fp12& e); + fp12 multiply(const fp12& e) const; + void multiplyAssign(const fp12& e); static std::tuple fp4Square(const fp2& e0, const fp2& e1); fp12 inverse() const; void mulBy014Assign(const fp2& e0, const fp2& e1, const fp2& e4); diff --git a/include/bls12-381/g.hpp b/include/bls12-381/g.hpp index 748e8c0..90be1f7 100644 --- a/include/bls12-381/g.hpp +++ b/include/bls12-381/g.hpp @@ -52,8 +52,8 @@ class g1 g1 affine() const; g1 add(const g1& e) const; g1 dbl() const; - g1 neg() const; - g1 sub(const g1& e) const; + g1 negate() const; + g1 subtract(const g1& e) const; template g1 scale(const std::array& s) const; g1 clearCofactor() const; g1 glvEndomorphism() const; @@ -105,8 +105,8 @@ class g2 g2 affine() const; g2 add(const g2& e) const; g2 dbl() const; - g2 neg() const; - g2 sub(const g2& e) const; + g2 negate() const; + g2 subtract(const g2& e) const; g2 psi() const; template g2 scale(const std::array& s) const; g2 clearCofactor() const; diff --git a/include/bls12-381/scalar.hpp b/include/bls12-381/scalar.hpp index 3ff2f88..00a71b7 100644 --- a/include/bls12-381/scalar.hpp +++ b/include/bls12-381/scalar.hpp @@ -124,7 +124,7 @@ std::array add(const std::array& a, const std::array // multiplies two std::arrays: calculates c = a * b template -std::array mul(const std::array& a, const std::array& b) +std::array multiply(const std::array& a, const std::array& b) { std::array c; memset(c.data(), 0, NC * sizeof(uint64_t)); @@ -254,10 +254,10 @@ fp fp::exp(const std::array& s) const uint64_t l = scalar::bitLength(s); for(int64_t i = l - 1; i >= 0; i--) { - _mul(&z, &z, &z); + _multiply(&z, &z, &z); if((s[i/64] >> (i%64) & 1) == 1) { - _mul(&z, &z, this); + _multiply(&z, &z, this); } } return z; @@ -273,7 +273,7 @@ fp2 fp2::exp(const std::array& s) const z = z.square(); if((s[i/64] >> (i%64) & 1) == 1) { - z = z.mul(*this); + z = z.multiply(*this); } } return z; @@ -289,7 +289,7 @@ fp6 fp6::exp(const std::array& s) const z = z.square(); if((s[i/64] >> (i%64) & 1) == 1) { - z = z.mul(*this); + z = z.multiply(*this); } } return z; @@ -304,7 +304,7 @@ template fp12 fp12::exp(const std::array& s) const z = z.square(); if((s[i/64] >> (i%64) & 1) == 1) { - z = z.mul(*this); + z = z.multiply(*this); } } return z; @@ -320,7 +320,7 @@ fp12 fp12::cyclotomicExp(const std::array& s) const z = z.cyclotomicSquare(); if((s[i/64] >> (i%64) & 1) == 1) { - z = z.mul(*this); + z = z.multiply(*this); } } return z; diff --git a/src/arithmetic.cpp b/src/arithmetic.cpp index 56fa924..02dc80e 100644 --- a/src/arithmetic.cpp +++ b/src/arithmetic.cpp @@ -476,7 +476,7 @@ void _ldouble(fp* z, const fp* x) #endif #ifdef __x86_64__ -void _sub(fp* z, const fp* x, const fp* y) +void _subtract(fp* z, const fp* x, const fp* y) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): // z => %rdi @@ -532,7 +532,7 @@ void _sub(fp* z, const fp* x, const fp* y) asm("pop %r15;"); } #else -void _sub(fp* z, const fp* x, const fp* y) +void _subtract(fp* z, const fp* x, const fp* y) { uint64_t b; tie(z->d[0], b) = Sub64(x->d[0], y->d[0], 0); @@ -555,7 +555,7 @@ void _sub(fp* z, const fp* x, const fp* y) #endif #ifdef __x86_64__ -void _subAssign(fp* z, const fp* x) +void _subtractAssign(fp* z, const fp* x) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): // z => %rdi @@ -610,7 +610,7 @@ void _subAssign(fp* z, const fp* x) asm("pop %r15;"); } #else -void _subAssign(fp* z, const fp* x) +void _subtractAssign(fp* z, const fp* x) { uint64_t b; tie(z->d[0], b) = Sub64(z->d[0], x->d[0], 0); @@ -633,7 +633,7 @@ void _subAssign(fp* z, const fp* x) #endif #ifdef __x86_64__ -void _lsubAssign(fp* z, const fp* x) +void _lsubtractAssign(fp* z, const fp* x) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): // z => %rdi @@ -659,7 +659,7 @@ void _lsubAssign(fp* z, const fp* x) asm("mov %rax,0x28(%rdi);"); } #else -void _lsubAssign(fp* z, const fp* x) +void _lsubtractAssign(fp* z, const fp* x) { uint64_t b, _; tie(z->d[0], b) = Sub64(z->d[0], x->d[0], 0); @@ -672,7 +672,7 @@ void _lsubAssign(fp* z, const fp* x) #endif #ifdef __x86_64__ -void __neg(fp* z, const fp* x) +void __negate(fp* z, const fp* x) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): // z => %rdi @@ -697,9 +697,9 @@ void __neg(fp* z, const fp* x) asm("mov %rcx,0x20(%rdi);"); asm("mov %rax,0x28(%rdi);"); } -void _neg(fp* z, const fp* x) +void _negate(fp* z, const fp* x) { - __neg(z, x); + __negate(z, x); // put zero check after __neg because gcc messes up %rdi in -O3 (doesn't restore it before inlining asm code) if(x->isZero()) { @@ -708,7 +708,7 @@ void _neg(fp* z, const fp* x) } } #else -void _neg(fp* z, const fp* x) +void _negate(fp* z, const fp* x) { if(x->isZero()) { @@ -726,7 +726,7 @@ void _neg(fp* z, const fp* x) #endif #ifdef __x86_64__ -void __mul(fp* z, const fp* x, const fp* y) +void __multiply(fp* z, const fp* x, const fp* y) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): // z => %rdi (=> stack) @@ -1796,7 +1796,7 @@ extern "C" blsmul_func_t __attribute__((no_sanitize_address)) resolve_blsmul() { return __mul; } -void _mul(fp*, const fp*, const fp*) __attribute__((ifunc("resolve_blsmul"))); +void _multiply(fp*, const fp*, const fp*) __attribute__((ifunc("resolve_blsmul"))); #else blsmul_func_t _mul = __mul; @@ -1810,7 +1810,7 @@ static bls_mul_init the_bls_mul_init; #endif //__ELF__ #else -void _mul(fp* z, const fp* x, const fp* y) +void _multiply(fp* z, const fp* x, const fp* y) { array t; array c; @@ -1936,16 +1936,16 @@ void _mul(fp* z, const fp* x, const fp* y) void _square(fp* z, const fp* x) { #ifdef __clang__ - // The clang compiler completely optimizes out the _square() function and inlines __mul() wherever + // The clang compiler completely optimizes out the _square() function and inlines __multiply() wherever // it occurs. However, for some reason the compiler forgets that it has to move the third - // parameter ('y') of __mul() into %rdx according to the calling convention. The first two + // parameter ('y') of __multiply() into %rdx according to the calling convention. The first two // parameters, 'z' (%rdi) and 'x' (%rsi), are set properly because they are the exact same as for // __square(). But the third parameter (which sould be 'x' as well) is somehow ignored by the - // clang compiler. So we need to help out by moving it into %rdx before calling __mul(). + // clang compiler. So we need to help out by moving it into %rdx before calling __multiply(). // This is probably a bug in clang! asm("mov %rsi,%rdx;"); #endif - __mul(z, x, x); + __multiply(z, x, x); } #else void _square(fp* z, const fp* x) diff --git a/src/fp.cpp b/src/fp.cpp index 460637b..c3e68db 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -134,21 +134,21 @@ uint64_t fp::mul2() fp fp::toMont() const { fp c; - _mul(&c, this, &R2); + _multiply(&c, this, &R2); return c; } fp fp::fromMont() const { fp c, b = fp({1, 0, 0, 0, 0, 0}); - _mul(&c, this, &b); + _multiply(&c, this, &b); return c; } fp fp::phi() const { fp c; - _mul(&c, this, &glvPhi1); + _multiply(&c, this, &glvPhi1); return c; } @@ -185,14 +185,14 @@ fp fp::inverse() const } else if(u.cmp(v) == 1) { - _lsubAssign(&u, &v); + _lsubtractAssign(&u, &v); u.div2(0); _laddAssign(&r, &s); s.mul2(); } else { - _lsubAssign(&v, &u); + _lsubtractAssign(&v, &u); v.div2(0); _laddAssign(&s, &r); z += r.mul2(); @@ -212,10 +212,10 @@ fp fp::inverse() const if(r.cmp(MODULUS) != -1 || z > 0) { - _lsubAssign(&r, &MODULUS); + _lsubtractAssign(&r, &MODULUS); } u = MODULUS; - _lsubAssign(&u, &r); + _lsubtractAssign(&u, &r); // Phase 2 for(uint64_t i = k; i < 384*2; i++) @@ -489,62 +489,62 @@ fp2 fp2::ldouble() const return c; } -fp2 fp2::sub(const fp2& e) const +fp2 fp2::subtract(const fp2& e) const { fp2 c; - _sub(&c.c0, &c0, &e.c0); - _sub(&c.c1, &c1, &e.c1); + _subtract(&c.c0, &c0, &e.c0); + _subtract(&c.c1, &c1, &e.c1); return c; } -void fp2::subAssign(const fp2& e) +void fp2::subtractAssign(const fp2& e) { - _subAssign(&c0, &e.c0); - _subAssign(&c1, &e.c1); + _subtractAssign(&c0, &e.c0); + _subtractAssign(&c1, &e.c1); } -fp2 fp2::neg() const +fp2 fp2::negate() const { fp2 c; - _neg(&c.c0, &c0); - _neg(&c.c1, &c1); + _negate(&c.c0, &c0); + _negate(&c.c1, &c1); return c; } -fp2 fp2::conj() const +fp2 fp2::conjugate() const { fp2 c; c.c0 = c0; - _neg(&c.c1, &c1); + _negate(&c.c1, &c1); return c; } -fp2 fp2::mul(const fp2& e) const +fp2 fp2::multiply(const fp2& e) const { fp t[4]; fp2 c; - _mul(&t[1], &c0, &e.c0); - _mul(&t[2], &c1, &e.c1); + _multiply(&t[1], &c0, &e.c0); + _multiply(&t[2], &c1, &e.c1); _add(&t[0], &c0, &c1); _add(&t[3], &e.c0, &e.c1); - _sub(&c.c0, &t[1], &t[2]); + _subtract(&c.c0, &t[1], &t[2]); _addAssign(&t[1], &t[2]); - _mul(&t[0], &t[0], &t[3]); - _sub(&c.c1, &t[0], &t[1]); + _multiply(&t[0], &t[0], &t[3]); + _subtract(&c.c1, &t[0], &t[1]); return c; } -void fp2::mulAssign(const fp2& e) +void fp2::multiplyAssign(const fp2& e) { fp t[4]; - _mul(&t[1], &c0, &e.c0); - _mul(&t[2], &c1, &e.c1); + _multiply(&t[1], &c0, &e.c0); + _multiply(&t[2], &c1, &e.c1); _add(&t[0], &c0, &c1); _add(&t[3], &e.c0, &e.c1); - _sub(&c0, &t[1], &t[2]); + _subtract(&c0, &t[1], &t[2]); _addAssign(&t[1], &t[2]); - _mul(&t[0], &t[0], &t[3]); - _sub(&c1, &t[0], &t[1]); + _multiply(&t[0], &t[0], &t[3]); + _subtract(&c1, &t[0], &t[1]); } fp2 fp2::square() const @@ -552,10 +552,10 @@ fp2 fp2::square() const fp t[3]; fp2 c; _ladd(&t[0], &c0, &c1); - _sub(&t[1], &c0, &c1); + _subtract(&t[1], &c0, &c1); _ldouble(&t[2], &c0); - _mul(&c.c0, &t[0], &t[1]); - _mul(&c.c1, &t[2], &c1); + _multiply(&c.c0, &t[0], &t[1]); + _multiply(&c.c1, &t[2], &c1); return c; } @@ -563,17 +563,17 @@ void fp2::squareAssign() { fp t[3]; _ladd(&t[0], &c0, &c1); - _sub(&t[1], &c0, &c1); + _subtract(&t[1], &c0, &c1); _ldouble(&t[2], &c0); - _mul(&c0, &t[0], &t[1]); - _mul(&c1, &t[2], &c1); + _multiply(&c0, &t[0], &t[1]); + _multiply(&c1, &t[2], &c1); } fp2 fp2::mulByNonResidue() const { fp t; fp2 c; - _sub(&t, &c0, &c1); + _subtract(&t, &c0, &c1); _add(&c.c1, &c0, &c1); c.c0 = t; return c; @@ -587,7 +587,7 @@ fp2 fp2::mulByB() const _double(&t[1], &c1); _doubleAssign(&t[0]); _doubleAssign(&t[1]); - _sub(&c.c0, &t[0], &t[1]); + _subtract(&c.c0, &t[0], &t[1]); _add(&c.c1, &t[0], &t[1]); return c; } @@ -600,17 +600,17 @@ fp2 fp2::inverse() const _square(&t[1], &c1); _addAssign(&t[0], &t[1]); t[0] = t[0].inverse(); - _mul(&c.c0, &c0, &t[0]); - _mul(&t[0], &t[0], &c1); - _neg(&c.c1, &t[0]); + _multiply(&c.c0, &c0, &t[0]); + _multiply(&t[0], &t[0], &c1); + _negate(&c.c1, &t[0]); return c; } fp2 fp2::mulByFq(const fp& e) const { fp2 c; - _mul(&c.c0, &c0, &e); - _mul(&c.c1, &c1, &e); + _multiply(&c.c0, &c0, &e); + _multiply(&c.c1, &c1, &e); return c; } @@ -620,7 +620,7 @@ fp2 fp2::frobeniusMap(const uint64_t& power) const c.c0 = c0; if(power%2 == 1) { - _neg(&c.c1, &c1); + _negate(&c.c1, &c1); return c; } c.c1 = c1; @@ -631,7 +631,7 @@ void fp2::frobeniusMapAssign(const uint64_t& power) { if(power%2 == 1) { - _neg(&c1, &c1); + _negate(&c1, &c1); } } @@ -641,17 +641,17 @@ bool fp2::sqrt(fp2& c) const u = *this; a1 = this->exp(fp::pMinus3Over4); alpha = a1.square(); - alpha = alpha.mul(*this); - x0 = a1.mul(*this); + alpha = alpha.multiply(*this); + x0 = a1.multiply(*this); if(alpha.equal(fp2::negativeOne2)) { - _neg(&c.c0, &x0.c1); + _negate(&c.c0, &x0.c1); c.c1 = x0.c0; return true; } alpha = alpha.add(fp2::one()); alpha = alpha.exp(fp::pMinus1Over2); - c = alpha.mul(x0); + c = alpha.multiply(x0); alpha = c.square(); return alpha.equal(u); } @@ -863,87 +863,87 @@ void fp6::doubleAssign() c2.doubleAssign(); } -fp6 fp6::sub(const fp6& e) const +fp6 fp6::subtract(const fp6& e) const { fp6 c; - c.c0 = c0.sub(e.c0); - c.c1 = c1.sub(e.c1); - c.c2 = c2.sub(e.c2); + c.c0 = c0.subtract(e.c0); + c.c1 = c1.subtract(e.c1); + c.c2 = c2.subtract(e.c2); return c; } -void fp6::subAssign(const fp6& e) +void fp6::subtractAssign(const fp6& e) { - c0.subAssign(e.c0); - c1.subAssign(e.c1); - c2.subAssign(e.c2); + c0.subtractAssign(e.c0); + c1.subtractAssign(e.c1); + c2.subtractAssign(e.c2); } -fp6 fp6::neg() const +fp6 fp6::negate() const { fp6 c; - c.c0 = c0.neg(); - c.c1 = c1.neg(); - c.c2 = c2.neg(); + c.c0 = c0.negate(); + c.c1 = c1.negate(); + c.c2 = c2.negate(); return c; } -fp6 fp6::mul(const fp6& e) const +fp6 fp6::multiply(const fp6& e) const { fp2 t[6]; fp6 c; - t[0] = c0.mul(e.c0); - t[1] = c1.mul(e.c1); - t[2] = c2.mul(e.c2); + t[0] = c0.multiply(e.c0); + t[1] = c1.multiply(e.c1); + t[2] = c2.multiply(e.c2); t[3] = c1.add(c2); t[4] = e.c1.add(e.c2); - t[3].mulAssign(t[4]); + t[3].multiplyAssign(t[4]); t[4] = t[1].add(t[2]); - t[3].subAssign(t[4]); + t[3].subtractAssign(t[4]); t[3] = t[3].mulByNonResidue(); t[5] = t[0].add(t[3]); t[3] = c0.add(c1); t[4] = e.c0.add(e.c1); - t[3].mulAssign(t[4]); + t[3].multiplyAssign(t[4]); t[4] = t[0].add(t[1]); - t[3].subAssign(t[4]); + t[3].subtractAssign(t[4]); t[4] = t[2].mulByNonResidue(); c.c1 = t[3].add(t[4]); t[3] = c0.add(c2); t[4] = e.c0.add(e.c2); - t[3].mulAssign(t[4]); + t[3].multiplyAssign(t[4]); t[4] = t[0].add(t[2]); - t[3].subAssign(t[4]); + t[3].subtractAssign(t[4]); c.c2 = t[1].add(t[3]); c.c0 = t[5]; return c; } -void fp6::mulAssign(const fp6& e) +void fp6::multiplyAssign(const fp6& e) { fp2 t[6]; - t[0] = c0.mul(e.c0); - t[1] = c1.mul(e.c1); - t[2] = c2.mul(e.c2); + t[0] = c0.multiply(e.c0); + t[1] = c1.multiply(e.c1); + t[2] = c2.multiply(e.c2); t[3] = c1.add(c2); t[4] = e.c1.add(e.c2); - t[3].mulAssign(t[4]); + t[3].multiplyAssign(t[4]); t[4] = t[1].add(t[2]); - t[3].subAssign(t[4]); + t[3].subtractAssign(t[4]); t[3] = t[3].mulByNonResidue(); t[5] = t[0].add(t[3]); t[3] = c0.add(c1); t[4] = e.c0.add(e.c1); - t[3].mulAssign(t[4]); + t[3].multiplyAssign(t[4]); t[4] = t[0].add(t[1]); - t[3].subAssign(t[4]); + t[3].subtractAssign(t[4]); t[4] = t[2].mulByNonResidue(); c1 = t[3].add(t[4]); t[3] = c0.add(c2); t[4] = e.c0.add(e.c2); - t[3].mulAssign(t[4]); + t[3].multiplyAssign(t[4]); t[4] = t[0].add(t[2]); - t[3].subAssign(t[4]); + t[3].subtractAssign(t[4]); c2 = t[1].add(t[3]); c0 = t[5]; } @@ -953,12 +953,12 @@ fp6 fp6::square() const fp2 t[6]; fp6 c; t[0] = c0.square(); - t[1] = c0.mul(c1); + t[1] = c0.multiply(c1); t[1].doubleAssign(); - t[2] = c0.sub(c1); + t[2] = c0.subtract(c1); t[2].addAssign(c2); t[2].squareAssign(); - t[3] = c1.mul(c2); + t[3] = c1.multiply(c2); t[3].doubleAssign(); t[4] = c2.square(); t[5] = t[3].mulByNonResidue(); @@ -968,28 +968,28 @@ fp6 fp6::square() const t[1].addAssign(t[2]); t[1].addAssign(t[3]); t[0].addAssign(t[4]); - c.c2 = t[1].sub(t[0]); + c.c2 = t[1].subtract(t[0]); return c; } void fp6::mulBy01Assign(const fp2& e0, const fp2& e1) { fp2 t[6]; - t[0] = c0.mul(e0); - t[1] = c1.mul(e1); + t[0] = c0.multiply(e0); + t[1] = c1.multiply(e1); t[5] = c1.add(c2); - t[2] = e1.mul(t[5]); - t[2].subAssign(t[1]); + t[2] = e1.multiply(t[5]); + t[2].subtractAssign(t[1]); t[2] = t[2].mulByNonResidue(); t[5] = c0.add(c2); - t[3] = e0.mul(t[5]); - t[3].subAssign(t[0]); + t[3] = e0.multiply(t[5]); + t[3].subtractAssign(t[0]); c2 = t[3].add(t[1]); t[4] = e0.add(e1); t[5] = c0.add(c1); - t[4].mulAssign(t[5]); - t[4].subAssign(t[0]); - c1 = t[4].sub(t[1]); + t[4].multiplyAssign(t[5]); + t[4].subtractAssign(t[0]); + c1 = t[4].subtract(t[1]); c0 = t[2].add(t[0]); } @@ -997,21 +997,21 @@ fp6 fp6::mulBy01(const fp2& e0, const fp2& e1) const { fp2 t[5]; fp6 c; - t[0] = c0.mul(e0); - t[1] = c1.mul(e1); + t[0] = c0.multiply(e0); + t[1] = c1.multiply(e1); t[2] = c1.add(c2); - t[2].mulAssign(e1); - t[2].subAssign(t[1]); + t[2].multiplyAssign(e1); + t[2].subtractAssign(t[1]); t[2] = t[2].mulByNonResidue(); t[3] = c0.add(c2); - t[3].mulAssign(e0); - t[3].subAssign(t[0]); + t[3].multiplyAssign(e0); + t[3].subtractAssign(t[0]); c.c2 = t[3].add(t[1]); t[4] = e0.add(e1); t[3] = c0.add(c1); - t[4].mulAssign(t[3]); - t[4].subAssign(t[0]); - c.c1 = t[4].sub(t[1]); + t[4].multiplyAssign(t[3]); + t[4].subtractAssign(t[0]); + c.c1 = t[4].subtract(t[1]); c.c0 = t[2].add(t[0]); return c; } @@ -1020,9 +1020,9 @@ fp6 fp6::mulBy1(const fp2& e1) const { fp2 t; fp6 c; - t = c2.mul(e1); - c.c2 = c1.mul(e1); - c.c1 = c0.mul(e1); + t = c2.multiply(e1); + c.c2 = c1.multiply(e1); + c.c1 = c0.multiply(e1); c.c0 = t.mulByNonResidue(); return c; } @@ -1039,9 +1039,9 @@ fp6 fp6::mulByNonResidue() const fp6 fp6::mulByBaseField(const fp2& e) const { fp6 c; - c.c0 = c0.mul(e); - c.c1 = c1.mul(e); - c.c2 = c2.mul(e); + c.c0 = c0.multiply(e); + c.c1 = c1.multiply(e); + c.c2 = c2.multiply(e); return c; } @@ -1050,26 +1050,26 @@ fp6 fp6::inverse() const fp2 t[5]; fp6 c; t[0] = c0.square(); - t[1] = c1.mul(c2); + t[1] = c1.multiply(c2); t[1] = t[1].mulByNonResidue(); - t[0].subAssign(t[1]); + t[0].subtractAssign(t[1]); t[1] = c1.square(); - t[2] = c0.mul(c2); - t[1].subAssign(t[2]); + t[2] = c0.multiply(c2); + t[1].subtractAssign(t[2]); t[2] = c2.square(); t[2] = t[2].mulByNonResidue(); - t[3] = c0.mul(c1); - t[2].subAssign(t[3]); - t[3] = c2.mul(t[2]); - t[4] = c1.mul(t[1]); + t[3] = c0.multiply(c1); + t[2].subtractAssign(t[3]); + t[3] = c2.multiply(t[2]); + t[4] = c1.multiply(t[1]); t[3].addAssign(t[4]); t[3] = t[3].mulByNonResidue(); - t[4] = c0.mul(t[0]); + t[4] = c0.multiply(t[0]); t[3].addAssign(t[4]); t[3] = t[3].inverse(); - c.c0 = t[0].mul(t[3]); - c.c1 = t[2].mul(t[3]); - c.c2 = t[1].mul(t[3]); + c.c0 = t[0].multiply(t[3]); + c.c1 = t[2].multiply(t[3]); + c.c2 = t[1].multiply(t[3]); return c; } @@ -1087,15 +1087,15 @@ fp6 fp6::frobeniusMap(const uint64_t& power) const } case 3: { - _neg(&c.c0.c0, &c1.c1); + _negate(&c.c0.c0, &c1.c1); c.c1.c1 = c1.c0; - c.c2 = c2.neg(); + c.c2 = c2.negate(); break; } default: { - c.c1 = c.c1.mul(frobeniusCoeffs61[power%6]); - c.c2 = c.c2.mul(frobeniusCoeffs62[power%6]); + c.c1 = c.c1.multiply(frobeniusCoeffs61[power%6]); + c.c2 = c.c2.multiply(frobeniusCoeffs62[power%6]); break; } } @@ -1116,16 +1116,16 @@ void fp6::frobeniusMapAssign(const uint64_t& power) } case 3: { - _neg(&t.c0, &c1.c1); + _negate(&t.c0, &c1.c1); c1.c1 = c1.c0; c1.c0 = t.c0; - c2 = c2.neg(); + c2 = c2.negate(); break; } default: { - c1.mulAssign(frobeniusCoeffs61[power%6]); - c2.mulAssign(frobeniusCoeffs62[power%6]); + c1.multiplyAssign(frobeniusCoeffs61[power%6]); + c2.multiplyAssign(frobeniusCoeffs62[power%6]); break; } } @@ -1286,19 +1286,19 @@ fp12 fp12::dbl() const return c; } -fp12 fp12::sub(const fp12& e) const +fp12 fp12::subtract(const fp12& e) const { fp12 c; - c.c0 = c0.sub(e.c0); - c.c1 = c1.sub(e.c1); + c.c0 = c0.subtract(e.c0); + c.c1 = c1.subtract(e.c1); return c; } -fp12 fp12::neg() const +fp12 fp12::negate() const { fp12 c; - c.c0 = c0.neg(); - c.c1 = c1.neg(); + c.c0 = c0.negate(); + c.c1 = c1.negate(); return c; } @@ -1306,7 +1306,7 @@ fp12 fp12::conjugate() const { fp12 c; c.c0 = c0; - c.c1 = c1.neg(); + c.c1 = c1.negate(); return c; } @@ -1315,13 +1315,13 @@ fp12 fp12::square() const fp6 t[4]; fp12 c; t[0] = c0.add(c1); - t[2] = c0.mul(c1); + t[2] = c0.multiply(c1); t[1] = c1.mulByNonResidue(); t[1].addAssign(c0); t[3] = t[2].mulByNonResidue(); - t[0].mulAssign(t[1]); - t[0].subAssign(t[2]); - c.c0 = t[0].sub(t[3]); + t[0].multiplyAssign(t[1]); + t[0].subtractAssign(t[2]); + c.c0 = t[0].subtract(t[3]); c.c1 = t[2].dbl(); return c; } @@ -1331,7 +1331,7 @@ fp12 fp12::cyclotomicSquare() const fp2 t[7]; fp12 c; tie(t[3], t[4]) = fp4Square(c0.c0, c1.c1); - t[2] = t[3].sub(c0.c0); + t[2] = t[3].subtract(c0.c0); t[2].doubleAssign(); c.c0.c0 = t[2].add(t[3]); t[2] = t[4].add(c1.c1); @@ -1339,7 +1339,7 @@ fp12 fp12::cyclotomicSquare() const c.c1.c1 = t[2].add(t[4]); tie(t[3], t[4]) = fp4Square(c1.c0, c0.c2); tie(t[5], t[6]) = fp4Square(c0.c1, c1.c2); - t[2] = t[3].sub(c0.c1); + t[2] = t[3].subtract(c0.c1); t[2].doubleAssign(); c.c0.c1 = t[2].add(t[3]); t[2] = t[4].add(c1.c2); @@ -1349,42 +1349,42 @@ fp12 fp12::cyclotomicSquare() const t[2] = t[3].add(c1.c0); t[2].doubleAssign(); c.c1.c0 = t[2].add(t[3]); - t[2] = t[5].sub(c0.c2); + t[2] = t[5].subtract(c0.c2); t[2].doubleAssign(); c.c0.c2 = t[2].add(t[5]); return c; } -fp12 fp12::mul(const fp12& e) const +fp12 fp12::multiply(const fp12& e) const { fp6 t[4]; fp12 c; - t[1] = c0.mul(e.c0); - t[2] = c1.mul(e.c1); + t[1] = c0.multiply(e.c0); + t[2] = c1.multiply(e.c1); t[0] = t[1].add(t[2]); t[2] = t[2].mulByNonResidue(); t[3] = t[1].add(t[2]); t[1] = c0.add(c1); t[2] = e.c0.add(e.c1); - t[1].mulAssign(t[2]); + t[1].multiplyAssign(t[2]); c.c0 = t[3]; - c.c1 = t[1].sub(t[0]); + c.c1 = t[1].subtract(t[0]); return c; } -void fp12::mulAssign(const fp12& e) +void fp12::multiplyAssign(const fp12& e) { fp6 t[4]; - t[1] = c0.mul(e.c0); - t[2] = c1.mul(e.c1); + t[1] = c0.multiply(e.c0); + t[2] = c1.multiply(e.c1); t[0] = t[1].add(t[2]); t[2] = t[2].mulByNonResidue(); t[3] = t[1].add(t[2]); t[1] = c0.add(c1); t[2] = e.c0.add(e.c1); - t[1].mulAssign(t[2]); + t[1].multiplyAssign(t[2]); c0 = t[3]; - c1 = t[1].sub(t[0]); + c1 = t[1].subtract(t[0]); } tuple fp12::fp4Square(const fp2& e0, const fp2& e1) @@ -1397,8 +1397,8 @@ tuple fp12::fp4Square(const fp2& e0, const fp2& e1) c0 = t[2].add(t[0]); t[2] = e0.add(e1); t[2].squareAssign(); - t[2].subAssign(t[0]); - c1 = t[2].sub(t[1]); + t[2].subtractAssign(t[0]); + c1 = t[2].subtract(t[1]); return {c0, c1}; } @@ -1409,11 +1409,11 @@ fp12 fp12::inverse() const t[0] = c0.square(); t[1] = c1.square(); t[1] = t[1].mulByNonResidue(); - t[1] = t[0].sub(t[1]); + t[1] = t[0].subtract(t[1]); t[0] = t[1].inverse(); - c.c0 = c0.mul(t[0]); - t[0].mulAssign(c1); - c.c1 = t[0].neg(); + c.c0 = c0.multiply(t[0]); + t[0].multiplyAssign(c1); + c.c1 = t[0].negate(); return c; } @@ -1426,8 +1426,8 @@ void fp12::mulBy014Assign(const fp2& e0, const fp2& e1, const fp2& e4) t2 = e1.add(e4); t[2] = c1.add(c0); t[2].mulBy01Assign(e0, t2); - t[2].subAssign(t[0]); - c1 = t[2].sub(t[1]); + t[2].subtractAssign(t[0]); + c1 = t[2].subtract(t[1]); t[1] = t[1].mulByNonResidue(); c0 = t[1].add(t[0]); } @@ -1445,7 +1445,7 @@ fp12 fp12::frobeniusMap(const uint64_t& power) const } case 6: { - c.c1 = c.c1.neg(); + c.c1 = c.c1.negate(); break; } default: @@ -1469,7 +1469,7 @@ void fp12::frobeniusMapAssign(const uint64_t& power) } case 6: { - c1 = c1.neg(); + c1 = c1.negate(); break; } default: diff --git a/src/g.cpp b/src/g.cpp index 192a997..bcba814 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -111,7 +111,7 @@ optional g1::fromCompressedBytesBE(const span in) // => y = +/- sqrt(x^3 + B) fp b = fp::B; _square(&p.y, &p.x); // y = x^2 - _mul(&p.y, &p.y, &p.x); // y = x^2 * x = x^3 + _multiply(&p.y, &p.y, &p.x); // y = x^2 * x = x^3 _add(&p.y, &p.y, &b); // y = x^3 + B if(!p.y.sqrt(p.y)) { @@ -119,7 +119,7 @@ optional g1::fromCompressedBytesBE(const span in) } if(p.y.isLexicographicallyLargest() ^ ysign) { - _neg(&p.y, &p.y); + _negate(&p.y, &p.y); } p.z = fp::one(); return p; @@ -252,12 +252,12 @@ bool g1::equal(const g1& e) const fp t[4]; _square(&t[0], &z); _square(&t[1], &b.z); - _mul(&t[2], &t[0], &b.x); - _mul(&t[3], &t[1], &x); - _mul(&t[0], &t[0], &z); - _mul(&t[1], &t[1], &b.z); - _mul(&t[1], &t[1], &y); - _mul(&t[0], &t[0], &b.y); + _multiply(&t[2], &t[0], &b.x); + _multiply(&t[3], &t[1], &x); + _multiply(&t[0], &t[0], &z); + _multiply(&t[1], &t[1], &b.z); + _multiply(&t[1], &t[1], &y); + _multiply(&t[0], &t[0], &b.y); return t[0].equal(t[1]) && t[2].equal(t[3]); } @@ -270,10 +270,10 @@ bool g1::inCorrectSubgroup() const g1 t1 = t0; t0 = t0.glvEndomorphism(); t1 = t1.dbl(); - t1 = t1.sub(*this); - t1 = t1.sub(t0); + t1 = t1.subtract(*this); + t1 = t1.subtract(t0); t1 = t1.scale<2>({0x0000000055555555, 0x396c8c005555e156}); - t1 = t1.sub(t0); + t1 = t1.subtract(t0); return t1.isZero(); } @@ -286,11 +286,11 @@ bool g1::isOnCurve() const fp t[4], _b = fp::B; _square(&t[0], &y); _square(&t[1], &x); - _mul(&t[1], &t[1], &x); + _multiply(&t[1], &t[1], &x); _square(&t[2], &z); _square(&t[3], &t[2]); - _mul(&t[2], &t[2], &t[3]); - _mul(&t[2], &_b, &t[2]); + _multiply(&t[2], &t[2], &t[3]); + _multiply(&t[2], &_b, &t[2]); _add(&t[1], &t[1], &t[2]); return t[0].equal(t[1]); } @@ -310,9 +310,9 @@ g1 g1::affine() const fp t[2]; t[0] = r.z.inverse(); _square(&t[1], &t[0]); - _mul(&r.x, &r.x, &t[1]); - _mul(&t[0], &t[0], &t[1]); - _mul(&r.y, &r.y, &t[0]); + _multiply(&r.x, &r.x, &t[1]); + _multiply(&t[0], &t[0], &t[1]); + _multiply(&r.y, &r.y, &t[0]); r.z = fp::one(); return r; } @@ -330,13 +330,13 @@ g1 g1::add(const g1& e) const } fp t[9]; _square(&t[7], &z); - _mul(&t[1], &e.x, &t[7]); - _mul(&t[2], &z, &t[7]); - _mul(&t[0], &e.y, &t[2]); + _multiply(&t[1], &e.x, &t[7]); + _multiply(&t[2], &z, &t[7]); + _multiply(&t[0], &e.y, &t[2]); _square(&t[8], &e.z); - _mul(&t[3], &x, &t[8]); - _mul(&t[4], &e.z, &t[8]); - _mul(&t[2], &y, &t[4]); + _multiply(&t[3], &x, &t[8]); + _multiply(&t[4], &e.z, &t[8]); + _multiply(&t[2], &y, &t[4]); if(t[1].equal(t[3])) { if(t[0].equal(t[2])) @@ -346,27 +346,27 @@ g1 g1::add(const g1& e) const return zero(); } g1 r; - _sub(&t[1], &t[1], &t[3]); + _subtract(&t[1], &t[1], &t[3]); _double(&t[4], &t[1]); _square(&t[4], &t[4]); - _mul(&t[5], &t[1], &t[4]); - _sub(&t[0], &t[0], &t[2]); + _multiply(&t[5], &t[1], &t[4]); + _subtract(&t[0], &t[0], &t[2]); _double(&t[0], &t[0]); _square(&t[6], &t[0]); - _sub(&t[6], &t[6], &t[5]); - _mul(&t[3], &t[3], &t[4]); + _subtract(&t[6], &t[6], &t[5]); + _multiply(&t[3], &t[3], &t[4]); _double(&t[4], &t[3]); - _sub(&r.x, &t[6], &t[4]); - _sub(&t[4], &t[3], &r.x); - _mul(&t[6], &t[2], &t[5]); + _subtract(&r.x, &t[6], &t[4]); + _subtract(&t[4], &t[3], &r.x); + _multiply(&t[6], &t[2], &t[5]); _double(&t[6], &t[6]); - _mul(&t[0], &t[0], &t[4]); - _sub(&r.y, &t[0], &t[6]); + _multiply(&t[0], &t[0], &t[4]); + _subtract(&r.y, &t[0], &t[6]); _add(&t[0], &z, &e.z); _square(&t[0], &t[0]); - _sub(&t[0], &t[0], &t[7]); - _sub(&t[0], &t[0], &t[8]); - _mul(&r.z, &t[0], &t[1]); + _subtract(&t[0], &t[0], &t[7]); + _subtract(&t[0], &t[0], &t[8]); + _multiply(&r.z, &t[0], &t[1]); return r; } @@ -384,39 +384,39 @@ g1 g1::dbl() const _square(&t[2], &t[1]); _add(&t[1], &x, &t[1]); _square(&t[1], &t[1]); - _sub(&t[1], &t[1], &t[0]); - _sub(&t[1], &t[1], &t[2]); + _subtract(&t[1], &t[1], &t[0]); + _subtract(&t[1], &t[1], &t[2]); _double(&t[1], &t[1]); _double(&t[3], &t[0]); _add(&t[0], &t[3], &t[0]); _square(&t[4], &t[0]); _double(&t[3], &t[1]); - _sub(&r.x, &t[4], &t[3]); - _sub(&t[1], &t[1], &r.x); + _subtract(&r.x, &t[4], &t[3]); + _subtract(&t[1], &t[1], &r.x); _double(&t[2], &t[2]); _double(&t[2], &t[2]); _double(&t[2], &t[2]); - _mul(&t[0], &t[0], &t[1]); - _sub(&t[1], &t[0], &t[2]); - _mul(&t[0], &y, &z); + _multiply(&t[0], &t[0], &t[1]); + _subtract(&t[1], &t[0], &t[2]); + _multiply(&t[0], &y, &z); r.y = t[1]; _double(&r.z, &t[0]); return r; } -g1 g1::neg() const +g1 g1::negate() const { g1 r; r.x = x; r.z = z; - _neg(&r.y, &y); + _negate(&r.y, &y); return r; } -g1 g1::sub(const g1& e) const +g1 g1::subtract(const g1& e) const { g1 c, d; - d = e.neg(); + d = e.negate(); c = this->add(d); return c; } @@ -530,7 +530,7 @@ tuple g1::swuMapG1(const fp& e) }; fp tv[4]; _square(&tv[0], &e); - _mul(&tv[0], &tv[0], ¶ms.z); + _multiply(&tv[0], &tv[0], ¶ms.z); _square(&tv[1], &tv[0]); fp x1; _add(&x1, &tv[0], &tv[1]); @@ -542,17 +542,17 @@ tuple g1::swuMapG1(const fp& e) { x1 = params.zInv; } - _mul(&x1, &x1, ¶ms.minusBOverA); + _multiply(&x1, &x1, ¶ms.minusBOverA); fp gx1; _square(&gx1, &x1); _add(&gx1, &gx1, ¶ms.a); - _mul(&gx1, &gx1, &x1); + _multiply(&gx1, &gx1, &x1); _add(&gx1, &gx1, ¶ms.b); fp x2; - _mul(&x2, &tv[0], &x1); - _mul(&tv[1], &tv[0], &tv[1]); + _multiply(&x2, &tv[0], &x1); + _multiply(&tv[1], &tv[0], &tv[1]); fp gx2; - _mul(&gx2, &gx1, &tv[1]); + _multiply(&gx2, &gx1, &tv[1]); bool e2 = !gx1.isQuadraticNonResidue(); fp x, y2; if(e2) @@ -569,7 +569,7 @@ tuple g1::swuMapG1(const fp& e) y2.sqrt(y); if(y.sign() != e.sign()) { - _neg(&y, &y); + _negate(&y, &y); } return {x, y}; } @@ -660,10 +660,10 @@ void g1::isogenyMapG1(fp& x, fp& y) yDen = params[3][degree]; for(int64_t i = degree - 1; i >= 0; i--) { - _mul(&xNum, &xNum, &x); - _mul(&xDen, &xDen, &x); - _mul(&yNum, &yNum, &x); - _mul(&yDen, &yDen, &x); + _multiply(&xNum, &xNum, &x); + _multiply(&xDen, &xDen, &x); + _multiply(&yNum, &yNum, &x); + _multiply(&yDen, &yDen, &x); _add(&xNum, &xNum, ¶ms[0][i]); _add(&xDen, &xDen, ¶ms[1][i]); _add(&yNum, &yNum, ¶ms[2][i]); @@ -671,9 +671,9 @@ void g1::isogenyMapG1(fp& x, fp& y) } xDen = xDen.inverse(); yDen = yDen.inverse(); - _mul(&xNum, &xNum, &xDen); - _mul(&yNum, &yNum, &yDen); - _mul(&yNum, &yNum, &y); + _multiply(&xNum, &xNum, &xDen); + _multiply(&yNum, &yNum, &yDen); + _multiply(&yNum, &yNum, &y); x = xNum; y = yNum; } @@ -797,7 +797,7 @@ optional g2::fromCompressedBytesBE(const span in) // => y = +/- sqrt(x^3 + B) fp2 b = fp2::B; p.y = p.x.square(); // y = x^2 - p.y = p.y.mul(p.x); // y = x^2 * x = x^3 + p.y = p.y.multiply(p.x); // y = x^2 * x = x^3 p.y = p.y.add(b); // y = x^3 + B if(!p.y.sqrt(p.y)) { @@ -805,7 +805,7 @@ optional g2::fromCompressedBytesBE(const span in) } if(p.y.isLexicographicallyLargest() ^ ysign) { - p.y = p.y.neg(); + p.y = p.y.negate(); } p.z = fp2::one(); return p; @@ -938,12 +938,12 @@ bool g2::equal(const g2& e) const fp2 t[9]; t[0] = z.square(); t[1] = e.z.square(); - t[2] = t[0].mul(e.x); - t[3] = t[1].mul(x); - t[0] = t[0].mul(z); - t[1] = t[1].mul(e.z); - t[1] = t[1].mul(y); - t[0] = t[0].mul(e.y); + t[2] = t[0].multiply(e.x); + t[3] = t[1].multiply(x); + t[0] = t[0].multiply(z); + t[1] = t[1].multiply(e.z); + t[1] = t[1].multiply(y); + t[0] = t[0].multiply(e.y); return t[0].equal(t[1]) && t[2].equal(t[3]); } @@ -955,10 +955,10 @@ bool g2::inCorrectSubgroup() const g2 t0, t1; t0 = this->psi(); t0 = t0.psi(); - t1 = t0.neg(); // - ψ^2(P) + t1 = t0.negate(); // - ψ^2(P) t0 = t0.psi(); // ψ^3(P) t0 = t0.scale(cofactorEFF); // - x ψ^3(P) - t0 = t0.neg(); + t0 = t0.negate(); t0 = t0.add(t1); t0 = t0.add(*this); @@ -975,11 +975,11 @@ bool g2::isOnCurve() const fp2 t[9]; t[0] = y.square(); t[1] = x.square(); - t[1] = t[1].mul(x); + t[1] = t[1].multiply(x); t[2] = z.square(); t[3] = t[2].square(); - t[2] = t[2].mul(t[3]); - t[2] = fp2::B.mul(t[2]); + t[2] = t[2].multiply(t[3]); + t[2] = fp2::B.multiply(t[2]); t[1] = t[1].add(t[2]); return t[0].equal(t[1]); } @@ -999,9 +999,9 @@ g2 g2::affine() const fp2 t[9]; t[0] = r.z.inverse(); t[1] = t[0].square(); - r.x = r.x.mul(t[1]); - t[0] = t[0].mul(t[1]); - r.y = r.y.mul(t[0]); + r.x = r.x.multiply(t[1]); + t[0] = t[0].multiply(t[1]); + r.y = r.y.multiply(t[0]); r.z = fp2::one(); return r; } @@ -1019,13 +1019,13 @@ g2 g2::add(const g2& e) const } fp2 t[9]; t[7] = z.square(); - t[1] = e.x.mul(t[7]); - t[2] = z.mul(t[7]); - t[0] = e.y.mul(t[2]); + t[1] = e.x.multiply(t[7]); + t[2] = z.multiply(t[7]); + t[0] = e.y.multiply(t[2]); t[8] = e.z.square(); - t[3] = x.mul(t[8]); - t[4] = e.z.mul(t[8]); - t[2] = y.mul(t[4]); + t[3] = x.multiply(t[8]); + t[4] = e.z.multiply(t[8]); + t[2] = y.multiply(t[4]); if(t[1].equal(t[3])) { if(t[0].equal(t[2])) @@ -1035,27 +1035,27 @@ g2 g2::add(const g2& e) const return zero(); } g2 r; - t[1] = t[1].sub(t[3]); + t[1] = t[1].subtract(t[3]); t[4] = t[1].dbl(); t[4] = t[4].square(); - t[5] = t[1].mul(t[4]); - t[0] = t[0].sub(t[2]); + t[5] = t[1].multiply(t[4]); + t[0] = t[0].subtract(t[2]); t[0] = t[0].dbl(); t[6] = t[0].square(); - t[6] = t[6].sub(t[5]); - t[3] = t[3].mul(t[4]); + t[6] = t[6].subtract(t[5]); + t[3] = t[3].multiply(t[4]); t[4] = t[3].dbl(); - r.x = t[6].sub(t[4]); - t[4] = t[3].sub(r.x); - t[6] = t[2].mul(t[5]); + r.x = t[6].subtract(t[4]); + t[4] = t[3].subtract(r.x); + t[6] = t[2].multiply(t[5]); t[6] = t[6].dbl(); - t[0] = t[0].mul(t[4]); - r.y = t[0].sub(t[6]); + t[0] = t[0].multiply(t[4]); + r.y = t[0].subtract(t[6]); t[0] = z.add(e.z); t[0] = t[0].square(); - t[0] = t[0].sub(t[7]); - t[0] = t[0].sub(t[8]); - r.z = t[0].mul(t[1]); + t[0] = t[0].subtract(t[7]); + t[0] = t[0].subtract(t[8]); + r.z = t[0].multiply(t[1]); return r; } @@ -1073,39 +1073,39 @@ g2 g2::dbl() const t[2] = t[1].square(); t[1] = x.add(t[1]); t[1] = t[1].square(); - t[1] = t[1].sub(t[0]); - t[1] = t[1].sub(t[2]); + t[1] = t[1].subtract(t[0]); + t[1] = t[1].subtract(t[2]); t[1] = t[1].dbl(); t[3] = t[0].dbl(); t[0] = t[3].add(t[0]); t[4] = t[0].square(); t[3] = t[1].dbl(); - r.x = t[4].sub(t[3]); - t[1] = t[1].sub(r.x); + r.x = t[4].subtract(t[3]); + t[1] = t[1].subtract(r.x); t[2] = t[2].dbl(); t[2] = t[2].dbl(); t[2] = t[2].dbl(); - t[0] = t[0].mul(t[1]); - t[1] = t[0].sub(t[2]); - t[0] = y.mul(z); + t[0] = t[0].multiply(t[1]); + t[1] = t[0].subtract(t[2]); + t[0] = y.multiply(z); r.y = t[1]; r.z = t[0].dbl(); return r; } -g2 g2::neg() const +g2 g2::negate() const { g2 r; r.x = x; - r.y = y.neg(); + r.y = y.negate(); r.z = z; return r; } -g2 g2::sub(const g2& e) const +g2 g2::subtract(const g2& e) const { g2 c, d; - d = e.neg(); + d = e.negate(); c = this->add(d); return c; } @@ -1113,11 +1113,11 @@ g2 g2::sub(const g2& e) const g2 g2::psi() const { g2 p; - p.x = this->x.conj(); - p.y = this->y.conj(); - p.z = this->z.conj(); - p.x = p.x.mul(fp2::psiX); - p.y = p.y.mul(fp2::psiY); + p.x = this->x.conjugate(); + p.y = this->y.conjugate(); + p.z = this->z.conjugate(); + p.x = p.x.multiply(fp2::psiX); + p.y = p.y.multiply(fp2::psiY); return p; } @@ -1127,17 +1127,17 @@ g2 g2::clearCofactor() const // Compute t0 = xP t0 = scale(cofactorEFF); // cofactorEFF has the MSB set, so relic has the sign bit set and negates the y coordinate - t0 = t0.neg(); + t0 = t0.negate(); // Compute t1 = [x^2]P t1 = t0.scale(cofactorEFF); // cofactorEFF has the MSB set, so relic has the sign bit set and negates the y coordinate - t1 = t1.neg(); + t1 = t1.negate(); // t2 = (x^2 - x - 1)P = x^2P - x*P - P - t2 = t1.sub(t0); - t2 = t2.sub(*this); + t2 = t1.subtract(t0); + t2 = t2.subtract(*this); // t3 = \psi(x - 1)P - t3 = t0.sub(*this); + t3 = t0.subtract(*this); t3 = t3.frobeniusMap(1); t2 = t2.add(t3); // t3 = \psi^2(2P) @@ -1163,8 +1163,8 @@ g2 g2::frobeniusMap(int64_t power) const r.x.frobeniusMapAssign(1); r.y.frobeniusMapAssign(1); r.z.frobeniusMapAssign(1); - r.x = r.x.mul(frb0); - r.y = r.y.mul(frb1); + r.x = r.x.multiply(frb0); + r.y = r.y.multiply(frb1); } return r; } @@ -1277,7 +1277,7 @@ tuple g2::swuMapG2(const fp2& e) }; fp2 tv[4]; tv[0] = e.square(); - tv[0] = tv[0].mul(params.z); + tv[0] = tv[0].multiply(params.z); tv[1] = tv[0].square(); fp2 x1; x1 = tv[0].add(tv[1]); @@ -1288,17 +1288,17 @@ tuple g2::swuMapG2(const fp2& e) { x1 = params.zInv; } - x1 = x1.mul(params.minusBOverA); + x1 = x1.multiply(params.minusBOverA); fp2 gx1; gx1 = x1.square(); gx1 = gx1.add(params.a); - gx1 = gx1.mul(x1); + gx1 = gx1.multiply(x1); gx1 = gx1.add(params.b); fp2 x2; - x2 = tv[0].mul(x1); - tv[1] = tv[0].mul(tv[1]); + x2 = tv[0].multiply(x1); + tv[1] = tv[0].multiply(tv[1]); fp2 gx2; - gx2 = gx1.mul(tv[1]); + gx2 = gx1.multiply(tv[1]); bool e2 = !gx1.isQuadraticNonResidue(); fp2 x, y2; if(e2) @@ -1315,7 +1315,7 @@ tuple g2::swuMapG2(const fp2& e) y2.sqrt(y); if(y.sign() != e.sign()) { - y = y.neg(); + y = y.negate(); } return {x, y}; } @@ -1405,10 +1405,10 @@ void g2::isogenyMapG2(fp2& x, fp2& y) fp2 yDen = params[3][degree]; for(int64_t i = degree - 1; i >= 0; i--) { - xNum = xNum.mul(x); - xDen = xDen.mul(x); - yNum = yNum.mul(x); - yDen = yDen.mul(x); + xNum = xNum.multiply(x); + xDen = xDen.multiply(x); + yNum = yNum.multiply(x); + yDen = yDen.multiply(x); xNum = xNum.add(params[0][i]); xDen = xDen.add(params[1][i]); yNum = yNum.add(params[2][i]); @@ -1416,9 +1416,9 @@ void g2::isogenyMapG2(fp2& x, fp2& y) } xDen = xDen.inverse(); yDen = yDen.inverse(); - xNum = xNum.mul(xDen); - yNum = yNum.mul(yDen); - yNum = yNum.mul(y); + xNum = xNum.multiply(xDen); + yNum = yNum.multiply(yDen); + yNum = yNum.multiply(y); x = xNum; y = yNum; } @@ -1507,38 +1507,38 @@ g2 g2::isogenyMap() const t0 = params[0][3]; for(int i = 3; i > 0; --i) { - t0 = t0.mul(x); + t0 = t0.multiply(x); t0 = t0.add(params[0][i - 1]); } t1 = params[2][3]; for(int i = 3; i > 0; --i) { - t1 = t1.mul(x); + t1 = t1.multiply(x); t1 = t1.add(params[2][i - 1]); } t2 = params[3][3]; for(int i = 3; i > 0; --i) { - t2 = t2.mul(x); + t2 = t2.multiply(x); t2 = t2.add(params[3][i - 1]); } t3 = params[1][2]; for(int i = 2; i > 0; --i) { - t3 = t3.mul(x); + t3 = t3.multiply(x); t3 = t3.add(params[1][i - 1]); } // Y = Ny * Dx * Z^2. - q.y = y.mul(t1); - q.y = q.y.mul(t3); + q.y = y.multiply(t1); + q.y = q.y.multiply(t3); // Z = Dx * Dy, t1 = Z^2. - q.z = t2.mul(t3); + q.z = t2.multiply(t3); t1 = q.z.square(); - q.y = q.y.mul(t1); + q.y = q.y.multiply(t1); // X = Nx * Dy * Z. - q.x = t0.mul(t2); - q.x = q.x.mul(q.z); + q.x = t0.multiply(t2); + q.x = q.x.multiply(q.z); return q; } diff --git a/src/pairing.cpp b/src/pairing.cpp index 4a412a2..efff18e 100644 --- a/src/pairing.cpp +++ b/src/pairing.cpp @@ -11,7 +11,7 @@ void doubling_step(array& coeff, g2& r) { // Adaptation of Formula 3 in https://eprint.iacr.org/2010/526.pdf fp2 t[10]; - t[0] = r.x.mul(r.y); + t[0] = r.x.multiply(r.y); t[0] = t[0].mulByFq(fp::twoInv); t[1] = r.y.square(); t[2] = r.z.square(); @@ -25,50 +25,50 @@ void doubling_step(array& coeff, g2& r) t[6] = r.y.add(r.z); t[6] = t[6].square(); t[7] = t[2].add(t[1]); - t[6] = t[6].sub(t[7]); - coeff[0] = t[3].sub(t[1]); + t[6] = t[6].subtract(t[7]); + coeff[0] = t[3].subtract(t[1]); t[7] = r.x.square(); - t[4] = t[1].sub(t[4]); - r.x = t[4].mul(t[0]); + t[4] = t[1].subtract(t[4]); + r.x = t[4].multiply(t[0]); t[2] = t[3].square(); t[3] = t[2].dbl(); t[3] = t[3].add(t[2]); t[5] = t[5].square(); - r.y = t[5].sub(t[3]); - r.z = t[1].mul(t[6]); + r.y = t[5].subtract(t[3]); + r.z = t[1].multiply(t[6]); t[0] = t[7].dbl(); coeff[1] = t[0].add(t[7]); - coeff[2] = t[6].neg(); + coeff[2] = t[6].negate(); } void addition_step(array& coeff, g2& r, g2& tp) { // Algorithm 12 in https://eprint.iacr.org/2010/526.pdf fp2 t[10]; - t[0] = tp.y.mul(r.z); - t[0] = t[0].neg(); + t[0] = tp.y.multiply(r.z); + t[0] = t[0].negate(); t[0] = t[0].add(r.y); - t[1] = tp.x.mul(r.z); - t[1] = t[1].neg(); + t[1] = tp.x.multiply(r.z); + t[1] = t[1].negate(); t[1] = t[1].add(r.x); t[2] = t[0].square(); t[3] = t[1].square(); - t[4] = t[1].mul(t[3]); - t[2] = r.z.mul(t[2]); - t[3] = r.x.mul(t[3]); + t[4] = t[1].multiply(t[3]); + t[2] = r.z.multiply(t[2]); + t[3] = r.x.multiply(t[3]); t[5] = t[3].dbl(); - t[5] = t[4].sub(t[5]); + t[5] = t[4].subtract(t[5]); t[5] = t[5].add(t[2]); - r.x = t[1].mul(t[5]); - t[2] = t[3].sub(t[5]); - t[2] = t[2].mul(t[0]); - t[3] = r.y.mul(t[4]); - r.y = t[2].sub(t[3]); - r.z = r.z.mul(t[4]); - t[2] = t[1].mul(tp.y); - t[3] = t[0].mul(tp.x); - coeff[0] = t[3].sub(t[2]); - coeff[1] = t[0].neg(); + r.x = t[1].multiply(t[5]); + t[2] = t[3].subtract(t[5]); + t[2] = t[2].multiply(t[0]); + t[3] = r.y.multiply(t[4]); + r.y = t[2].subtract(t[3]); + r.z = r.z.multiply(t[4]); + t[2] = t[1].multiply(tp.y); + t[3] = t[0].multiply(tp.x); + coeff[0] = t[3].subtract(t[2]); + coeff[1] = t[0].negate(); coeff[2] = t[1]; } @@ -142,39 +142,39 @@ void final_exponentiation(fp12& f) // easy part t[0] = f.frobeniusMap(6); t[1] = f.inverse(); - t[2] = t[0].mul(t[1]); + t[2] = t[0].multiply(t[1]); t[1] = t[2]; t[2].frobeniusMapAssign(2); - t[2].mulAssign(t[1]); + t[2].multiplyAssign(t[1]); t[1] = t[2].cyclotomicSquare(); t[1] = t[1].conjugate(); // hard part t[3] = t[2].cyclotomicExp(g2::cofactorEFF); t[3] = t[3].conjugate(); t[4] = t[3].cyclotomicSquare(); - t[5] = t[1].mul(t[3]); + t[5] = t[1].multiply(t[3]); t[1] = t[5].cyclotomicExp(g2::cofactorEFF); t[1] = t[1].conjugate(); t[0] = t[1].cyclotomicExp(g2::cofactorEFF); t[0] = t[0].conjugate(); t[6] = t[0].cyclotomicExp(g2::cofactorEFF); t[6] = t[6].conjugate(); - t[6].mulAssign(t[4]); + t[6].multiplyAssign(t[4]); t[4] = t[6].cyclotomicExp(g2::cofactorEFF); t[4] = t[4].conjugate(); t[5] = t[5].conjugate(); - t[4].mulAssign(t[5]); - t[4].mulAssign(t[2]); + t[4].multiplyAssign(t[5]); + t[4].multiplyAssign(t[2]); t[5] = t[2].conjugate(); - t[1].mulAssign(t[2]); + t[1].multiplyAssign(t[2]); t[1].frobeniusMapAssign(3); - t[6].mulAssign(t[5]); + t[6].multiplyAssign(t[5]); t[6].frobeniusMapAssign(1); - t[3].mulAssign(t[0]); + t[3].multiplyAssign(t[0]); t[3].frobeniusMapAssign(2); - t[3].mulAssign(t[1]); - t[3].mulAssign(t[6]); - f = t[3].mul(t[4]); + t[3].multiplyAssign(t[1]); + t[3].multiplyAssign(t[6]); + f = t[3].multiply(t[4]); } fp12 calculate(vector>& pairs, std::function yield) diff --git a/src/signatures.cpp b/src/signatures.cpp index eda8b4a..bcbfbf8 100644 --- a/src/signatures.cpp +++ b/src/signatures.cpp @@ -542,7 +542,7 @@ bool verify( ) { vector> v; - pairing::add_pair(v, g1::one().neg(), signature); + pairing::add_pair(v, g1::one().negate(), signature); const g2 hashedPoint = fromMessage(message, CIPHERSUITE_ID); pairing::add_pair(v, pubkey, hashedPoint); @@ -587,7 +587,7 @@ bool aggregate_verify( ) { vector> v; - pairing::add_pair(v, g1::one().neg(), signature); + pairing::add_pair(v, g1::one().negate(), signature); if(!signature.isOnCurve() || !signature.inCorrectSubgroup()) { @@ -653,7 +653,7 @@ bool pop_verify( } vector> v; - pairing::add_pair(v, g1::one().neg(), signature_proof); + pairing::add_pair(v, g1::one().negate(), signature_proof); pairing::add_pair(v, pubkey, hashedPoint); // 1 =? prod e(pubkey[i], hash[i]) * e(-g1, aggSig) diff --git a/test/unittests.cpp b/test/unittests.cpp index e0733fc..d8b6d6c 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -247,7 +247,7 @@ void TestFieldElementArithmeticCornerCases() { fp s,m,a; _square(&s, &*input); - _mul(&m, &*input, &*input); + _multiply(&m, &*input, &*input); _add(&a, &*input, &*input); s = s.fromMont(); @@ -526,23 +526,23 @@ void TestG1AdditiveProperties() { throw invalid_argument("0 + 0 == 0"); } - t0 = a.sub(zero); + t0 = a.subtract(zero); if(!t0.equal(a)) { throw invalid_argument("a - 0 == a"); } - t0 = zero.sub(zero); + t0 = zero.subtract(zero); if(!t0.equal(zero)) { throw invalid_argument("0 - 0 == 0"); } - t0 = zero.neg(); + t0 = zero.negate(); if(!t0.equal(zero)) { throw invalid_argument("- 0 == 0"); } - t0 = zero.sub(a); - t0 = t0.neg(); + t0 = zero.subtract(a); + t0 = t0.negate(); if(!t0.equal(a)) { throw invalid_argument(" - (0 - a) == a"); @@ -553,7 +553,7 @@ void TestG1AdditiveProperties() throw invalid_argument("2 * 0 == 0"); } t0 = a.dbl(); - t0 = t0.sub(a); + t0 = t0.subtract(a); if(!t0.equal(a) || !t0.isOnCurve()) { throw invalid_argument(" (2 * a) - a == a"); @@ -564,9 +564,9 @@ void TestG1AdditiveProperties() { throw invalid_argument("a + b == b + a"); } - t0 = a.sub(b); - t1 = b.sub(a); - t1 = t1.neg(); + t0 = a.subtract(b); + t1 = b.subtract(a); + t1 = t1.negate(); if(!t0.equal(t1)) { throw invalid_argument("a - b == - ( b - a )"); @@ -580,10 +580,10 @@ void TestG1AdditiveProperties() { throw invalid_argument("(a + b) + c == (a + c ) + b"); } - t0 = a.sub(b); - t0 = t0.sub(c); - t1 = a.sub(c); - t1 = t1.sub(b); + t0 = a.subtract(b); + t0 = t0.subtract(c); + t1 = a.subtract(c); + t1 = t1.subtract(b); if(!t0.equal(t1)) { throw invalid_argument("(a - b) - c == (a - c) -b"); @@ -636,7 +636,7 @@ void TestG1MultiplicativePropertiesExpected() } t0 = a.scale(s1); t0 = t0.scale(s2); - s3 = scalar::mul<10, 4, 4>(s1, s2); + s3 = scalar::multiply<10, 4, 4>(s1, s2); t1 = a.scale(s3); if(!t0.equal(t1)) { @@ -682,7 +682,7 @@ void TestG1MultiplicativeProperties() } t0 = a.scale(s1); t0 = t0.scale(s2); - s3 = scalar::mul<10, 4, 4>(s1, s2); + s3 = scalar::multiply<10, 4, 4>(s1, s2); t1 = a.scale(s3); if(!t0.equal(t1)) { @@ -902,23 +902,23 @@ void TestG2AdditiveProperties() { throw invalid_argument("0 + 0 == 0"); } - t0 = a.sub(zero); + t0 = a.subtract(zero); if(!t0.equal(a)) { throw invalid_argument("a - 0 == a"); } - t0 = zero.sub(zero); + t0 = zero.subtract(zero); if(!t0.equal(zero)) { throw invalid_argument("0 - 0 == 0"); } - t0 = zero.neg(); + t0 = zero.negate(); if(!t0.equal(zero)) { throw invalid_argument("- 0 == 0"); } - t0 = zero.sub(a); - t0 = t0.neg(); + t0 = zero.subtract(a); + t0 = t0.negate(); if(!t0.equal(a)) { throw invalid_argument(" - (0 - a) == a"); @@ -929,7 +929,7 @@ void TestG2AdditiveProperties() throw invalid_argument("2 * 0 == 0"); } t0 = a.dbl(); - t0 = t0.sub(a); + t0 = t0.subtract(a); if(!t0.equal(a) || !t0.isOnCurve()) { throw invalid_argument(" (2 * a) - a == a"); @@ -940,9 +940,9 @@ void TestG2AdditiveProperties() { throw invalid_argument("a + b == b + a"); } - t0 = a.sub(b); - t1 = b.sub(a); - t1 = t1.neg(); + t0 = a.subtract(b); + t1 = b.subtract(a); + t1 = t1.negate(); if(!t0.equal(t1)) { throw invalid_argument("a - b == - ( b - a )"); @@ -956,10 +956,10 @@ void TestG2AdditiveProperties() { throw invalid_argument("(a + b) + c == (a + c ) + b"); } - t0 = a.sub(b); - t0 = t0.sub(c); - t1 = a.sub(c); - t1 = t1.sub(b); + t0 = a.subtract(b); + t0 = t0.subtract(c); + t1 = a.subtract(c); + t1 = t1.subtract(b); if(!t0.equal(t1)) { throw invalid_argument("(a - b) - c == (a - c) -b"); @@ -995,7 +995,7 @@ void TestG2MultiplicativeProperties() } t0 = a.scale(s1); t0 = t0.scale(s2); - s3 = scalar::mul<10, 4, 4>(s1, s2); + s3 = scalar::multiply<10, 4, 4>(s1, s2); t1 = a.scale(s3); if(!t0.equal(t1)) { @@ -1253,7 +1253,7 @@ void TestPairingBilinearity() g2 P2 = g2::one(); P1 = P1.scale(a); P2 = P2.scale(b); - P1 = P1.neg(); + P1 = P1.negate(); pairing::add_pair(v, P1, P2); // should be one if(!pairing::calculate(v).isOne()) @@ -1279,7 +1279,7 @@ void TestPairingBilinearity() g2 H2 = g2::one(); H1 = H1.scale(a); H2 = H2.scale(b); - H1 = H1.neg(); + H1 = H1.negate(); pairing::add_pair(v, H1, H2); // should be one if(!pairing::calculate(v).isOne()) @@ -1309,7 +1309,7 @@ void TestPairingMulti() pairing::add_pair(v, P1, P2); // accumulate targetExp // t += (ai1 * ai2) - array tmp = scalar::mul<10, 4, 4>(a1, a2); + array tmp = scalar::multiply<10, 4, 4>(a1, a2); targetExp = scalar::add<10, 10, 10>(targetExp, tmp); } // LHS @@ -1317,7 +1317,7 @@ void TestPairingMulti() g1 T1 = g1::one(); g2 T2 = g2::one(); T1 = T1.scale(targetExp); - T1 = T1.neg(); + T1 = T1.negate(); pairing::add_pair(v, T1, T2); if(!pairing::calculate(v).isOne()) { From 508c983eb9d225e7fefa07988d731ac2c1fea331 Mon Sep 17 00:00:00 2001 From: yarkin Date: Thu, 2 Nov 2023 22:34:24 +0800 Subject: [PATCH 10/40] Make ctors with array inputs explicit. --- include/bls12-381/fp.hpp | 8 ++++---- include/bls12-381/g.hpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/bls12-381/fp.hpp b/include/bls12-381/fp.hpp index 1a8e38f..29a5009 100644 --- a/include/bls12-381/fp.hpp +++ b/include/bls12-381/fp.hpp @@ -18,7 +18,7 @@ class fp std::array d; fp(); - fp(const std::array& d); + explicit fp(const std::array& d); fp(const fp& e); static std::optional fromBytesBE(const std::span in, const bool check = true, const bool raw = false); static std::optional fromBytesLE(const std::span in, const bool check = true, const bool raw = false); @@ -71,7 +71,7 @@ class fp2 fp c1; fp2(); - fp2(const std::array& e2); + explicit fp2(const std::array& e2); fp2(const fp2& e); static std::optional fromBytesBE(const std::span in, const bool check = true, const bool raw = false); static std::optional fromBytesLE(const std::span in, const bool check = true, const bool raw = false); @@ -127,7 +127,7 @@ class fp6 fp2 c2; fp6(); - fp6(const std::array& e3); + explicit fp6(const std::array& e3); fp6(const fp6& e); static std::optional fromBytesBE(const std::span in, const bool check = true, const bool raw = false); static std::optional fromBytesLE(const std::span in, const bool check = true, const bool raw = false); @@ -174,7 +174,7 @@ class fp12 fp6 c1; fp12(); - fp12(const std::array& e2); + explicit fp12(const std::array& e2); fp12(const fp12& e); static std::optional fromBytesBE(const std::span in, const bool check = true, const bool raw = false); static std::optional fromBytesLE(const std::span in, const bool check = true, const bool raw = false); diff --git a/include/bls12-381/g.hpp b/include/bls12-381/g.hpp index 90be1f7..6af3293 100644 --- a/include/bls12-381/g.hpp +++ b/include/bls12-381/g.hpp @@ -25,7 +25,7 @@ class g1 fp z; g1(); - g1(const std::array& e3); + explicit g1(const std::array& e3); g1(const g1& e); static std::optional fromJacobianBytesBE(const std::span in, const bool check = false, const bool raw = false); static std::optional fromJacobianBytesLE(const std::span in, const bool check = false, const bool raw = false); @@ -78,7 +78,7 @@ class g2 fp2 z; g2(); - g2(const std::array& e3); + explicit g2(const std::array& e3); g2(const g2& e); static std::optional fromJacobianBytesBE(const std::span in, const bool check = false, const bool raw = false); static std::optional fromJacobianBytesLE(const std::span in, const bool check = false, const bool raw = false); From 635854f8c870985a413be8db0bf4b2d470f7a63b Mon Sep 17 00:00:00 2001 From: yarkin Date: Fri, 3 Nov 2023 16:23:50 +0800 Subject: [PATCH 11/40] Add some benchmark. --- bench/eth_bench.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/bench/eth_bench.cpp b/bench/eth_bench.cpp index 9615f48..00dc116 100644 --- a/bench/eth_bench.cpp +++ b/bench/eth_bench.cpp @@ -205,6 +205,78 @@ void benchPairing() { endStopwatch(testName, start, numIters); } +void benchG1Add2() { + string testName = "G1 Addition With different settings"; + cout << endl << testName << endl; + + const int numIters = 10000; + g1 pbak = random_g1(); + + + + array s = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}; + + + auto performTest = [numIters, s, pbak](bool check, bool raw) { + array pRaw = {}; + g1 p = pbak; + p.toJacobianBytesLE(pRaw, raw); + + auto start = startStopwatch(); + + for (int i = 0; i < numIters; i++) { + p = *g1::fromJacobianBytesLE(pRaw, check, raw); + p.add(p); + p.toJacobianBytesLE(pRaw, raw); + } + endStopwatch(string("check=") + std::to_string(check) + string(", raw=") + std::to_string(raw), start, numIters); + + start = startStopwatch(); + }; + + performTest(true, true); + performTest(true, false); + performTest(false, true); + performTest(false, false); + +} + +void benchG2Add2() { + string testName = "G2 Addition With different settings"; + cout << endl << testName << endl; + + const int numIters = 10000; + g2 pbak = random_g2(); + + + + array s = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}; + + + auto performTest = [numIters, s, pbak](bool check, bool raw) { + array pRaw = {}; + g2 p = pbak; + p.toJacobianBytesLE(pRaw, raw); + + auto start = startStopwatch(); + + for (int i = 0; i < numIters; i++) { + p = *g2::fromJacobianBytesLE(pRaw, check, raw); + p.add(p); + p.toJacobianBytesLE(pRaw, raw); + } + endStopwatch(string("check=") + std::to_string(check) + string(", raw=") + std::to_string(raw), start, numIters); + + start = startStopwatch(); + }; + + performTest(true, true); + performTest(true, false); + performTest(false, true); + performTest(false, false); + +} + int main(int argc, char* argv[]) { benchG1Add(); @@ -214,4 +286,6 @@ int main(int argc, char* argv[]) benchG2Mul(); benchG2WeightedSum(); benchPairing(); + benchG1Add2(); + benchG2Add2(); } \ No newline at end of file From 3601738125c58828010ad903ba9cc6f73bb8a536 Mon Sep 17 00:00:00 2001 From: yarkin Date: Mon, 6 Nov 2023 23:09:20 +0800 Subject: [PATCH 12/40] Remove all xxAssign functions for basic arithmatics. --- include/bls12-381/arithmetic.hpp | 6 +- src/arithmetic.cpp | 331 ++----------------------------- src/fp.cpp | 34 ++-- 3 files changed, 39 insertions(+), 332 deletions(-) diff --git a/include/bls12-381/arithmetic.hpp b/include/bls12-381/arithmetic.hpp index 063c9c5..449be63 100644 --- a/include/bls12-381/arithmetic.hpp +++ b/include/bls12-381/arithmetic.hpp @@ -12,15 +12,11 @@ class fp; void init(bool cpu_features = true); void _add(fp* z, const fp* x, const fp* y); -void _addAssign(fp* x, const fp* y); void _ladd(fp* z, const fp* x, const fp* y); -void _laddAssign(fp* x, const fp* y); void _double(fp* z, const fp* x); -void _doubleAssign(fp* z); void _ldouble(fp* z, const fp* x); void _subtract(fp* z, const fp* x, const fp* y); -void _subtractAssign(fp* z, const fp* x); -void _lsubtractAssign(fp* z, const fp* x); +void _lsubtract(fp* z, const fp* x, const fp* y); void _negate(fp* z, const fp* x); void _square(fp* z, const fp* x); diff --git a/src/arithmetic.cpp b/src/arithmetic.cpp index 02dc80e..315fd14 100644 --- a/src/arithmetic.cpp +++ b/src/arithmetic.cpp @@ -96,93 +96,6 @@ void _add(fp* z, const fp* x, const fp* y) } #endif -#ifdef __x86_64__ -void _addAssign(fp* x, const fp* y) -{ - // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): - // x => %rdi - // y => %rsi - // callee needs to restore registers r15, r14, r13, r12, rbx before returning - asm("push %r15;"); - asm("push %r14;"); - asm("push %r13;"); - asm("push %r12;"); - asm("push %rbx;"); - asm("mov (%rdi),%r8;"); - asm("mov 0x08(%rdi),%r9;"); - asm("mov 0x10(%rdi),%r10;"); - asm("mov 0x18(%rdi),%r11;"); - asm("mov 0x20(%rdi),%r12;"); - asm("mov 0x28(%rdi),%r13;"); - asm("add (%rsi),%r8;"); - asm("adc 0x08(%rsi),%r9;"); - asm("adc 0x10(%rsi),%r10;"); - asm("adc 0x18(%rsi),%r11;"); - asm("adc 0x20(%rsi),%r12;"); - asm("adc 0x28(%rsi),%r13;"); - asm("mov %r8,%r14;"); - asm("mov %r9,%r15;"); - asm("mov %r10,%rcx;"); - asm("mov %r11,%rdx;"); - asm("mov %r12,%rsi;"); - asm("mov %r13,%rbx;"); - asm("mov $0xb9feffffffffaaab,%rax;"); - asm("sub %rax,%r14;"); - asm("mov $0x1eabfffeb153ffff,%rax;"); - asm("sbb %rax,%r15;"); - asm("mov $0x6730d2a0f6b0f624,%rax;"); - asm("sbb %rax,%rcx;"); - asm("mov $0x64774b84f38512bf,%rax;"); - asm("sbb %rax,%rdx;"); - asm("mov $0x4b1ba7b6434bacd7,%rax;"); - asm("sbb %rax,%rsi;"); - asm("mov $0x1a0111ea397fe69a,%rax;"); - asm("sbb %rax,%rbx;"); - asm("cmovae %r14,%r8;"); - asm("cmovae %r15,%r9;"); - asm("cmovae %rcx,%r10;"); - asm("cmovae %rdx,%r11;"); - asm("cmovae %rsi,%r12;"); - asm("cmovae %rbx,%r13;"); - asm("mov %r8, (%rdi);"); - asm("mov %r9, 0x08(%rdi);"); - asm("mov %r10,0x10(%rdi);"); - asm("mov %r11,0x18(%rdi);"); - asm("mov %r12,0x20(%rdi);"); - asm("mov %r13,0x28(%rdi);"); - asm("pop %rbx;"); - asm("pop %r12;"); - asm("pop %r13;"); - asm("pop %r14;"); - asm("pop %r15;"); -} -#else -void _addAssign(fp* x, const fp* y) -{ - uint64_t carry, _; - - tie(x->d[0], carry) = Add64(x->d[0], y->d[0], 0); - tie(x->d[1], carry) = Add64(x->d[1], y->d[1], carry); - tie(x->d[2], carry) = Add64(x->d[2], y->d[2], carry); - tie(x->d[3], carry) = Add64(x->d[3], y->d[3], carry); - tie(x->d[4], carry) = Add64(x->d[4], y->d[4], carry); - tie(x->d[5], _) = Add64(x->d[5], y->d[5], carry); - - // if z > q --> z -= q - // note: this is NOT constant time - if(!(x->d[5] < fp::MODULUS.d[5] || (x->d[5] == fp::MODULUS.d[5] && (x->d[4] < fp::MODULUS.d[4] || (x->d[4] == fp::MODULUS.d[4] && (x->d[3] < fp::MODULUS.d[3] || (x->d[3] == fp::MODULUS.d[3] && (x->d[2] < fp::MODULUS.d[2] || (x->d[2] == fp::MODULUS.d[2] && (x->d[1] < fp::MODULUS.d[1] || (x->d[1] == fp::MODULUS.d[1] && (x->d[0] < fp::MODULUS.d[0])))))))))))) - { - uint64_t b; - tie(x->d[0], b) = Sub64(x->d[0], fp::MODULUS.d[0], 0); - tie(x->d[1], b) = Sub64(x->d[1], fp::MODULUS.d[1], b); - tie(x->d[2], b) = Sub64(x->d[2], fp::MODULUS.d[2], b); - tie(x->d[3], b) = Sub64(x->d[3], fp::MODULUS.d[3], b); - tie(x->d[4], b) = Sub64(x->d[4], fp::MODULUS.d[4], b); - tie(x->d[5], _) = Sub64(x->d[5], fp::MODULUS.d[5], b); - } -} -#endif - #ifdef __x86_64__ void _ladd(fp* z, const fp* x, const fp* y) { @@ -223,45 +136,6 @@ void _ladd(fp* z, const fp* x, const fp* y) } #endif -#ifdef __x86_64__ -void _laddAssign(fp* x, const fp* y) -{ - // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): - // x => %rdi - // y => %rsi - // callee needs to restore registers r15, r14, r13, r12, rbx (if clobbed) before returning - asm("mov (%rdi),%r8;"); - asm("mov 0x08(%rdi),%r9;"); - asm("mov 0x10(%rdi),%r10;"); - asm("mov 0x18(%rdi),%r11;"); - asm("mov 0x20(%rdi),%rcx;"); - asm("mov 0x28(%rdi),%rax;"); - asm("add (%rsi),%r8;"); - asm("adc 0x08(%rsi),%r9;"); - asm("adc 0x10(%rsi),%r10;"); - asm("adc 0x18(%rsi),%r11;"); - asm("adc 0x20(%rsi),%rcx;"); - asm("adc 0x28(%rsi),%rax;"); - asm("mov %r8, (%rdi);"); - asm("mov %r9, 0x08(%rdi);"); - asm("mov %r10,0x10(%rdi);"); - asm("mov %r11,0x18(%rdi);"); - asm("mov %rcx,0x20(%rdi);"); - asm("mov %rax,0x28(%rdi);"); -} -#else -void _laddAssign(fp* x, const fp* y) -{ - uint64_t carry, _; - tie(x->d[0], carry) = Add64(x->d[0], y->d[0], 0); - tie(x->d[1], carry) = Add64(x->d[1], y->d[1], carry); - tie(x->d[2], carry) = Add64(x->d[2], y->d[2], carry); - tie(x->d[3], carry) = Add64(x->d[3], y->d[3], carry); - tie(x->d[4], carry) = Add64(x->d[4], y->d[4], carry); - tie(x->d[5], _) = Add64(x->d[5], y->d[5], carry); -} -#endif - #ifdef __x86_64__ void _double(fp* z, const fp* x) { @@ -349,92 +223,6 @@ void _double(fp* z, const fp* x) } #endif -#ifdef __x86_64__ -void _doubleAssign(fp* z) -{ - // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): - // z => %rdi - // callee needs to restore registers r15, r14, r13, r12, rbx before returning - asm("push %r15;"); - asm("push %r14;"); - asm("push %r13;"); - asm("push %r12;"); - asm("push %rbx;"); - asm("mov (%rdi),%r8;"); - asm("mov 0x08(%rdi),%r9;"); - asm("mov 0x10(%rdi),%r10;"); - asm("mov 0x18(%rdi),%r11;"); - asm("mov 0x20(%rdi),%r12;"); - asm("mov 0x28(%rdi),%r13;"); - asm("add %r8,%r8;"); - asm("adc %r9,%r9;"); - asm("adc %r10,%r10;"); - asm("adc %r11,%r11;"); - asm("adc %r12,%r12;"); - asm("adc %r13,%r13;"); - asm("mov %r8,%r14;"); - asm("mov %r9,%r15;"); - asm("mov %r10,%rcx;"); - asm("mov %r11,%rdx;"); - asm("mov %r12,%rsi;"); - asm("mov %r13,%rbx;"); - asm("mov $0xb9feffffffffaaab,%rax;"); - asm("sub %rax,%r14;"); - asm("mov $0x1eabfffeb153ffff,%rax;"); - asm("sbb %rax,%r15;"); - asm("mov $0x6730d2a0f6b0f624,%rax;"); - asm("sbb %rax,%rcx;"); - asm("mov $0x64774b84f38512bf,%rax;"); - asm("sbb %rax,%rdx;"); - asm("mov $0x4b1ba7b6434bacd7,%rax;"); - asm("sbb %rax,%rsi;"); - asm("mov $0x1a0111ea397fe69a,%rax;"); - asm("sbb %rax,%rbx;"); - asm("cmovae %r14,%r8;"); - asm("cmovae %r15,%r9;"); - asm("cmovae %rcx,%r10;"); - asm("cmovae %rdx,%r11;"); - asm("cmovae %rsi,%r12;"); - asm("cmovae %rbx,%r13;"); - asm("mov %r8, (%rdi);"); - asm("mov %r9, 0x08(%rdi);"); - asm("mov %r10,0x10(%rdi);"); - asm("mov %r11,0x18(%rdi);"); - asm("mov %r12,0x20(%rdi);"); - asm("mov %r13,0x28(%rdi);"); - asm("pop %rbx;"); - asm("pop %r12;"); - asm("pop %r13;"); - asm("pop %r14;"); - asm("pop %r15;"); -} -#else -void _doubleAssign(fp* z) -{ - uint64_t carry, _; - - tie(z->d[0], carry) = Add64(z->d[0], z->d[0], 0); - tie(z->d[1], carry) = Add64(z->d[1], z->d[1], carry); - tie(z->d[2], carry) = Add64(z->d[2], z->d[2], carry); - tie(z->d[3], carry) = Add64(z->d[3], z->d[3], carry); - tie(z->d[4], carry) = Add64(z->d[4], z->d[4], carry); - tie(z->d[5], _) = Add64(z->d[5], z->d[5], carry); - - // if z > q --> z -= q - // note: this is NOT constant time - if(!(z->d[5] < fp::MODULUS.d[5] || (z->d[5] == fp::MODULUS.d[5] && (z->d[4] < fp::MODULUS.d[4] || (z->d[4] == fp::MODULUS.d[4] && (z->d[3] < fp::MODULUS.d[3] || (z->d[3] == fp::MODULUS.d[3] && (z->d[2] < fp::MODULUS.d[2] || (z->d[2] == fp::MODULUS.d[2] && (z->d[1] < fp::MODULUS.d[1] || (z->d[1] == fp::MODULUS.d[1] && (z->d[0] < fp::MODULUS.d[0])))))))))))) - { - uint64_t b; - tie(z->d[0], b) = Sub64(z->d[0], fp::MODULUS.d[0], 0); - tie(z->d[1], b) = Sub64(z->d[1], fp::MODULUS.d[1], b); - tie(z->d[2], b) = Sub64(z->d[2], fp::MODULUS.d[2], b); - tie(z->d[3], b) = Sub64(z->d[3], fp::MODULUS.d[3], b); - tie(z->d[4], b) = Sub64(z->d[4], fp::MODULUS.d[4], b); - tie(z->d[5], _) = Sub64(z->d[5], fp::MODULUS.d[5], b); - } -} -#endif - #ifdef __x86_64__ void _ldouble(fp* z, const fp* x) { @@ -555,102 +343,25 @@ void _subtract(fp* z, const fp* x, const fp* y) #endif #ifdef __x86_64__ -void _subtractAssign(fp* z, const fp* x) -{ - // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): - // z => %rdi - // x => %rsi - // callee needs to restore registers r15, r14, r13, r12, rbx before returning - asm("push %r15;"); - asm("push %r14;"); - asm("push %r13;"); - asm("push %r12;"); - asm("push %rbx;"); - asm("xor %rax,%rax;"); - asm("mov (%rdi),%r8;"); - asm("mov 0x08(%rdi),%r9;"); - asm("mov 0x10(%rdi),%r10;"); - asm("mov 0x18(%rdi),%r11;"); - asm("mov 0x20(%rdi),%r12;"); - asm("mov 0x28(%rdi),%r13;"); - asm("sub (%rsi),%r8;"); - asm("sbb 0x08(%rsi),%r9;"); - asm("sbb 0x10(%rsi),%r10;"); - asm("sbb 0x18(%rsi),%r11;"); - asm("sbb 0x20(%rsi),%r12;"); - asm("sbb 0x28(%rsi),%r13;"); - asm("mov $0xb9feffffffffaaab,%r14;"); - asm("mov $0x1eabfffeb153ffff,%r15;"); - asm("mov $0x6730d2a0f6b0f624,%rcx;"); - asm("mov $0x64774b84f38512bf,%rdx;"); - asm("mov $0x4b1ba7b6434bacd7,%rsi;"); - asm("mov $0x1a0111ea397fe69a,%rbx;"); - asm("cmovae %rax,%r14;"); - asm("cmovae %rax,%r15;"); - asm("cmovae %rax,%rcx;"); - asm("cmovae %rax,%rdx;"); - asm("cmovae %rax,%rsi;"); - asm("cmovae %rax,%rbx;"); - asm("add %r14,%r8;"); - asm("adc %r15,%r9;"); - asm("adc %rcx,%r10;"); - asm("adc %rdx,%r11;"); - asm("adc %rsi,%r12;"); - asm("adc %rbx,%r13;"); - asm("mov %r8, (%rdi);"); - asm("mov %r9, 0x08(%rdi);"); - asm("mov %r10,0x10(%rdi);"); - asm("mov %r11,0x18(%rdi);"); - asm("mov %r12,0x20(%rdi);"); - asm("mov %r13,0x28(%rdi);"); - asm("pop %rbx;"); - asm("pop %r12;"); - asm("pop %r13;"); - asm("pop %r14;"); - asm("pop %r15;"); -} -#else -void _subtractAssign(fp* z, const fp* x) -{ - uint64_t b; - tie(z->d[0], b) = Sub64(z->d[0], x->d[0], 0); - tie(z->d[1], b) = Sub64(z->d[1], x->d[1], b); - tie(z->d[2], b) = Sub64(z->d[2], x->d[2], b); - tie(z->d[3], b) = Sub64(z->d[3], x->d[3], b); - tie(z->d[4], b) = Sub64(z->d[4], x->d[4], b); - tie(z->d[5], b) = Sub64(z->d[5], x->d[5], b); - if(b != 0) - { - uint64_t c, _; - tie(z->d[0], c) = Add64(z->d[0], fp::MODULUS.d[0], 0); - tie(z->d[1], c) = Add64(z->d[1], fp::MODULUS.d[1], c); - tie(z->d[2], c) = Add64(z->d[2], fp::MODULUS.d[2], c); - tie(z->d[3], c) = Add64(z->d[3], fp::MODULUS.d[3], c); - tie(z->d[4], c) = Add64(z->d[4], fp::MODULUS.d[4], c); - tie(z->d[5], _) = Add64(z->d[5], fp::MODULUS.d[5], c); - } -} -#endif - -#ifdef __x86_64__ -void _lsubtractAssign(fp* z, const fp* x) +void _lsubtract(fp* z, const fp* x, const fp* y) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): // z => %rdi // x => %rsi + // y => %rdx // callee needs to restore registers r15, r14, r13, r12, rbx before returning - asm("mov (%rdi),%r8;"); - asm("mov 0x08(%rdi),%r9;"); - asm("mov 0x10(%rdi),%r10;"); - asm("mov 0x18(%rdi),%r11;"); - asm("mov 0x20(%rdi),%rcx;"); - asm("mov 0x28(%rdi),%rax;"); - asm("sub (%rsi),%r8;"); - asm("sbb 0x08(%rsi),%r9;"); - asm("sbb 0x10(%rsi),%r10;"); - asm("sbb 0x18(%rsi),%r11;"); - asm("sbb 0x20(%rsi),%rcx;"); - asm("sbb 0x28(%rsi),%rax;"); + asm("mov (%rsi),%r8;"); + asm("mov 0x08(%rsi),%r9;"); + asm("mov 0x10(%rsi),%r10;"); + asm("mov 0x18(%rsi),%r11;"); + asm("mov 0x20(%rsi),%rcx;"); + asm("mov 0x28(%rsi),%rax;"); + asm("sub (%rdx),%r8;"); + asm("sbb 0x08(%rdx),%r9;"); + asm("sbb 0x10(%rdx),%r10;"); + asm("sbb 0x18(%rdx),%r11;"); + asm("sbb 0x20(%rdx),%rcx;"); + asm("sbb 0x28(%rdx),%rax;"); asm("mov %r8, (%rdi);"); asm("mov %r9, 0x08(%rdi);"); asm("mov %r10,0x10(%rdi);"); @@ -659,15 +370,15 @@ void _lsubtractAssign(fp* z, const fp* x) asm("mov %rax,0x28(%rdi);"); } #else -void _lsubtractAssign(fp* z, const fp* x) +void _lsubtract(fp* z, const fp* x, const fp* y) { uint64_t b, _; - tie(z->d[0], b) = Sub64(z->d[0], x->d[0], 0); - tie(z->d[1], b) = Sub64(z->d[1], x->d[1], b); - tie(z->d[2], b) = Sub64(z->d[2], x->d[2], b); - tie(z->d[3], b) = Sub64(z->d[3], x->d[3], b); - tie(z->d[4], b) = Sub64(z->d[4], x->d[4], b); - tie(z->d[5], _) = Sub64(z->d[5], x->d[5], b); + tie(z->d[0], b) = Sub64(x->d[0], y->d[0], 0); + tie(z->d[1], b) = Sub64(x->d[1], y->d[1], b); + tie(z->d[2], b) = Sub64(x->d[2], y->d[2], b); + tie(z->d[3], b) = Sub64(x->d[3], y->d[3], b); + tie(z->d[4], b) = Sub64(x->d[4], y->d[4], b); + tie(z->d[5], _) = Sub64(x->d[5], y->d[5], b); } #endif diff --git a/src/fp.cpp b/src/fp.cpp index c3e68db..603c04f 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -185,16 +185,16 @@ fp fp::inverse() const } else if(u.cmp(v) == 1) { - _lsubtractAssign(&u, &v); + _lsubtract(&u, &u, &v); u.div2(0); - _laddAssign(&r, &s); + _ladd(&r, &r, &s); s.mul2(); } else { - _lsubtractAssign(&v, &u); + _lsubtract(&v, &v, &u); v.div2(0); - _laddAssign(&s, &r); + _ladd(&s, &s, &r); z += r.mul2(); } k += 1; @@ -212,10 +212,10 @@ fp fp::inverse() const if(r.cmp(MODULUS) != -1 || z > 0) { - _lsubtractAssign(&r, &MODULUS); + _lsubtract(&r, &r, &MODULUS); } u = MODULUS; - _lsubtractAssign(&u, &r); + _lsubtract(&u, &u, &r); // Phase 2 for(uint64_t i = k; i < 384*2; i++) @@ -455,8 +455,8 @@ fp2 fp2::add(const fp2& e) const void fp2::addAssign(const fp2& e) { - _addAssign(&c0, &e.c0); - _addAssign(&c1, &e.c1); + _add(&c0, &c0, &e.c0); + _add(&c1, &c1, &e.c1); } fp2 fp2::ladd(const fp2& e) const @@ -477,8 +477,8 @@ fp2 fp2::dbl() const void fp2::doubleAssign() { - _doubleAssign(&c0); - _doubleAssign(&c1); + _double(&c0, &c0); + _double(&c1, &c1); } fp2 fp2::ldouble() const @@ -499,8 +499,8 @@ fp2 fp2::subtract(const fp2& e) const void fp2::subtractAssign(const fp2& e) { - _subtractAssign(&c0, &e.c0); - _subtractAssign(&c1, &e.c1); + _subtract(&c0, &c0, &e.c0); + _subtract(&c1, &c1, &e.c1); } fp2 fp2::negate() const @@ -528,7 +528,7 @@ fp2 fp2::multiply(const fp2& e) const _add(&t[0], &c0, &c1); _add(&t[3], &e.c0, &e.c1); _subtract(&c.c0, &t[1], &t[2]); - _addAssign(&t[1], &t[2]); + _add(&t[1], &t[1], &t[2]); _multiply(&t[0], &t[0], &t[3]); _subtract(&c.c1, &t[0], &t[1]); return c; @@ -542,7 +542,7 @@ void fp2::multiplyAssign(const fp2& e) _add(&t[0], &c0, &c1); _add(&t[3], &e.c0, &e.c1); _subtract(&c0, &t[1], &t[2]); - _addAssign(&t[1], &t[2]); + _add(&t[1], &t[1], &t[2]); _multiply(&t[0], &t[0], &t[3]); _subtract(&c1, &t[0], &t[1]); } @@ -585,8 +585,8 @@ fp2 fp2::mulByB() const fp2 c; _double(&t[0], &c0); _double(&t[1], &c1); - _doubleAssign(&t[0]); - _doubleAssign(&t[1]); + _double(&t[0], &t[0]); + _double(&t[1], &t[1]); _subtract(&c.c0, &t[0], &t[1]); _add(&c.c1, &t[0], &t[1]); return c; @@ -598,7 +598,7 @@ fp2 fp2::inverse() const fp2 c; _square(&t[0], &c0); _square(&t[1], &c1); - _addAssign(&t[0], &t[1]); + _add(&t[0], &t[0], &t[1]); t[0] = t[0].inverse(); _multiply(&c.c0, &c0, &t[0]); _multiply(&t[0], &t[0], &c1); From af8e9a227e55bb566c5d2caa5c49ba9b29057fe2 Mon Sep 17 00:00:00 2001 From: yarkin Date: Mon, 6 Nov 2023 23:45:35 +0800 Subject: [PATCH 13/40] Refactor some fp api. --- include/bls12-381/fp.hpp | 13 ++++ src/fp.cpp | 150 ++++++++++++++++++++++----------------- 2 files changed, 99 insertions(+), 64 deletions(-) diff --git a/include/bls12-381/fp.hpp b/include/bls12-381/fp.hpp index 29a5009..175fd23 100644 --- a/include/bls12-381/fp.hpp +++ b/include/bls12-381/fp.hpp @@ -36,6 +36,19 @@ class fp int64_t cmp(const fp& e) const; bool equal(const fp& e) const; bool sign() const; + + fp add(const fp& e) const; + void addAssign(const fp& e); + fp dbl() const; + void doubleAssign(); + fp subtract(const fp& e) const; + void subtractAssign(const fp& e); + fp negate() const; + fp multiply(const fp& e) const; + void multiplyAssign(const fp& e); + fp square() const; + void squareAssign(); + void div2(const uint64_t& e); uint64_t mul2(); fp toMont() const; diff --git a/src/fp.cpp b/src/fp.cpp index 603c04f..97476cc 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -109,6 +109,73 @@ bool fp::sign() const return (fromMont().d[0] & 1) == 0; } +fp fp::add(const fp& e) const +{ + fp c(*this); + c.addAssign(e); + return c; +} + +void fp::addAssign(const fp& e) +{ + _add(this, this, &e); +} + +fp fp::dbl() const +{ + fp c(*this); + c.doubleAssign(); + return c; +} + +void fp::doubleAssign() +{ + _double(this, this); +} + +fp fp::subtract(const fp& e) const +{ + fp c(*this); + c.subtractAssign(e); + return c; +} + +void fp::subtractAssign(const fp& e) +{ + _subtract(this, this, &e); +} + +fp fp::negate() const +{ + fp c; + _negate(&c, this); + return c; +} + +fp fp::multiply(const fp& e) const +{ + fp c(*this); + c.multiply(e); + return c; +} + +void fp::multiplyAssign(const fp& e) +{ + _multiply(this, this, &e); +} + +fp fp::square() const +{ + fp c(*this); + c.squareAssign(); + return c; +} + +void fp::squareAssign() +{ + _square(this, this); +} + void fp::div2(const uint64_t& e) { d[0] = d[0]>>1 | d[1]<<63; @@ -447,9 +514,8 @@ bool fp2::sign() const fp2 fp2::add(const fp2& e) const { - fp2 c; - _add(&c.c0, &c0, &e.c0); - _add(&c.c1, &c1, &e.c1); + fp2 c(*this); + c.addAssign(e); return c; } @@ -469,9 +535,8 @@ fp2 fp2::ladd(const fp2& e) const fp2 fp2::dbl() const { - fp2 c; - _double(&c.c0, &c0); - _double(&c.c1, &c1); + fp2 c(*this); + c.doubleAssign(); return c; } @@ -491,9 +556,8 @@ fp2 fp2::ldouble() const fp2 fp2::subtract(const fp2& e) const { - fp2 c; - _subtract(&c.c0, &c0, &e.c0); - _subtract(&c.c1, &c1, &e.c1); + fp2 c(*this); + c.subtractAssign(e); return c; } @@ -521,16 +585,9 @@ fp2 fp2::conjugate() const fp2 fp2::multiply(const fp2& e) const { - fp t[4]; - fp2 c; - _multiply(&t[1], &c0, &e.c0); - _multiply(&t[2], &c1, &e.c1); - _add(&t[0], &c0, &c1); - _add(&t[3], &e.c0, &e.c1); - _subtract(&c.c0, &t[1], &t[2]); - _add(&t[1], &t[1], &t[2]); - _multiply(&t[0], &t[0], &t[3]); - _subtract(&c.c1, &t[0], &t[1]); + fp2 c(*this); + c.multiplyAssign(e); + return c; return c; } @@ -549,13 +606,8 @@ void fp2::multiplyAssign(const fp2& e) fp2 fp2::square() const { - fp t[3]; - fp2 c; - _ladd(&t[0], &c0, &c1); - _subtract(&t[1], &c0, &c1); - _ldouble(&t[2], &c0); - _multiply(&c.c0, &t[0], &t[1]); - _multiply(&c.c1, &t[2], &c1); + fp2 c(*this); + c.squareAssign(); return c; } @@ -833,10 +885,8 @@ bool fp6::equal(const fp6& e) const fp6 fp6::add(const fp6& e) const { - fp6 c; - c.c0 = c0.add(e.c0); - c.c1 = c1.add(e.c1); - c.c2 = c2.add(e.c2); + fp6 c(*this); + c.addAssign(e); return c; } @@ -849,10 +899,8 @@ void fp6::addAssign(const fp6& e) fp6 fp6::dbl() const { - fp6 c; - c.c0 = c0.dbl(); - c.c1 = c1.dbl(); - c.c2 = c2.dbl(); + fp6 c(*this); + c.doubleAssign(); return c; } @@ -865,10 +913,8 @@ void fp6::doubleAssign() fp6 fp6::subtract(const fp6& e) const { - fp6 c; - c.c0 = c0.subtract(e.c0); - c.c1 = c1.subtract(e.c1); - c.c2 = c2.subtract(e.c2); + fp6 c(*this); + c.subtractAssign(e); return c; } @@ -890,32 +936,8 @@ fp6 fp6::negate() const fp6 fp6::multiply(const fp6& e) const { - fp2 t[6]; - fp6 c; - t[0] = c0.multiply(e.c0); - t[1] = c1.multiply(e.c1); - t[2] = c2.multiply(e.c2); - t[3] = c1.add(c2); - t[4] = e.c1.add(e.c2); - t[3].multiplyAssign(t[4]); - t[4] = t[1].add(t[2]); - t[3].subtractAssign(t[4]); - t[3] = t[3].mulByNonResidue(); - t[5] = t[0].add(t[3]); - t[3] = c0.add(c1); - t[4] = e.c0.add(e.c1); - t[3].multiplyAssign(t[4]); - t[4] = t[0].add(t[1]); - t[3].subtractAssign(t[4]); - t[4] = t[2].mulByNonResidue(); - c.c1 = t[3].add(t[4]); - t[3] = c0.add(c2); - t[4] = e.c0.add(e.c2); - t[3].multiplyAssign(t[4]); - t[4] = t[0].add(t[2]); - t[3].subtractAssign(t[4]); - c.c2 = t[1].add(t[3]); - c.c0 = t[5]; + fp6 c(*this); + c.multiplyAssign(e); return c; } From 1f60410eef74ee933333ce4d35f0ba70474b1b5d Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 00:14:21 +0800 Subject: [PATCH 14/40] Refactor weightedSum. --- include/bls12-381/g.hpp | 4 ++-- src/g.cpp | 26 ++++++++++---------------- test/unittests.cpp | 8 ++++---- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/include/bls12-381/g.hpp b/include/bls12-381/g.hpp index b6c6ddb..d0b88af 100644 --- a/include/bls12-381/g.hpp +++ b/include/bls12-381/g.hpp @@ -60,7 +60,7 @@ class g1 auto operator<=>(const g1&) const = default; - static std::optional weightedSum(std::span points, std::span> scalars, std::function yield = std::function()); + static g1 weightedSum(std::span points, std::span> scalars, std::function yield = std::function()); static g1 mapToCurve(const fp& e); static std::tuple swuMapG1(const fp& e); static void isogenyMapG1(fp& x, fp& y); @@ -117,7 +117,7 @@ class g2 auto operator<=>(const g2&) const = default; - static std::optional weightedSum(std::span points, std::span> scalars, std::function yield = std::function()); + static g2 weightedSum(std::span points, std::span> scalars, std::function yield = std::function()); static g2 mapToCurve(const fp2& e); static std::tuple swuMapG2(const fp2& e); //static void isogenyMapG2(fp2& x, fp2& y); diff --git a/src/g.cpp b/src/g.cpp index 70c5138..c6bfc0a 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -440,16 +440,13 @@ g1 g1::glvEndomorphism() const // WeightedSum calculates multi exponentiation. Given pairs of G1 point and scalar values // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n // Length of points and scalars are expected to be equal, otherwise NONE is returned. -optional g1::weightedSum(std::span points, std::span> scalars, std::function yield) +g1 g1::weightedSum(std::span points, std::span> scalars, std::function yield) { - if(points.size() != scalars.size()) - { - return {}; - } + const size_t effective_size = min(scalars.size(), points.size()); uint64_t c = 3; - if(scalars.size() >= 32) + if(effective_size >= 32) { - c = static_cast(ceil(log10(static_cast(scalars.size())))); + c = static_cast(ceil(log10(static_cast(effective_size)))); } uint64_t bucketSize = (1< g1::weightedSum(std::span points, std::span shifted; scalar::rsh(shifted, scalars[i], c*j); @@ -1172,16 +1169,13 @@ g2 g2::frobeniusMap(int64_t power) const // WeightedSum calculates multi exponentiation. Given pairs of G2 point and scalar values // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n // Length of points and scalars are expected to be equal, otherwise NONE is returned. -optional g2::weightedSum(std::span points, std::span> scalars, std::function yield) +g2 g2::weightedSum(std::span points, std::span> scalars, std::function yield) { - if(points.size() != scalars.size()) - { - return {}; - } + const size_t effective_size = min(scalars.size(), points.size()); uint64_t c = 3; - if(scalars.size() >= 32) + if(effective_size >= 32) { - c = static_cast(ceil(log10(static_cast(scalars.size())))); + c = static_cast(ceil(log10(static_cast(effective_size)))); } uint64_t bucketSize = (1< g2::weightedSum(std::span points, std::span shifted; scalar::rsh(shifted, scalars[i], c*j); diff --git a/test/unittests.cpp b/test/unittests.cpp index 5778b63..44450b2 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -710,7 +710,7 @@ void TestG1WeightedSumExpected() vector bases = {one, one}; g1 expected, result; expected = one.scale<1>({5}); - result = g1::weightedSum(bases, scalars).value(); + result = g1::weightedSum(bases, scalars); if(!expected.equal(result)) { throw invalid_argument("TestG1WeightedSumExpected: bad multi-exponentiation"); @@ -738,7 +738,7 @@ void TestG1WeightedSumBatch() tmp = bases[i].scale(scalars[i]); expected = expected.add(tmp); } - g1 result = g1::weightedSum(bases, scalars).value(); + g1 result = g1::weightedSum(bases, scalars); if(!expected.equal(result)) { throw invalid_argument("bad multi-exponentiation"); @@ -1023,7 +1023,7 @@ void TestG2WeightedSumExpected() vector bases = {one, one}; g2 expected, result; expected = one.scale<1>({5}); - result = g2::weightedSum(bases, scalars).value(); + result = g2::weightedSum(bases, scalars); if(!expected.equal(result)) { throw invalid_argument("bad multi-exponentiation"); @@ -1051,7 +1051,7 @@ void TestG2WeightedSumBatch() tmp = bases[i].scale(scalars[i]); expected = expected.add(tmp); } - g2 result = g2::weightedSum(bases, scalars).value(); + g2 result = g2::weightedSum(bases, scalars); if(!expected.equal(result)) { throw invalid_argument("bad multi-exponentiation"); From d2caf235976f4f8105ca6203195e6d58fba0a262 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 00:17:24 +0800 Subject: [PATCH 15/40] Comiling issue in x86 --- include/bls12-381/arithmetic.hpp | 2 +- src/arithmetic.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/bls12-381/arithmetic.hpp b/include/bls12-381/arithmetic.hpp index 449be63..0a7de7d 100644 --- a/include/bls12-381/arithmetic.hpp +++ b/include/bls12-381/arithmetic.hpp @@ -23,7 +23,7 @@ void _square(fp* z, const fp* x); #if defined(__x86_64__) && defined(__ELF__) extern void _multiply(fp*, const fp*, const fp*); #elif defined(__x86_64__) -extern void (*_mul)(fp*, const fp*, const fp*); +extern void (*_multiply)(fp*, const fp*, const fp*); #else void _multiply(fp*, const fp*, const fp*); #endif diff --git a/src/arithmetic.cpp b/src/arithmetic.cpp index 315fd14..d5f2650 100644 --- a/src/arithmetic.cpp +++ b/src/arithmetic.cpp @@ -1499,22 +1499,22 @@ extern "C" blsmul_func_t __attribute__((no_sanitize_address)) resolve_blsmul() { while(*my_environ != nullptr) { const char disable_str[] = "BLS_DISABLE_BMI2"; if(strncmp(*my_environ++, disable_str, strlen(disable_str)) == 0) - return __mul; + return __multiply; } if(cpu_has_bmi2_and_adx()) return __mul_ex; - return __mul; + return __multiply; } void _multiply(fp*, const fp*, const fp*) __attribute__((ifunc("resolve_blsmul"))); #else -blsmul_func_t _mul = __mul; +blsmul_func_t _multiply = __multiply; struct bls_mul_init { bls_mul_init() { if(cpu_has_bmi2_and_adx()) - _mul = __mul_ex; + _multiply = __mul_ex; } }; static bls_mul_init the_bls_mul_init; From e5be876b4d567be1670ee59b5596180bfd40a0c4 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 00:25:26 +0800 Subject: [PATCH 16/40] update comments. --- src/g.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/g.cpp b/src/g.cpp index c6bfc0a..486101f 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -19,6 +19,7 @@ g1::g1(const g1& e) : x(e.x), y(e.y), z(e.z) optional g1::fromJacobianBytesBE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp::fromBytesBE(span(&in[ 0], &in[ 48]), true, raw); optional y = fp::fromBytesBE(span(&in[48], &in[ 96]), true, raw); optional z = fp::fromBytesBE(span(&in[96], &in[144]), true, raw); @@ -33,6 +34,7 @@ optional g1::fromJacobianBytesBE(const span in, const bo optional g1::fromJacobianBytesLE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), true, raw); optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), true, raw); optional z = fp::fromBytesLE(span(&in[96], &in[144]), true, raw); @@ -47,6 +49,7 @@ optional g1::fromJacobianBytesLE(const span in, const bo optional g1::fromAffineBytesBE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp::fromBytesBE(span(&in[ 0], &in[ 48]), true, raw); optional y = fp::fromBytesBE(span(&in[48], &in[ 96]), true, raw); if(!x.has_value() || !y.has_value()) return {}; @@ -66,6 +69,7 @@ optional g1::fromAffineBytesBE(const span in, const bool optional g1::fromAffineBytesLE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), true, raw); optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), true, raw); if(!x.has_value() || !y.has_value()) return {}; @@ -697,6 +701,7 @@ g2::g2(const g2& e) : x(e.x), y(e.y), z(e.z) optional g2::fromJacobianBytesBE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), true, raw); optional y = fp2::fromBytesBE(span(&in[ 96], &in[192]), true, raw); optional z = fp2::fromBytesBE(span(&in[192], &in[288]), true, raw); @@ -711,6 +716,7 @@ optional g2::fromJacobianBytesBE(const span in, const bo optional g2::fromJacobianBytesLE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), true, raw); optional y = fp2::fromBytesLE(span(&in[ 96], &in[192]), true, raw); optional z = fp2::fromBytesLE(span(&in[192], &in[288]), true, raw); @@ -725,6 +731,7 @@ optional g2::fromJacobianBytesLE(const span in, const bo optional g2::fromAffineBytesBE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), true, raw); optional y = fp2::fromBytesBE(span(&in[ 96], &in[192]), true, raw); if(!x.has_value() || !y.has_value()) return {}; @@ -744,6 +751,7 @@ optional g2::fromAffineBytesBE(const span in, const bool optional g2::fromAffineBytesLE(const span in, const bool check, const bool raw) { + // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), true, raw); optional y = fp2::fromBytesLE(span(&in[ 96], &in[192]), true, raw); if(!x.has_value() || !y.has_value()) return {}; @@ -952,9 +960,9 @@ bool g2::inCorrectSubgroup() const g2 t0, t1; t0 = this->psi(); t0 = t0.psi(); - t1 = t0.negate(); // - ψ^2(P) + t1 = t0.negate(); // - ψ^2(P) t0 = t0.psi(); // ψ^3(P) - t0 = t0.scale(cofactorEFF); // - x ψ^3(P) + t0 = t0.scale(cofactorEFF); // - x ψ^3(P) t0 = t0.negate(); t0 = t0.add(t1); From 45557fc7d06675d2e98aabb96378c2c9b8eb3ce2 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 00:34:59 +0800 Subject: [PATCH 17/40] Better optional access. --- src/fp.cpp | 24 ++++++++++++------------ src/g.cpp | 42 +++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/fp.cpp b/src/fp.cpp index 4985b04..dff3363 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -439,16 +439,16 @@ optional fp2::fromBytesBE(const span in, const bool chec { optional c1 = fp::fromBytesBE(span(&in[ 0], &in[48]), check, raw); optional c0 = fp::fromBytesBE(span(&in[48], &in[96]), check, raw); - if(!c1.has_value() || !c0.has_value()) return {}; - return fp2({c0.value(), c1.value()}); + if(!c1 || !c0) return {}; + return fp2({*c0, *c1}); } optional fp2::fromBytesLE(const span in, const bool check, const bool raw) { optional c0 = fp::fromBytesLE(span(&in[ 0], &in[48]), check, raw); optional c1 = fp::fromBytesLE(span(&in[48], &in[96]), check, raw); - if(!c1.has_value() || !c0.has_value()) return {}; - return fp2({c0.value(), c1.value()}); + if(!c1 || !c0) return {}; + return fp2({*c0, *c1}); } void fp2::toBytesBE(const span out, const bool raw) const @@ -817,8 +817,8 @@ optional fp6::fromBytesBE(const span in, const bool che optional c2 = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), check, raw); optional c1 = fp2::fromBytesBE(span(&in[ 96], &in[192]), check, raw); optional c0 = fp2::fromBytesBE(span(&in[192], &in[288]), check, raw); - if(!c2.has_value() || !c1.has_value() || !c0.has_value()) return {}; - return fp6({c0.value(), c1.value(), c2.value()}); + if(!c2 || !c1 || !c0) return {}; + return fp6({*c0, *c1, *c2}); } optional fp6::fromBytesLE(const span in, const bool check, const bool raw) @@ -826,8 +826,8 @@ optional fp6::fromBytesLE(const span in, const bool che optional c0 = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), check, raw); optional c1 = fp2::fromBytesLE(span(&in[ 96], &in[192]), check, raw); optional c2 = fp2::fromBytesLE(span(&in[192], &in[288]), check, raw); - if(!c2.has_value() || !c1.has_value() || !c0.has_value()) return {}; - return fp6({c0.value(), c1.value(), c2.value()}); + if(!c2 || !c1 || !c0) return {}; + return fp6({*c0, *c1, *c2}); } void fp6::toBytesBE(const span out, const bool raw) const @@ -1223,16 +1223,16 @@ optional fp12::fromBytesBE(const span in, const bool c { optional c1 = fp6::fromBytesBE(span(&in[ 0], &in[288]), check, raw); optional c0 = fp6::fromBytesBE(span(&in[288], &in[576]), check, raw); - if(!c1.has_value() || !c0.has_value()) return {}; - return fp12({c0.value(), c1.value()}); + if(!c1 || !c0) return {}; + return fp12({*c0, *c1}); } optional fp12::fromBytesLE(const span in, const bool check, const bool raw) { optional c0 = fp6::fromBytesLE(span(&in[ 0], &in[288]), check, raw); optional c1 = fp6::fromBytesLE(span(&in[288], &in[576]), check, raw); - if(!c1.has_value() || !c0.has_value()) return {}; - return fp12({c0.value(), c1.value()}); + if(!c1 || !c0) return {}; + return fp12({*c0, *c1}); } void fp12::toBytesBE(const span out, const bool raw) const diff --git a/src/g.cpp b/src/g.cpp index 486101f..91d81cd 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -23,8 +23,8 @@ optional g1::fromJacobianBytesBE(const span in, const bo optional x = fp::fromBytesBE(span(&in[ 0], &in[ 48]), true, raw); optional y = fp::fromBytesBE(span(&in[48], &in[ 96]), true, raw); optional z = fp::fromBytesBE(span(&in[96], &in[144]), true, raw); - if(!x.has_value() || !y.has_value() || !z.has_value()) return {}; - g1 p = g1({x.value(), y.value(), z.value()}); + if(!x || !y || !z) return {}; + g1 p = g1({*x, *y, *z}); if(check && !p.isOnCurve()) { return {}; @@ -38,8 +38,8 @@ optional g1::fromJacobianBytesLE(const span in, const bo optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), true, raw); optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), true, raw); optional z = fp::fromBytesLE(span(&in[96], &in[144]), true, raw); - if(!x.has_value() || !y.has_value() || !z.has_value()) return {}; - g1 p = g1({x.value(), y.value(), z.value()}); + if(!x || !y || !z) return {}; + g1 p = g1({*x, *y, *z}); if(check && !p.isOnCurve()) { return {}; @@ -52,14 +52,14 @@ optional g1::fromAffineBytesBE(const span in, const bool // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp::fromBytesBE(span(&in[ 0], &in[ 48]), true, raw); optional y = fp::fromBytesBE(span(&in[48], &in[ 96]), true, raw); - if(!x.has_value() || !y.has_value()) return {}; + if(!x || !y) return {}; // check if given input points to infinity - if(x.value().isZero() && y.value().isZero()) + if(x->isZero() && y->isZero()) { return zero(); } fp z = fp::one(); - g1 p = g1({x.value(), y.value(), z}); + g1 p = g1({*x, *y, z}); if(check && !p.isOnCurve()) { return {}; @@ -72,14 +72,14 @@ optional g1::fromAffineBytesLE(const span in, const bool // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp::fromBytesLE(span(&in[ 0], &in[ 48]), true, raw); optional y = fp::fromBytesLE(span(&in[48], &in[ 96]), true, raw); - if(!x.has_value() || !y.has_value()) return {}; + if(!x || !y) return {}; // check if given input points to infinity - if(x.value().isZero() && y.value().isZero()) + if(x->isZero() && y->isZero()) { return zero(); } fp z = fp::one(); - g1 p = g1({x.value(), y.value(), z}); + g1 p = g1({*x, *y, z}); if(check && !p.isOnCurve()) { return {}; @@ -705,8 +705,8 @@ optional g2::fromJacobianBytesBE(const span in, const bo optional x = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), true, raw); optional y = fp2::fromBytesBE(span(&in[ 96], &in[192]), true, raw); optional z = fp2::fromBytesBE(span(&in[192], &in[288]), true, raw); - if(!x.has_value() || !y.has_value() || !z.has_value()) return {}; - g2 p = g2({x.value(), y.value(), z.value()}); + if(!x || !y || !z) return {}; + g2 p = g2({*x, *y, *z}); if(check && !p.isOnCurve()) { return {}; @@ -720,8 +720,8 @@ optional g2::fromJacobianBytesLE(const span in, const bo optional x = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), true, raw); optional y = fp2::fromBytesLE(span(&in[ 96], &in[192]), true, raw); optional z = fp2::fromBytesLE(span(&in[192], &in[288]), true, raw); - if(!x.has_value() || !y.has_value() || !z.has_value()) return {}; - g2 p = g2({x.value(), y.value(), z.value()}); + if(!x || !y || !z) return {}; + g2 p = g2({*x, *y, *z}); if(check && !p.isOnCurve()) { return {}; @@ -734,14 +734,14 @@ optional g2::fromAffineBytesBE(const span in, const bool // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp2::fromBytesBE(span(&in[ 0], &in[ 96]), true, raw); optional y = fp2::fromBytesBE(span(&in[ 96], &in[192]), true, raw); - if(!x.has_value() || !y.has_value()) return {}; + if(!x || !y) return {}; // check if given input points to infinity - if(x.value().isZero() && y.value().isZero()) + if(x->isZero() && y->isZero()) { return zero(); } fp2 z = fp2::one(); - g2 p = g2({x.value(), y.value(), z}); + g2 p = g2({*x, *y, z}); if(check && !p.isOnCurve()) { return {}; @@ -754,14 +754,14 @@ optional g2::fromAffineBytesLE(const span in, const bool // We decided to always validate the input here. Check flag will only affect on-curve checks. optional x = fp2::fromBytesLE(span(&in[ 0], &in[ 96]), true, raw); optional y = fp2::fromBytesLE(span(&in[ 96], &in[192]), true, raw); - if(!x.has_value() || !y.has_value()) return {}; + if(!x || !y) return {}; // check if given input points to infinity - if(x.value().isZero() && y.value().isZero()) + if(x->isZero() && y->isZero()) { return zero(); } fp2 z = fp2::one(); - g2 p = g2({x.value(), y.value(), z}); + g2 p = g2({*x, *y, z}); if(check && !p.isOnCurve()) { return {}; @@ -789,7 +789,7 @@ optional g2::fromCompressedBytesBE(const span in) if (!c0) { return {}; } - p.x.c0 = c0.value(); + p.x.c0 = *c0; // erase 3 msbs from given input and perform validity check p.x.c1.d[5] &= 0x1FFFFFFFFFFFFFFF; p.x.c1 = p.x.c1.toMont(); From e3a24bb380a6e50e4749596ccb407baa91c0078e Mon Sep 17 00:00:00 2001 From: yarkinwho <99302011+yarkinwho@users.noreply.github.com> Date: Tue, 7 Nov 2023 08:21:17 +0800 Subject: [PATCH 18/40] Update text in tests. Co-authored-by: Gregory Popovitch --- bench/eth_bench.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench/eth_bench.cpp b/bench/eth_bench.cpp index 00dc116..6eab4ff 100644 --- a/bench/eth_bench.cpp +++ b/bench/eth_bench.cpp @@ -119,7 +119,7 @@ void benchG1Mul() { } void benchG1WeightedSum() { - string testName = "G2 WeightedSum"; + string testName = "G1 WeightedSum"; const int numIters = 10000; g1 p = random_g1(); vector bases = {p,p,p,p,p,p,p,p}; From 88493fef1466a1cea75c36c2f717684a1b8c079e Mon Sep 17 00:00:00 2001 From: yarkinwho <99302011+yarkinwho@users.noreply.github.com> Date: Tue, 7 Nov 2023 08:21:37 +0800 Subject: [PATCH 19/40] Update test Co-authored-by: Gregory Popovitch --- bench/eth_bench.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/bench/eth_bench.cpp b/bench/eth_bench.cpp index 6eab4ff..f72692c 100644 --- a/bench/eth_bench.cpp +++ b/bench/eth_bench.cpp @@ -122,17 +122,8 @@ void benchG1WeightedSum() { string testName = "G1 WeightedSum"; const int numIters = 10000; g1 p = random_g1(); - vector bases = {p,p,p,p,p,p,p,p}; - vector> scalars = { - {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, - {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, - {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, - {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, - {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, - {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, - {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, - {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff} - }; + vector bases{8, p}; + vector> scalars{8, {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}}; auto start = startStopwatch(); for (int i = 0; i < numIters; i++) { g1::weightedSum(bases, scalars); From a1cef41895c6f3676dd5f3ad66167e95930b1251 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 08:56:32 +0800 Subject: [PATCH 20/40] Change the way weightedSum pick window and bucket size to avoid using floats. --- src/g.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g.cpp b/src/g.cpp index 91d81cd..272f16b 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -450,7 +450,7 @@ g1 g1::weightedSum(std::span points, std::span= 32) { - c = static_cast(ceil(log10(static_cast(effective_size)))); + c = (std::numeric_limits::digits - std::countl_zero(effective_size))/3 + 2; } uint64_t bucketSize = (1< points, std::span= 32) { - c = static_cast(ceil(log10(static_cast(effective_size)))); + c = (std::numeric_limits::digits - std::countl_zero(effective_size))/3 + 2; } uint64_t bucketSize = (1< Date: Tue, 7 Nov 2023 12:06:17 +0800 Subject: [PATCH 21/40] minor fix. --- src/fp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fp.cpp b/src/fp.cpp index dff3363..ace6f34 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -588,7 +588,6 @@ fp2 fp2::multiply(const fp2& e) const fp2 c(*this); c.multiplyAssign(e); return c; - return c; } void fp2::multiplyAssign(const fp2& e) From c43e154a0ecb4fcd2fbdf35ca5985b9070bb93e7 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 15:31:12 +0800 Subject: [PATCH 22/40] Further optimize weightedSum. --- include/bls12-381/g.hpp | 4 ++-- src/g.cpp | 32 ++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/bls12-381/g.hpp b/include/bls12-381/g.hpp index d0b88af..bac4980 100644 --- a/include/bls12-381/g.hpp +++ b/include/bls12-381/g.hpp @@ -60,7 +60,7 @@ class g1 auto operator<=>(const g1&) const = default; - static g1 weightedSum(std::span points, std::span> scalars, std::function yield = std::function()); + static g1 weightedSum(std::span points, std::span> scalars, const std::function& yield = std::function()); static g1 mapToCurve(const fp& e); static std::tuple swuMapG1(const fp& e); static void isogenyMapG1(fp& x, fp& y); @@ -117,7 +117,7 @@ class g2 auto operator<=>(const g2&) const = default; - static g2 weightedSum(std::span points, std::span> scalars, std::function yield = std::function()); + static g2 weightedSum(std::span points, std::span> scalars, const std::function& yield = std::function()); static g2 mapToCurve(const fp2& e); static std::tuple swuMapG2(const fp2& e); //static void isogenyMapG2(fp2& x, fp2& y); diff --git a/src/g.cpp b/src/g.cpp index 272f16b..704250b 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -444,7 +444,7 @@ g1 g1::glvEndomorphism() const // WeightedSum calculates multi exponentiation. Given pairs of G1 point and scalar values // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n // Length of points and scalars are expected to be equal, otherwise NONE is returned. -g1 g1::weightedSum(std::span points, std::span> scalars, std::function yield) +g1 g1::weightedSum(std::span points, std::span> scalars, const std::function& yield) { const size_t effective_size = min(scalars.size(), points.size()); uint64_t c = 3; @@ -462,10 +462,16 @@ g1 g1::weightedSum(std::span points, std::span shifted; scalar::rsh(shifted, scalars[i], c*j); uint64_t index = bucketSize & shifted[0]; @@ -478,15 +484,15 @@ g1 g1::weightedSum(std::span points, std::span= 0; i--) { + if (i & 255 == 0) { + yield(); + } sum = sum.add(bucket[i]); acc = acc.add(sum); } windows.push_back(acc); } - if(scalars.size() >= 32 && yield) - { - yield(); - } + g1 acc = zero(); for(int64_t i = windows.size()-1; i >= 0; i--) { @@ -1177,7 +1183,7 @@ g2 g2::frobeniusMap(int64_t power) const // WeightedSum calculates multi exponentiation. Given pairs of G2 point and scalar values // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n // Length of points and scalars are expected to be equal, otherwise NONE is returned. -g2 g2::weightedSum(std::span points, std::span> scalars, std::function yield) +g2 g2::weightedSum(std::span points, std::span> scalars, const std::function& yield) { const size_t effective_size = min(scalars.size(), points.size()); uint64_t c = 3; @@ -1195,10 +1201,16 @@ g2 g2::weightedSum(std::span points, std::span shifted; scalar::rsh(shifted, scalars[i], c*j); uint64_t index = bucketSize & shifted[0]; @@ -1211,15 +1223,15 @@ g2 g2::weightedSum(std::span points, std::span= 0; i--) { + if (i & 255 == 0) { + yield(); + } sum = sum.add(bucket[i]); acc = acc.add(sum); } windows.push_back(acc); } - if(scalars.size() >= 32 && yield) - { - yield(); - } + g2 acc = zero(); for(int64_t i = windows.size()-1; i >= 0; i--) { From 009e5255feb79c87343341730fdf75e313cef8c8 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 16:23:30 +0800 Subject: [PATCH 23/40] More fp refactor. --- include/bls12-381/fp.hpp | 6 +++ include/bls12-381/scalar.hpp | 20 ++++---- src/fp.cpp | 91 +++++++++++++++++++++--------------- 3 files changed, 70 insertions(+), 47 deletions(-) diff --git a/include/bls12-381/fp.hpp b/include/bls12-381/fp.hpp index f316474..bbef043 100644 --- a/include/bls12-381/fp.hpp +++ b/include/bls12-381/fp.hpp @@ -168,6 +168,7 @@ class fp6 fp6 multiply(const fp6& e) const; void multiplyAssign(const fp6& e); fp6 square() const; + void squareAssign(); void mulBy01Assign(const fp2& e0, const fp2& e1); fp6 mulBy01(const fp2& e0, const fp2& e1) const; fp6 mulBy1(const fp2& e1) const; @@ -207,12 +208,17 @@ class fp12 bool isGtValid() const; bool equal(const fp12& e) const; fp12 add(const fp12& e) const; + void addAssign(const fp12& e); fp12 dbl() const; + void doubleAssign(); fp12 subtract(const fp12& e) const; + void subtractAssign(const fp12& e); fp12 negate() const; fp12 conjugate() const; fp12 square() const; + void squareAssign(); fp12 cyclotomicSquare() const; + void cyclotomicSquareAssign(); fp12 multiply(const fp12& e) const; void multiplyAssign(const fp12& e); static std::tuple fp4Square(const fp2& e0, const fp2& e1); diff --git a/include/bls12-381/scalar.hpp b/include/bls12-381/scalar.hpp index 4e5f5a1..f53a259 100644 --- a/include/bls12-381/scalar.hpp +++ b/include/bls12-381/scalar.hpp @@ -255,10 +255,10 @@ fp fp::exp(const std::array& s) const uint64_t l = scalar::bitLength(s); for(int64_t i = l - 1; i >= 0; i--) { - _multiply(&z, &z, &z); + z.squareAssign(); if((s[i/64] >> (i%64) & 1) == 1) { - _multiply(&z, &z, this); + z.multiplyAssign(*this); } } return z; @@ -271,10 +271,10 @@ fp2 fp2::exp(const std::array& s) const uint64_t l = scalar::bitLength(s); for(int64_t i = l - 1; i >= 0; i--) { - z = z.square(); + z.squareAssign(); if((s[i/64] >> (i%64) & 1) == 1) { - z = z.multiply(*this); + z.multiplyAssign(*this); } } return z; @@ -287,10 +287,10 @@ fp6 fp6::exp(const std::array& s) const uint64_t l = scalar::bitLength(s); for(int64_t i = l - 1; i >= 0; i--) { - z = z.square(); + z.squareAssign(); if((s[i/64] >> (i%64) & 1) == 1) { - z = z.multiply(*this); + z.multiplyAssign(*this); } } return z; @@ -302,10 +302,10 @@ template fp12 fp12::exp(const std::array& s) const uint64_t l = scalar::bitLength(s); for(int64_t i = l - 1; i >= 0; i--) { - z = z.square(); + z.squareAssign(); if((s[i/64] >> (i%64) & 1) == 1) { - z = z.multiply(*this); + z.multiplyAssign(*this); } } return z; @@ -318,10 +318,10 @@ fp12 fp12::cyclotomicExp(const std::array& s) const uint64_t l = scalar::bitLength(s); for(int64_t i = l - 1; i >= 0; i--) { - z = z.cyclotomicSquare(); + z.cyclotomicSquareAssign(); if((s[i/64] >> (i%64) & 1) == 1) { - z = z.multiply(*this); + z.multiplyAssign(*this); } } return z; diff --git a/src/fp.cpp b/src/fp.cpp index ace6f34..01f9754 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -970,6 +970,13 @@ void fp6::multiplyAssign(const fp6& e) } fp6 fp6::square() const +{ + fp6 c(*this); + c.squareAssign(); + return c; +} + +void fp6::squareAssign() { fp2 t[6]; fp6 c; @@ -983,14 +990,13 @@ fp6 fp6::square() const t[3].doubleAssign(); t[4] = c2.square(); t[5] = t[3].mulByNonResidue(); - c.c0 = t[0].add(t[5]); + c0 = t[0].add(t[5]); t[5] = t[4].mulByNonResidue(); - c.c1 = t[1].add(t[5]); + c1 = t[1].add(t[5]); t[1].addAssign(t[2]); t[1].addAssign(t[3]); t[0].addAssign(t[4]); - c.c2 = t[1].subtract(t[0]); - return c; + c2 = t[1].subtract(t[0]); } void fp6::mulBy01Assign(const fp2& e0, const fp2& e1) @@ -1293,28 +1299,40 @@ bool fp12::equal(const fp12& e) const fp12 fp12::add(const fp12& e) const { - fp12 c; - c.c0 = c0.add(e.c0); - c.c1 = c1.add(e.c1); + fp12 c(*this); + c.addAssign(e); return c; } +void fp12::addAssign(const fp12& e) { + c0.addAssign(e.c0); + c1.addAssign(e.c1); +} + fp12 fp12::dbl() const { - fp12 c; - c.c0 = c0.dbl(); - c.c1 = c1.dbl(); + fp12 c(*this); + c.doubleAssign(); return c; } +void fp12::doubleAssign() { + c0.doubleAssign(); + c1.doubleAssign(); +} + fp12 fp12::subtract(const fp12& e) const { - fp12 c; - c.c0 = c0.subtract(e.c0); - c.c1 = c1.subtract(e.c1); + fp12 c(*this); + c.subtractAssign(e); return c; } +void fp12::subtractAssign(const fp12& e) { + c0.subtractAssign(e.c0); + c1.subtractAssign(e.c1); +} + fp12 fp12::negate() const { fp12 c; @@ -1333,8 +1351,14 @@ fp12 fp12::conjugate() const fp12 fp12::square() const { + fp12 c(*this); + c.squareAssign(); + return c; +} + +void fp12::squareAssign() { fp6 t[4]; - fp12 c; + t[0] = c0.add(c1); t[2] = c0.multiply(c1); t[1] = c1.mulByNonResidue(); @@ -1342,54 +1366,47 @@ fp12 fp12::square() const t[3] = t[2].mulByNonResidue(); t[0].multiplyAssign(t[1]); t[0].subtractAssign(t[2]); - c.c0 = t[0].subtract(t[3]); - c.c1 = t[2].dbl(); - return c; + c0 = t[0].subtract(t[3]); + c1 = t[2].dbl(); } fp12 fp12::cyclotomicSquare() const { + fp12 c(*this); + c.cyclotomicSquareAssign(); + return c; +} + +void fp12::cyclotomicSquareAssign() { fp2 t[7]; - fp12 c; tie(t[3], t[4]) = fp4Square(c0.c0, c1.c1); t[2] = t[3].subtract(c0.c0); t[2].doubleAssign(); - c.c0.c0 = t[2].add(t[3]); + c0.c0 = t[2].add(t[3]); t[2] = t[4].add(c1.c1); t[2].doubleAssign(); - c.c1.c1 = t[2].add(t[4]); + c1.c1 = t[2].add(t[4]); tie(t[3], t[4]) = fp4Square(c1.c0, c0.c2); tie(t[5], t[6]) = fp4Square(c0.c1, c1.c2); t[2] = t[3].subtract(c0.c1); t[2].doubleAssign(); - c.c0.c1 = t[2].add(t[3]); + c0.c1 = t[2].add(t[3]); t[2] = t[4].add(c1.c2); t[2].doubleAssign(); - c.c1.c2 = t[2].add(t[4]); + c1.c2 = t[2].add(t[4]); t[3] = t[6].mulByNonResidue(); t[2] = t[3].add(c1.c0); t[2].doubleAssign(); - c.c1.c0 = t[2].add(t[3]); + c1.c0 = t[2].add(t[3]); t[2] = t[5].subtract(c0.c2); t[2].doubleAssign(); - c.c0.c2 = t[2].add(t[5]); - return c; + c0.c2 = t[2].add(t[5]); } fp12 fp12::multiply(const fp12& e) const { - fp6 t[4]; - fp12 c; - t[1] = c0.multiply(e.c0); - t[2] = c1.multiply(e.c1); - t[0] = t[1].add(t[2]); - t[2] = t[2].mulByNonResidue(); - t[3] = t[1].add(t[2]); - t[1] = c0.add(c1); - t[2] = e.c0.add(e.c1); - t[1].multiplyAssign(t[2]); - c.c0 = t[3]; - c.c1 = t[1].subtract(t[0]); + fp12 c(*this); + c.multiplyAssign(e); return c; } From 9bef4d7896a16425fe0985da831218e46075d281 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 17:11:49 +0800 Subject: [PATCH 24/40] Add assign methods to g1 and g2. --- include/bls12-381/g.hpp | 6 ++ src/g.cpp | 132 +++++++++++++++++++++++++--------------- 2 files changed, 88 insertions(+), 50 deletions(-) diff --git a/include/bls12-381/g.hpp b/include/bls12-381/g.hpp index bac4980..99df525 100644 --- a/include/bls12-381/g.hpp +++ b/include/bls12-381/g.hpp @@ -51,9 +51,12 @@ class g1 bool isAffine() const; g1 affine() const; g1 add(const g1& e) const; + void addAssign(const g1& e); g1 dbl() const; + void doubleAssign(); g1 negate() const; g1 subtract(const g1& e) const; + void subtractAssign(const g1& e); template g1 scale(const std::array& s) const; g1 clearCofactor() const; g1 glvEndomorphism() const; @@ -107,9 +110,12 @@ class g2 bool isAffine() const; g2 affine() const; g2 add(const g2& e) const; + void addAssign(const g2& e); g2 dbl() const; + void doubleAssign(); g2 negate() const; g2 subtract(const g2& e) const; + void subtractAssign(const g2& e); g2 psi() const; template g2 scale(const std::array& s) const; g2 clearCofactor() const; diff --git a/src/g.cpp b/src/g.cpp index 704250b..0794d6d 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -323,14 +323,21 @@ g1 g1::affine() const g1 g1::add(const g1& e) const { + g1 r(*this); + r.addAssign(e); + return r; +} + +void g1::addAssign(const g1& e) { // www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl if(isZero()) { - return e; + *this = e; + return; } if(e.isZero()) { - return *this; + return; } fp t[9]; _square(&t[7], &z); @@ -345,11 +352,13 @@ g1 g1::add(const g1& e) const { if(t[0].equal(t[2])) { - return dbl(); + doubleAssign(); + return; } - return zero(); + *this = zero(); + return; } - g1 r; + _subtract(&t[1], &t[1], &t[3]); _double(&t[4], &t[1]); _square(&t[4], &t[4]); @@ -360,29 +369,34 @@ g1 g1::add(const g1& e) const _subtract(&t[6], &t[6], &t[5]); _multiply(&t[3], &t[3], &t[4]); _double(&t[4], &t[3]); - _subtract(&r.x, &t[6], &t[4]); - _subtract(&t[4], &t[3], &r.x); + _subtract(&x, &t[6], &t[4]); + _subtract(&t[4], &t[3], &x); _multiply(&t[6], &t[2], &t[5]); _double(&t[6], &t[6]); _multiply(&t[0], &t[0], &t[4]); - _subtract(&r.y, &t[0], &t[6]); + _subtract(&y, &t[0], &t[6]); _add(&t[0], &z, &e.z); _square(&t[0], &t[0]); _subtract(&t[0], &t[0], &t[7]); _subtract(&t[0], &t[0], &t[8]); - _multiply(&r.z, &t[0], &t[1]); - return r; + _multiply(&z, &t[0], &t[1]); } g1 g1::dbl() const { + g1 r(*this); + r.doubleAssign(); + return r; +} + +void g1::doubleAssign() { // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l if(isZero()) { - return *this; + return; } fp t[5]; - g1 r; + _square(&t[0], &x); _square(&t[1], &y); _square(&t[2], &t[1]); @@ -395,17 +409,16 @@ g1 g1::dbl() const _add(&t[0], &t[3], &t[0]); _square(&t[4], &t[0]); _double(&t[3], &t[1]); - _subtract(&r.x, &t[4], &t[3]); - _subtract(&t[1], &t[1], &r.x); + _subtract(&x, &t[4], &t[3]); + _subtract(&t[1], &t[1], &x); _double(&t[2], &t[2]); _double(&t[2], &t[2]); _double(&t[2], &t[2]); _multiply(&t[0], &t[0], &t[1]); _subtract(&t[1], &t[0], &t[2]); _multiply(&t[0], &y, &z); - r.y = t[1]; - _double(&r.z, &t[0]); - return r; + y = t[1]; + _double(&z, &t[0]); } g1 g1::negate() const @@ -419,12 +432,15 @@ g1 g1::negate() const g1 g1::subtract(const g1& e) const { - g1 c, d; - d = e.negate(); - c = this->add(d); + g1 c(*this); + c.subtractAssign(e); return c; } +void g1::subtractAssign(const g1& e) { + addAssign(e.negate()); +} + g1 g1::clearCofactor() const { return this->scale(cofactorEFF); @@ -477,7 +493,7 @@ g1 g1::weightedSum(std::span points, std::span points, std::span points, std::spanadd(d); + g2 c(*this); + c.subtractAssign(e); return c; } +void g2::subtractAssign(const g2& e) { + addAssign(e.negate()); +} + g2 g2::psi() const { g2 p; @@ -1216,7 +1248,7 @@ g2 g2::weightedSum(std::span points, std::span points, std::span points, std::span Date: Tue, 7 Nov 2023 21:56:34 +0800 Subject: [PATCH 25/40] Fix yield check in weightedSum. --- src/g.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/g.cpp b/src/g.cpp index 0794d6d..cd0b021 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -478,14 +478,14 @@ g1 g1::weightedSum(std::span points, std::span shifted; @@ -500,7 +500,7 @@ g1 g1::weightedSum(std::span points, std::span= 0; i--) { - if (i & 255 == 0) { + if (yield && ((i & 255) == 0)) { yield(); } sum.addAssign(bucket[i]); @@ -1233,14 +1233,14 @@ g2 g2::weightedSum(std::span points, std::span shifted; @@ -1255,7 +1255,7 @@ g2 g2::weightedSum(std::span points, std::span= 0; i--) { - if (i & 255 == 0) { + if (yield && ((i & 255) == 0)) { yield(); } sum.addAssign(bucket[i]); From 0a829c4c1477ba0ea917f63aebd1b8b7beeaf73a Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 22:12:46 +0800 Subject: [PATCH 26/40] Better weightedSum tests. --- test/unittests.cpp | 124 +++++++++++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 48 deletions(-) diff --git a/test/unittests.cpp b/test/unittests.cpp index 44450b2..76ad4d3 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -719,30 +719,44 @@ void TestG1WeightedSumExpected() void TestG1WeightedSumBatch() { - g1 one = g1::one(); - int64_t n = 1000; - vector> scalars; - vector bases; - // scalars: [s0,s1 ... s(n-1)] - // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] - for(int64_t i = 0, j = n-1; i < n; i++, j--) - { - scalars.insert(scalars.begin(), array{static_cast(rand()%100000), 0, 0, 0}); - bases.push_back(g1::zero()); - bases[i] = one.scale(scalars[0]); - } - // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) - g1 expected, tmp; - for(int64_t i = 0; i < n; i++) - { - tmp = bases[i].scale(scalars[i]); - expected = expected.add(tmp); - } - g1 result = g1::weightedSum(bases, scalars); - if(!expected.equal(result)) - { - throw invalid_argument("bad multi-exponentiation"); - } + const auto doTest = [](int64_t n) { + g1 one = g1::one(); + vector> scalars; + vector bases; + // scalars: [s0,s1 ... s(n-1)] + // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] + for(int64_t i = 0; i < n; i++) + { + scalars.insert(scalars.begin(), array{static_cast(rand()%100000), 0, 0, 0}); + bases.push_back(g1::zero()); + bases[i] = one.scale(array{static_cast(rand()%100000), 0, 0, 0}); + } + // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) + g1 expected, tmp; + for(int64_t i = 0; i < n; i++) + { + tmp = bases[i].scale(scalars[i]); + expected = expected.add(tmp); + } + g1 result = g1::weightedSum(bases, scalars); + if(!expected.equal(result)) + { + throw invalid_argument("bad multi-exponentiation"); + } + }; + + doTest(0); + doTest(1); + doTest(2); + doTest(31); + doTest(32); + doTest(33); + doTest(63); + doTest(64); + doTest(65); + doTest(511); + doTest(512); + doTest(513); } void TestG1MapToCurve() @@ -1032,30 +1046,44 @@ void TestG2WeightedSumExpected() void TestG2WeightedSumBatch() { - g2 one = g2::one(); - int64_t n = 1000; - vector> scalars; - vector bases; - // scalars: [s0,s1 ... s(n-1)] - // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] - for(int64_t i = 0, j = n-1; i < n; i++, j--) - { - scalars.insert(scalars.begin(), array{static_cast(rand()%100000), 0, 0, 0}); - bases.push_back(g2::zero()); - bases[i] = one.scale(scalars[0]); - } - // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) - g2 expected, tmp; - for(int64_t i = 0; i < n; i++) - { - tmp = bases[i].scale(scalars[i]); - expected = expected.add(tmp); - } - g2 result = g2::weightedSum(bases, scalars); - if(!expected.equal(result)) - { - throw invalid_argument("bad multi-exponentiation"); - } + const auto doTest = [](int64_t n) { + g2 one = g2::one(); + vector> scalars; + vector bases; + // scalars: [s0,s1 ... s(n-1)] + // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] + for(int64_t i = 0, j = n-1; i < n; i++, j--) + { + scalars.insert(scalars.begin(), array{static_cast(rand()%100000), 0, 0, 0}); + bases.push_back(g2::zero()); + bases[i] = one.scale(array{static_cast(rand()%100000), 0, 0, 0}); + } + // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) + g2 expected, tmp; + for(int64_t i = 0; i < n; i++) + { + tmp = bases[i].scale(scalars[i]); + expected = expected.add(tmp); + } + g2 result = g2::weightedSum(bases, scalars); + if(!expected.equal(result)) + { + throw invalid_argument("bad multi-exponentiation"); + } + }; + + doTest(0); + doTest(1); + doTest(2); + doTest(31); + doTest(32); + doTest(33); + doTest(63); + doTest(64); + doTest(65); + doTest(511); + doTest(512); + doTest(513); } void TestG2MapToCurve() From a3bdd14b59bfb71a0d4f7485446a639732c8cf76 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 22:31:33 +0800 Subject: [PATCH 27/40] More fp tests and fix an issue. --- src/fp.cpp | 2 +- test/unittests.cpp | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/fp.cpp b/src/fp.cpp index 01f9754..b3a56af 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -155,7 +155,7 @@ fp fp::negate() const fp fp::multiply(const fp& e) const { fp c(*this); - c.multiply(e); + c.multiplyAssign(e); return c; } diff --git a/test/unittests.cpp b/test/unittests.cpp index 76ad4d3..32538a5 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -244,15 +244,36 @@ void TestFieldElementArithmeticCornerCases() { auto fpExpectedSquare = fp::fromBytesBE(hexToBytes<48>(expectedSquare), false, true); auto fpExpectedAdd = fp::fromBytesBE(hexToBytes<48>(expectedAdd), false, true); - fp s,m,a; + fp s,m,a,d; + fp s1,m1,a1,d1; _square(&s, &*input); _multiply(&m, &*input, &*input); _add(&a, &*input, &*input); + _double(&d, &*input); + + s1 = input->square(); + m1 = input->multiply(*input); + a1 = input->add(*input); + d1 = input->dbl(); + + if(!s.equal(s1)) { + throw invalid_argument("_square != fp::square"); + } + if(!m.equal(m1)) { + throw invalid_argument("_multiply != fp::multiply"); + } + if(!a.equal(a1)) { + throw invalid_argument("_add != fp::add"); + } + if(!d.equal(d1)) { + throw invalid_argument("_double != fp::dbl"); + } s = s.fromMont(); m = m.fromMont(); a = a.fromMont(); + d = d.fromMont(); if(!s.equal(m)) { @@ -264,6 +285,11 @@ void TestFieldElementArithmeticCornerCases() { throw invalid_argument("square != expected"); } + if(!a.equal(d)) + { + throw invalid_argument("double != add self"); + } + if(!a.equal(*fpExpectedAdd)) { throw invalid_argument("add != expected"); From baa619ee68d31b04f2e85af129c5b9788cc19b24 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 23:10:40 +0800 Subject: [PATCH 28/40] More tests for arithmetic operations. --- test/unittests.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/test/unittests.cpp b/test/unittests.cpp index 32538a5..3e64e97 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -302,6 +302,92 @@ void TestFieldElementArithmeticCornerCases() { } } +template void TestHelperMultiplySquare(const T input) { + T s,m; + s = input.square(); + m = input.multiply(input); + + T sa,ma; + sa = input; + sa.squareAssign(); + ma = input; + ma.multiplyAssign(ma); + + if(!s.equal(sa)) + { + throw invalid_argument("square != squareAssign"); + } + + if(!m.equal(ma)) + { + throw invalid_argument("multiply != multiplyAssign"); + } + + if(!s.equal(m)) + { + throw invalid_argument("square != mul self"); + } +} + +template void TestHelperAddSubtractDouble(const T input) { + T a,d; + a = input.add(input); + d = input.dbl(); + + T aa,da; + aa = input; + aa.addAssign(aa); + da = input; + da.doubleAssign(); + + if(!a.equal(aa)) + { + throw invalid_argument("add != addAssign"); + } + + if(!d.equal(da)) + { + throw invalid_argument("dbl != doubleAssign"); + } + + if(!a.equal(d)) + { + throw invalid_argument("double != add self"); + } + + T s = input.subtract(input); + T sa = input; + sa.subtractAssign(sa); + + if(!s.equal(sa)) + { + throw invalid_argument("subtract != subtractAssign"); + } + + if(!s.isZero()) + { + throw invalid_argument("zero != sub self"); + } +} + +void TestArithmeticOpraters() { + for(int i = 0; i < 100; i++) + { + TestHelperMultiplySquare(random_fe()); + TestHelperMultiplySquare(random_fe2()); + TestHelperMultiplySquare(random_fe6()); + TestHelperMultiplySquare(random_fe12()); + + TestHelperAddSubtractDouble(random_fe()); + TestHelperAddSubtractDouble(random_fe2()); + TestHelperAddSubtractDouble(random_fe6()); + TestHelperAddSubtractDouble(random_fe12()); + + TestHelperAddSubtractDouble(random_g1()); + TestHelperAddSubtractDouble(random_g2()); + } +} + void TestFieldElementHelpers() { // fe @@ -1983,6 +2069,8 @@ int main() TestFieldElementSerialization(); TestFieldElementByteInputs(); + TestArithmeticOpraters(); + TestG1Serialization(); TestG1SerializationGarbage(); TestG1IsOnCurve(); From 25ff4f647529cae3f72ab7b11a8e9ec106b4d11f Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 23:23:18 +0800 Subject: [PATCH 29/40] basic fb operations should not be implemented by assign methods for performance reason. --- src/fp.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/fp.cpp b/src/fp.cpp index b3a56af..03edd3f 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -111,8 +111,8 @@ bool fp::sign() const fp fp::add(const fp& e) const { - fp c(*this); - c.addAssign(e); + fp c; + _add(&c, this, &e); return c; } @@ -123,8 +123,8 @@ void fp::addAssign(const fp& e) fp fp::dbl() const { - fp c(*this); - c.doubleAssign(); + fp c; + _double(&c, this); return c; } @@ -135,8 +135,8 @@ void fp::doubleAssign() fp fp::subtract(const fp& e) const { - fp c(*this); - c.subtractAssign(e); + fp c; + _subtract(&c, this, &e); return c; } @@ -154,8 +154,8 @@ fp fp::negate() const fp fp::multiply(const fp& e) const { - fp c(*this); - c.multiplyAssign(e); + fp c; + _multiply(&c, this, &e); return c; } @@ -166,8 +166,8 @@ void fp::multiplyAssign(const fp& e) fp fp::square() const { - fp c(*this); - c.squareAssign(); + fp c; + _square(&c, this); return c; } From 0dde5447596ae508b6e04fb86e454c1628094765 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 23:26:57 +0800 Subject: [PATCH 30/40] Remove unused low level function. --- src/fp.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/fp.cpp b/src/fp.cpp index 03edd3f..b7fda85 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -525,14 +525,6 @@ void fp2::addAssign(const fp2& e) _add(&c1, &c1, &e.c1); } -fp2 fp2::ladd(const fp2& e) const -{ - fp2 c; - _ladd(&c.c0, &c0, &e.c0); - _ladd(&c.c1, &c1, &e.c1); - return c; -} - fp2 fp2::dbl() const { fp2 c(*this); @@ -546,14 +538,6 @@ void fp2::doubleAssign() _double(&c1, &c1); } -fp2 fp2::ldouble() const -{ - fp2 c; - _ldouble(&c.c0, &c0); - _ldouble(&c.c1, &c1); - return c; -} - fp2 fp2::subtract(const fp2& e) const { fp2 c(*this); From c9f9d277c067f6cbde63c0e4d31f148768eb1651 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 23:40:39 +0800 Subject: [PATCH 31/40] Missing file in last commit... --- include/bls12-381/fp.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/bls12-381/fp.hpp b/include/bls12-381/fp.hpp index bbef043..4ed0ad5 100644 --- a/include/bls12-381/fp.hpp +++ b/include/bls12-381/fp.hpp @@ -103,10 +103,8 @@ class fp2 bool sign() const; fp2 add(const fp2& e) const; void addAssign(const fp2& e); - fp2 ladd(const fp2& e) const; fp2 dbl() const; void doubleAssign(); - fp2 ldouble() const; fp2 subtract(const fp2& e) const; void subtractAssign(const fp2& e); fp2 negate() const; From 4d4f20e85d1bf936c0f0841f78eb25328958a9c0 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 7 Nov 2023 23:58:54 +0800 Subject: [PATCH 32/40] Add sqrt tests. --- test/unittests.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/unittests.cpp b/test/unittests.cpp index 3e64e97..4fa2c43 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -388,6 +388,45 @@ void TestArithmeticOpraters() { } } +void TestSqrt() { + for (int i = 0; i < 100; ++ i) { + fp a = random_fe(); + fp as = a.square(); + fp asqrt; + if (as.sqrt(asqrt)) { + if(!as.equal(asqrt.square())) + { + throw invalid_argument("sqrt(fp).square != fp"); + } + if(!a.equal(asqrt) && !a.equal(asqrt.negate())) + { + throw invalid_argument("fp2!= sqrt(fp.square)"); + } + } else { + throw invalid_argument("failed to find sqrt for fp"); + } + } + + for (int i = 0; i < 100; ++ i) { + fp2 a = random_fe2(); + fp2 as = a.square(); + fp2 asqrt; + if (as.sqrt(asqrt)) { + if(!as.equal(asqrt.square())) + { + throw invalid_argument("sqrt(fp2).square != fp2"); + } + if(!a.equal(asqrt) && !a.equal(asqrt.negate())) + { + throw invalid_argument("fp2 != sqrt(fp2.square)"); + } + } else { + throw invalid_argument("failed to find sqrt for fp2"); + } + } + +} + void TestFieldElementHelpers() { // fe @@ -2071,6 +2110,8 @@ int main() TestArithmeticOpraters(); + TestSqrt(); + TestG1Serialization(); TestG1SerializationGarbage(); TestG1IsOnCurve(); From e3893a85cd1598cb8ff1bfa288898148249237d4 Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 8 Nov 2023 00:15:58 +0800 Subject: [PATCH 33/40] Improve weigthedSum tests. --- test/unittests.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/unittests.cpp b/test/unittests.cpp index 4fa2c43..0789f82 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -878,9 +878,8 @@ void TestG1WeightedSumBatch() // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] for(int64_t i = 0; i < n; i++) { - scalars.insert(scalars.begin(), array{static_cast(rand()%100000), 0, 0, 0}); - bases.push_back(g1::zero()); - bases[i] = one.scale(array{static_cast(rand()%100000), 0, 0, 0}); + scalars.push_back(random_scalar()); + bases.push_back(random_g1()); } // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) g1 expected, tmp; @@ -1203,11 +1202,10 @@ void TestG2WeightedSumBatch() vector bases; // scalars: [s0,s1 ... s(n-1)] // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] - for(int64_t i = 0, j = n-1; i < n; i++, j--) + for(int64_t i = 0; i < n; i++) { - scalars.insert(scalars.begin(), array{static_cast(rand()%100000), 0, 0, 0}); - bases.push_back(g2::zero()); - bases[i] = one.scale(array{static_cast(rand()%100000), 0, 0, 0}); + scalars.push_back(random_scalar()); + bases.push_back(random_g2()); } // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) g2 expected, tmp; From ec8e8d585873e1775983782c274792da6315acf2 Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 15 Nov 2023 16:32:51 +0800 Subject: [PATCH 34/40] Add tests for fp mod and fp exp --- test/unittests.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/test/unittests.cpp b/test/unittests.cpp index 0789f82..6037ecb 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -427,6 +427,74 @@ void TestSqrt() { } +void TestMod() { + + const char* testVectorInput[] = { + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000001A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAA", // p-1 + "000000000000000000000000000000001A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB", // p + "000000000000000000000000000000001A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAC", // p+1 + }; + + const char* testVectorExpected[] = { + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAA", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + }; + + for (int i = 0; i < sizeof(testVectorInput)/sizeof(const char*); ++ i) { + auto s = hexToBytes<64>(testVectorInput[i]); + auto k = scalar::fromBytesBE<8>(s); + fp r = fp::modPrime<8>(k); + auto fpExpected = fp::fromBytesBE(hexToBytes<48>(testVectorExpected[i]), false, false); + if(!fpExpected->equal(r)) + { + throw invalid_argument("r != expected for Mod"); + } + + } +} + +void TestExp() { + + const char* testVectorInput[] = { + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000001A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAA", // p-1 + }; + + const char* testVectorInput2[] = { + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAA", // p-1 + }; + + const char* testVectorExpected[] = { + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + }; + + for (int i = 0; i < sizeof(testVectorInput)/sizeof(const char*); ++ i) { + auto s = hexToBytes<64>(testVectorInput[i]); + auto b = fp::fromBytesBE(hexToBytes<48>(testVectorInput2[i]), false, false); + auto k = scalar::fromBytesBE<8>(s); + fp r = b->exp(k); + auto fpExpected = fp::fromBytesBE(hexToBytes<48>(testVectorExpected[i]), false, false); + if(!fpExpected->equal(r)) + { + throw invalid_argument("r != expected for Exp"); + } + + } +} + void TestFieldElementHelpers() { // fe @@ -2109,6 +2177,8 @@ int main() TestArithmeticOpraters(); TestSqrt(); + TestMod(); + TestExp(); TestG1Serialization(); TestG1SerializationGarbage(); @@ -2146,6 +2216,6 @@ int main() TestPopScheme(); TestExtraVectors(); - + return 0; } From 9f165d003832828f7833812f3a0d59f8efdc3b43 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 21 Nov 2023 15:21:14 +0800 Subject: [PATCH 35/40] Update comments to explain usage of _add/_lsubtract/_ldouble and multiply of fp. --- include/bls12-381/arithmetic.hpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/bls12-381/arithmetic.hpp b/include/bls12-381/arithmetic.hpp index 0a7de7d..1006b55 100644 --- a/include/bls12-381/arithmetic.hpp +++ b/include/bls12-381/arithmetic.hpp @@ -12,14 +12,21 @@ class fp; void init(bool cpu_features = true); void _add(fp* z, const fp* x, const fp* y); -void _ladd(fp* z, const fp* x, const fp* y); void _double(fp* z, const fp* x); -void _ldouble(fp* z, const fp* x); void _subtract(fp* z, const fp* x, const fp* y); -void _lsubtract(fp* z, const fp* x, const fp* y); void _negate(fp* z, const fp* x); void _square(fp* z, const fp* x); +// Those are low level calls that will not perform modular reduction after the operation +// Please use with caution. Overflow will happen. +void _ladd(fp* z, const fp* x, const fp* y); +void _ldouble(fp* z, const fp* x); +void _lsubtract(fp* z, const fp* x, const fp* y); + +// Multiplication will work fine as long as both operands are smaller than around 4p. +// The "smaller than 4p" here means the montgomery form itself as number is less than 4p. +// Therefore, at most ONE _ladd/_lsubstract/_ldouble is allowed before passing the result to _multiply, +// unless the algorithm makes sure the number is small. #if defined(__x86_64__) && defined(__ELF__) extern void _multiply(fp*, const fp*, const fp*); #elif defined(__x86_64__) From bd81dd3d55e970f546bf0a82d47228b25282ba03 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 21 Nov 2023 21:58:58 +0800 Subject: [PATCH 36/40] Add tests to guard behavior of out of range inputs to multiply function. --- test/unittests.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/unittests.cpp b/test/unittests.cpp index 6037ecb..c74f1b0 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -2163,6 +2163,61 @@ void TestExtraVectors() } } +void TestOutOfRangeInputs() { + // This test is to make sure multiplication wiil not fail if the inputs is just slightly larger than p + // The 4(p-1) limit may be not that strict. But we should only relax this limit if we are absolutely sure this + // will not cause problems all the methods calling _ladd/_lsubstract/_ldouble. + auto p = *fp::fromBytesBE(hexToBytes<48>("1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB"), false, true); + auto pminus1 = *fp::fromBytesBE(hexToBytes<48>("1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAA"), false, true); + // 4(p-1) * 4(p-1) will work + for (int i = 0 ; i < 3; ++ i) { + auto a = pminus1; + auto b = pminus1; + auto a2 = pminus1; + a2 = a2.fromMont().toMont(); + auto b2 = pminus1; + b2 = b2.fromMont().toMont(); + for (int j = 0; j < i; ++ j) { + _ldouble(&a,&a); + _ldouble(&b,&b); + a2 = a2.dbl(); + b2 = b2.dbl(); + } + auto c = a.multiply(b); + auto c2 = a2.multiply(b2); + + if (!c.equal(c2)) { + cout << "multiplication 2^i(p-1) * 2^i(p-1) failed: i = "<< i; + break; + } + + } + + // 2p * 2p will work + for (int i = 0 ; i < 2; ++ i) { + auto a = p; + auto b = p; + auto a2 = p; + a2 = a2.fromMont().toMont(); + auto b2 = p; + b2 = b2.fromMont().toMont(); + for (int j = 0; j < i; ++ j) { + _ldouble(&a,&a); + _ldouble(&b,&b); + a2 = a2.dbl(); + b2 = b2.dbl(); + } + auto c = a.multiply(b); + auto c2 = a2.multiply(b2); + + if (!c.equal(c2)) { + cout << "multiplication 2^i(p) * 2^i(p) failed: i = "<< i; + break; + } + + } +} + int main() { TestScalar(); @@ -2216,6 +2271,7 @@ int main() TestPopScheme(); TestExtraVectors(); + TestOutOfRangeInputs(); return 0; } From 1afc690663bace7c73f6ddd8f55df34f19eb4077 Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 29 Nov 2023 13:16:31 +0800 Subject: [PATCH 37/40] Fix comments. --- src/g.cpp | 10 ++++++---- test/unittests.cpp | 16 +++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/g.cpp b/src/g.cpp index cd0b021..6aac590 100644 --- a/src/g.cpp +++ b/src/g.cpp @@ -457,9 +457,10 @@ g1 g1::glvEndomorphism() const return t; } -// WeightedSum calculates multi exponentiation. Given pairs of G1 point and scalar values +// Given pairs of G1 point and scalar values // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n -// Length of points and scalars are expected to be equal, otherwise NONE is returned. +// If length of points and scalars are not the same, then missing points will be treated as the zero point +// and missing scalars will be treated as the zero scalar. g1 g1::weightedSum(std::span points, std::span> scalars, const std::function& yield) { const size_t effective_size = min(scalars.size(), points.size()); @@ -1212,9 +1213,10 @@ g2 g2::frobeniusMap(int64_t power) const return r; } -// WeightedSum calculates multi exponentiation. Given pairs of G2 point and scalar values +// Given pairs of G2 point and scalar values // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n -// Length of points and scalars are expected to be equal, otherwise NONE is returned. +// If length of points and scalars are not the same, then missing points will be treated as the zero point +// and missing scalars will be treated as the zero scalar. g2 g2::weightedSum(std::span points, std::span> scalars, const std::function& yield) { const size_t effective_size = min(scalars.size(), points.size()); diff --git a/test/unittests.cpp b/test/unittests.cpp index c74f1b0..307797b 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -400,7 +400,7 @@ void TestSqrt() { } if(!a.equal(asqrt) && !a.equal(asqrt.negate())) { - throw invalid_argument("fp2!= sqrt(fp.square)"); + throw invalid_argument("fp!= sqrt(fp.square)"); } } else { throw invalid_argument("failed to find sqrt for fp"); @@ -942,14 +942,13 @@ void TestG1WeightedSumBatch() g1 one = g1::one(); vector> scalars; vector bases; - // scalars: [s0,s1 ... s(n-1)] - // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] + for(int64_t i = 0; i < n; i++) { scalars.push_back(random_scalar()); bases.push_back(random_g1()); } - // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) + g1 expected, tmp; for(int64_t i = 0; i < n; i++) { @@ -959,7 +958,7 @@ void TestG1WeightedSumBatch() g1 result = g1::weightedSum(bases, scalars); if(!expected.equal(result)) { - throw invalid_argument("bad multi-exponentiation"); + throw invalid_argument("bad G1 weighted sum"); } }; @@ -1268,14 +1267,13 @@ void TestG2WeightedSumBatch() g2 one = g2::one(); vector> scalars; vector bases; - // scalars: [s0,s1 ... s(n-1)] - // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] + for(int64_t i = 0; i < n; i++) { scalars.push_back(random_scalar()); bases.push_back(random_g2()); } - // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) + g2 expected, tmp; for(int64_t i = 0; i < n; i++) { @@ -1285,7 +1283,7 @@ void TestG2WeightedSumBatch() g2 result = g2::weightedSum(bases, scalars); if(!expected.equal(result)) { - throw invalid_argument("bad multi-exponentiation"); + throw invalid_argument("bad G2 weighted sum"); } }; From ad21d2697a95a6842b933ddf9f71db4dd862f6ab Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 29 Nov 2023 23:45:40 +0800 Subject: [PATCH 38/40] Optimize fp::inverse() and add related tests and benchmarks. --- bench/eth_bench.cpp | 13 ++++++++ src/fp.cpp | 57 ++++++++++++++++++++++++++++------- test/unittests.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 129 insertions(+), 13 deletions(-) diff --git a/bench/eth_bench.cpp b/bench/eth_bench.cpp index f72692c..16d5b5d 100644 --- a/bench/eth_bench.cpp +++ b/bench/eth_bench.cpp @@ -268,6 +268,18 @@ void benchG2Add2() { } +void benchInverse() { + string testName = "Inverse"; + const int numIters = 10000; + fp a = random_fe(); + auto start = startStopwatch(); + + for (int i = 0; i < numIters; i++) { + a.inverse(); + } + endStopwatch(testName, start, numIters); +} + int main(int argc, char* argv[]) { benchG1Add(); @@ -279,4 +291,5 @@ int main(int argc, char* argv[]) benchPairing(); benchG1Add2(); benchG2Add2(); + benchInverse(); } \ No newline at end of file diff --git a/src/fp.cpp b/src/fp.cpp index b7fda85..8933835 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -219,6 +219,10 @@ fp fp::phi() const return c; } +// Origin algorithm comes from: +// [1] B.S.Kaliski Jr. The Montgomery inverse and its applications. IEEE Transactions on Computers, 44(8):1064–1065, August 1995. +// Modified according to: +// [2] Savas, Erkay, and Cetin Kaya Koç. "The Montgomery modular inverse-revisited." IEEE transactions on computers 49, no. 7 (2000): 763-766. fp fp::inverse() const { if(isZero()) @@ -230,9 +234,16 @@ fp fp::inverse() const fp s({1, 0, 0, 0, 0, 0}); fp r({0, 0, 0, 0, 0, 0}); int64_t k = 0; - uint64_t z = 0; bool found = false; + // Phase 1 + // Input: a*2^384 mod p < p, p. + // Output: a^{-1} * 2^{k-384} mod p, where 381 <= k <= 2 * 381. + // 1. Input is in Montgomery form, so the input is a*2^384 mod p. + // 2. All Phase 1 operations will treat fp as integer in Z instead of elements in GF(p). + // Therefore, NO modular reduction shall happen in Phase 1. + // 3. As proved in [1], s,r,u,v < 2p. + // Therefore, there shall be NO overflow in the process as p has 381 bits and we can hold 384 bits in fp. for(uint64_t i = 0; i < 768; i++) { if(v.isZero()) @@ -248,7 +259,7 @@ fp fp::inverse() const else if(v.isEven()) { v.div2(0); - z += r.mul2(); + r.mul2(); } else if(u.cmp(v) > 0) { @@ -262,7 +273,7 @@ fp fp::inverse() const _lsubtract(&v, &v, &u); v.div2(0); _ladd(&s, &s, &r); - z += r.mul2(); + r.mul2(); } k += 1; } @@ -272,12 +283,7 @@ fp fp::inverse() const return zero(); } - if(k < 381 || k > 381+384) - { - return zero(); - } - - if(r.cmp(MODULUS) >= 0 || z > 0) + if(r.cmp(MODULUS) >= 0) { _lsubtract(&r, &r, &MODULUS); } @@ -285,10 +291,39 @@ fp fp::inverse() const _lsubtract(&u, &u, &r); // Phase 2 - for(uint64_t i = k; i < 384*2; i++) + // Input: u = a^{-1} * 2^{k-384} mod p, k where 381 <= k <= 2*381 + // Output: a^{-1} * 2^384 mod p + + // Process for 381 <= k <= 384 + // Generate new u, k pair that + // k' = k + 384 + // u' = u * 2^{2*384} * 2^{-384} mod p + // u' = a^{-1} * 2^{k'-384} mod p will still hold. + // Will hit this case if and only if input is fp::one() for the current p. + if (k <= 384) { + u.multiplyAssign(fp::R2); + k += 384; + } + + // u = u * 2^{2*384} * 2^{-384} mod p = a^{-1} * 2^k mod p + u.multiplyAssign(fp::R2); + + // This case should not happen mathmatically. + // Leave it here as sanity check to guard against access vialotion later. + if(k > 2 * 384) { - _double(&u, &u); + return zero(); } + + // 384 < k <= 2 * 384 + // 0 <= power < 384 + uint64_t power = 2*384 - k; + fp fpPower; + fpPower.d[power/64] = ((uint64_t)1) << (power%64); + + // result = u * 2^(2*384-k) * 2^{-384} = a^{-1} * 2^k * 2^{384-k} mod p = a^{-1} * 2^384 mod p + u.multiplyAssign(fpPower); + return u; } diff --git a/test/unittests.cpp b/test/unittests.cpp index 307797b..a31eec3 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -427,6 +427,54 @@ void TestSqrt() { } +void TestInverse() { + if (!fp::one().inverse().equal(fp::one())) { + throw invalid_argument("1^-1 != 1"); + } + + auto two = fp::one().dbl(); + if (!two.multiply(two.inverse()).equal(fp::one())) { + throw invalid_argument("2 * 2^-1 != 1"); + } + + auto pminus1 = *fp::fromBytesBE(hexToBytes<48>("1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAA"), false, true); + if (!pminus1.multiply(pminus1.inverse()).equal(fp::one())) { + throw invalid_argument("(p-1) * (p-1)^-1 != 1"); + } + + for (int i = 0; i < 100; ++ i) { + fp a = random_fe(); + auto b = a.inverse(); + if (!a.multiply(b).equal(fp::one())) { + throw invalid_argument("fp * fp^-1 != 1"); + } + } + + for (int i = 0; i < 100; ++ i) { + fp2 a = random_fe2(); + auto b = a.inverse(); + if (!a.multiply(b).equal(fp2::one())) { + throw invalid_argument("fp2 * fp2^-1 != 1"); + } + } + + for (int i = 0; i < 100; ++ i) { + fp6 a = random_fe6(); + auto b = a.inverse(); + if (!a.multiply(b).equal(fp6::one())) { + throw invalid_argument("fp * fp^-1 != 1"); + } + } + + for (int i = 0; i < 100; ++ i) { + fp12 a = random_fe12(); + auto b = a.inverse(); + if (!a.multiply(b).equal(fp12::one())) { + throw invalid_argument("fp * fp^-1 != 1"); + } + } +} + void TestMod() { const char* testVectorInput[] = { @@ -2167,6 +2215,8 @@ void TestOutOfRangeInputs() { // will not cause problems all the methods calling _ladd/_lsubstract/_ldouble. auto p = *fp::fromBytesBE(hexToBytes<48>("1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB"), false, true); auto pminus1 = *fp::fromBytesBE(hexToBytes<48>("1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAA"), false, true); + // 2^383, largest possible input to multiplication during the inverse(). + auto two383 = *fp::fromBytesBE(hexToBytes<48>("400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), false, true); // 4(p-1) * 4(p-1) will work for (int i = 0 ; i < 3; ++ i) { auto a = pminus1; @@ -2186,7 +2236,7 @@ void TestOutOfRangeInputs() { if (!c.equal(c2)) { cout << "multiplication 2^i(p-1) * 2^i(p-1) failed: i = "<< i; - break; + throw; } } @@ -2210,10 +2260,27 @@ void TestOutOfRangeInputs() { if (!c.equal(c2)) { cout << "multiplication 2^i(p) * 2^i(p) failed: i = "<< i; - break; + throw; } } + + { + auto a = two383; + auto b = two383; + auto a2 = two383; + a2 = a2.fromMont().toMont(); + auto b2 = two383; + b2 = b2.fromMont().toMont(); + + auto c = a.multiply(b); + auto c2 = a2.multiply(b2); + + if (!c.equal(c2)) { + cout << "multiplication 2^383 * 2^383 failed"; + throw; + } + } } int main() @@ -2230,6 +2297,7 @@ int main() TestArithmeticOpraters(); TestSqrt(); + TestInverse(); TestMod(); TestExp(); From 6818a313681575b18cf815ef1a57fa7ef924e2c2 Mon Sep 17 00:00:00 2001 From: yarkin Date: Thu, 30 Nov 2023 01:34:01 +0800 Subject: [PATCH 39/40] Add comments on default comparisons. --- include/bls12-381/fp.hpp | 9 ++++++++- include/bls12-381/g.hpp | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/bls12-381/fp.hpp b/include/bls12-381/fp.hpp index 4ed0ad5..39363a8 100644 --- a/include/bls12-381/fp.hpp +++ b/include/bls12-381/fp.hpp @@ -62,7 +62,11 @@ class fp bool isLexicographicallyLargest() const; template static fp modPrime(const std::array& k); - std::strong_ordering operator<=>(const fp& e) const { return cmp(e); } + // Those operators are defined to support set and map. + // They are mathematically correctly in certain cases. + // However, there are still ambiguity there as the fp can be in Montgomery form or not. + // Please avoid using those operators. + constexpr std::strong_ordering operator<=>(const fp& e) const { return cmp(e); } static const fp MODULUS; // base field modulus: p = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 or 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB static const uint64_t INP; // INP = -(p^{-1} mod 2^64) mod 2^64 @@ -124,6 +128,9 @@ class fp2 bool isQuadraticNonResidue() const; bool isLexicographicallyLargest() const; + // Those operators are defined to support set and map. + // They are not mathematically correct. + // DO NOT use them to compare fp2. auto operator<=>(const fp2&) const = default; static const fp2 negativeOne2; diff --git a/include/bls12-381/g.hpp b/include/bls12-381/g.hpp index 99df525..9daad3a 100644 --- a/include/bls12-381/g.hpp +++ b/include/bls12-381/g.hpp @@ -61,6 +61,9 @@ class g1 g1 clearCofactor() const; g1 glvEndomorphism() const; + // Those operators are defined to support set and map. + // They are not mathematically correct. + // DO NOT use them to compare g1. auto operator<=>(const g1&) const = default; static g1 weightedSum(std::span points, std::span> scalars, const std::function& yield = std::function()); @@ -121,6 +124,9 @@ class g2 g2 clearCofactor() const; g2 frobeniusMap(int64_t power) const; + // Those operators are defined to support set and map. + // They are not mathematically correct. + // DO NOT use them to compare g2. auto operator<=>(const g2&) const = default; static g2 weightedSum(std::span points, std::span> scalars, const std::function& yield = std::function()); From 8871e5efefdcb0f2a1315ed0942a6124022a7ac5 Mon Sep 17 00:00:00 2001 From: yarkin Date: Thu, 30 Nov 2023 01:34:36 +0800 Subject: [PATCH 40/40] Make cmp constexpr so that all <=> for fp/fp2/g1/g2 become constexpr. --- include/bls12-381/fp.hpp | 15 ++++++++++++++- src/fp.cpp | 5 ----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/bls12-381/fp.hpp b/include/bls12-381/fp.hpp index 39363a8..6519647 100644 --- a/include/bls12-381/fp.hpp +++ b/include/bls12-381/fp.hpp @@ -34,7 +34,20 @@ class fp bool isEven() const; bool isZero() const; bool isOne() const; - std::strong_ordering cmp(const fp& e) const; + constexpr std::strong_ordering cmp(const fp& e) const { + for(int64_t i = 5; i >= 0; i--) + { + if(d[i] < e.d[i]) + { + return std::strong_ordering::less; + } + if(d[i] > e.d[i]) + { + return std::strong_ordering::greater; + } + } + return std::strong_ordering::equal; + }; bool equal(const fp& e) const; bool sign() const; diff --git a/src/fp.cpp b/src/fp.cpp index 8933835..4379033 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -94,11 +94,6 @@ bool fp::isOne() const return equal(R1); } -std::strong_ordering fp::cmp(const fp& e) const -{ - return scalar::cmp<6>(d, e.d); -} - bool fp::equal(const fp& e) const { return d[0] == e.d[0] && d[1] == e.d[1] && d[2] == e.d[2] && d[3] == e.d[3] && d[4] == e.d[4] && d[5] == e.d[5];