From 09ac2e90d5371785f7b538bfcad5991d813a6ef9 Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 20 Apr 2023 22:58:27 -0500 Subject: [PATCH 1/6] feat: implement std::array based serialization --- include/dashbls/elements.hpp | 3 ++ src/elements.cpp | 68 ++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/include/dashbls/elements.hpp b/include/dashbls/elements.hpp index 6832b31f3..f4743a9f7 100644 --- a/include/dashbls/elements.hpp +++ b/include/dashbls/elements.hpp @@ -59,6 +59,7 @@ class G1Element { GTElement Pair(const G2Element &b) const; uint32_t GetFingerprint(bool fLegacy = false) const; std::vector Serialize(bool fLegacy = false) const; + std::array SerializeToArray(bool fLegacy = false) const; G1Element Copy(); friend bool operator==(const G1Element &a, const G1Element &b); @@ -102,6 +103,7 @@ class G2Element { G2Element Negate() const; GTElement Pair(const G1Element &a) const; std::vector Serialize(bool fLegacy = false) const; + std::array SerializeToArray(bool fLegacy = false); G2Element Copy(); friend bool operator==(G2Element const &a, G2Element const &b); @@ -127,6 +129,7 @@ class GTElement { void Serialize(uint8_t *buffer) const; std::vector Serialize() const; + std::array SerializeToArray() const; friend bool operator==(GTElement const &a, GTElement const &b); friend bool operator!=(GTElement const &a, GTElement const &b); diff --git a/src/elements.cpp b/src/elements.cpp index 278af8cd8..e032f8c99 100644 --- a/src/elements.cpp +++ b/src/elements.cpp @@ -190,6 +190,29 @@ std::vector G1Element::Serialize(const bool fLegacy) const { return std::vector(buffer + 1, buffer + 1 + G1Element::SIZE); } +std::array G1Element::SerializeToArray(const bool fLegacy) const { + uint8_t buffer[G1Element::SIZE + 1]; + g1_write_bin(buffer, G1Element::SIZE + 1, p, 1); + + if (buffer[0] == 0x00) { // infinity + std::array result{}; + result[0] = 0xc0; + return result; + } + + if (buffer[0] == 0x03) { // sign bit set + buffer[1] |= fLegacy ? 0x80 : 0x20; + } + + if (!fLegacy) { + buffer[1] |= 0x80; // indicate compression + } + + std::array result{}; + std::copy_n(buffer + 1, G1Element::SIZE, result.begin()); + return result; +} + bool operator==(const G1Element & a, const G1Element &b) { return g1_cmp(a.p, b.p) == RLC_EQ; @@ -422,6 +445,44 @@ std::vector G2Element::Serialize(const bool fLegacy) const { return result; } +std::array G2Element::SerializeToArray(const bool fLegacy) const { + uint8_t buffer[G2Element::SIZE + 1]; + g2_write_bin(buffer, G2Element::SIZE + 1, (g2_st*)q, 1); + + std::array result{}; + + if (buffer[0] == 0x00) { // infinity + result.fill(0); + result[0] = 0xc0; + return result; + } + + if (fLegacy) { + if (buffer[0] == 0x03) { // sign bit set + buffer[1] |= 0x80; + } + } else { + // remove leading 3 bits + buffer[1] &= 0x1f; + buffer[49] &= 0x1f; + if (buffer[0] == 0x03) { + buffer[49] |= 0xa0; // swapped later to 0 + } else { + buffer[49] |= 0x80; + } + } + + if (fLegacy) { + std::memcpy(result.data(), buffer + 1, G2Element::SIZE); + } else { + // Swap buffer, relic uses the opposite ordering for Fq2 elements + std::memcpy(result.data(), buffer + 1 + G2Element::SIZE / 2, G2Element::SIZE / 2); + std::memcpy(result.data() + G2Element::SIZE / 2, buffer + 1, G2Element::SIZE / 2); + } + + return result; +} + bool operator==(G2Element const& a, G2Element const& b) { return g2_cmp((g2_st*)a.q, (g2_st*)b.q) == RLC_EQ; @@ -551,4 +612,11 @@ std::vector GTElement::Serialize() const return data; } +std::array GTElement::SerializeToArray() const +{ + std::array data{}; + Serialize(data.data()); + return data; +} + } // end namespace bls From d1b3d244f0f2a4b41b059b81605442daa7adae1d Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 20 Apr 2023 23:17:27 -0500 Subject: [PATCH 2/6] fixup add const --- include/dashbls/elements.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dashbls/elements.hpp b/include/dashbls/elements.hpp index f4743a9f7..95937f62d 100644 --- a/include/dashbls/elements.hpp +++ b/include/dashbls/elements.hpp @@ -103,7 +103,7 @@ class G2Element { G2Element Negate() const; GTElement Pair(const G1Element &a) const; std::vector Serialize(bool fLegacy = false) const; - std::array SerializeToArray(bool fLegacy = false); + std::array SerializeToArray(bool fLegacy = false) const; G2Element Copy(); friend bool operator==(G2Element const &a, G2Element const &b); From 677db58fc3b8fcd9b4bd2bac8a2991169109b74e Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 20 Apr 2023 23:50:36 -0500 Subject: [PATCH 3/6] add SerializeToArray for PrivateKey --- include/dashbls/privatekey.hpp | 1 + src/privatekey.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/dashbls/privatekey.hpp b/include/dashbls/privatekey.hpp index beebbb05a..d02a7d292 100644 --- a/include/dashbls/privatekey.hpp +++ b/include/dashbls/privatekey.hpp @@ -82,6 +82,7 @@ class PrivateKey { // Serialize the key into bytes void Serialize(uint8_t *buffer) const; std::vector Serialize(bool fLegacy = false) const; + std::array SerializeToArray(bool fLegacy = false) const; G2Element SignG2( const uint8_t *msg, diff --git a/src/privatekey.cpp b/src/privatekey.cpp index 865507dfc..d4dd32d11 100644 --- a/src/privatekey.cpp +++ b/src/privatekey.cpp @@ -284,6 +284,13 @@ std::vector PrivateKey::Serialize(const bool fLegacy) const return data; } +std::array PrivateKey::SerializeToArray(bool fLegacy) const +{ + std::array data{}; + Serialize(data.data()); + return data; +} + G2Element PrivateKey::SignG2( const uint8_t *msg, size_t len, From 0f3705b7dbeee7174a4ad562d8f98d5b4e3839cf Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 4 Dec 2024 09:33:43 -0600 Subject: [PATCH 4/6] simplify G1Element::Serialize by using G1Element::SerializeToArray --- src/elements.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/elements.cpp b/src/elements.cpp index e032f8c99..d8d257e02 100644 --- a/src/elements.cpp +++ b/src/elements.cpp @@ -171,23 +171,8 @@ uint32_t G1Element::GetFingerprint(const bool fLegacy) const } std::vector G1Element::Serialize(const bool fLegacy) const { - uint8_t buffer[G1Element::SIZE + 1]; - g1_write_bin(buffer, G1Element::SIZE + 1, p, 1); - - if (buffer[0] == 0x00) { // infinity - std::vector result(G1Element::SIZE, 0); - result[0] = 0xc0; - return result; - } - - if (buffer[0] == 0x03) { // sign bit set - buffer[1] |= fLegacy ? 0x80 : 0x20; - } - - if (!fLegacy) { - buffer[1] |= 0x80; // indicate compression - } - return std::vector(buffer + 1, buffer + 1 + G1Element::SIZE); + const auto arr = G1Element::SerializeToArray(fLegacy); + return std::vector{arr.begin(), arr.end()}; } std::array G1Element::SerializeToArray(const bool fLegacy) const { From a3afed8669d7dd0bc5ea1061c305038976074c68 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 4 Dec 2024 09:41:27 -0600 Subject: [PATCH 5/6] refactor: continued reduced duplication --- src/elements.cpp | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/src/elements.cpp b/src/elements.cpp index d8d257e02..25c110f1d 100644 --- a/src/elements.cpp +++ b/src/elements.cpp @@ -394,40 +394,8 @@ G2Element G2Element::Negate() const GTElement G2Element::Pair(const G1Element& a) const { return a & (*this); } std::vector G2Element::Serialize(const bool fLegacy) const { - uint8_t buffer[G2Element::SIZE + 1]; - g2_write_bin(buffer, G2Element::SIZE + 1, (g2_st*)q, 1); - - if (buffer[0] == 0x00) { // infinity - std::vector result(G2Element::SIZE, 0); - result[0] = 0xc0; - return result; - } - - if (fLegacy) { - if (buffer[0] == 0x03) { // sign bit set - buffer[1] |= 0x80; - } - } else { - // remove leading 3 bits - buffer[1] &= 0x1f; - buffer[49] &= 0x1f; - if (buffer[0] == 0x03) { - buffer[49] |= 0xa0; // swapped later to 0 - } else { - buffer[49] |= 0x80; - } - } - - std::vector result(G2Element::SIZE, 0); - if (fLegacy) { - std::memcpy(result.data(), buffer + 1, G2Element::SIZE); - } else { - // Swap buffer, relic uses the opposite ordering for Fq2 elements - std::memcpy(result.data(), buffer + 1 + G2Element::SIZE / 2, G2Element::SIZE / 2); - std::memcpy(result.data() + G2Element::SIZE / 2, buffer + 1, G2Element::SIZE / 2); - } - - return result; + const auto arr = G2Element::SerializeToArray(fLegacy); + return std::vector{arr.begin(), arr.end()}; } std::array G2Element::SerializeToArray(const bool fLegacy) const { From 30aa085b2b8a169c157d3dfcba2caf604e8d3e54 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 4 Dec 2024 10:02:57 -0600 Subject: [PATCH 6/6] fixup: apply code review comments --- src/elements.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/elements.cpp b/src/elements.cpp index 25c110f1d..b0c747af8 100644 --- a/src/elements.cpp +++ b/src/elements.cpp @@ -171,16 +171,16 @@ uint32_t G1Element::GetFingerprint(const bool fLegacy) const } std::vector G1Element::Serialize(const bool fLegacy) const { - const auto arr = G1Element::SerializeToArray(fLegacy); - return std::vector{arr.begin(), arr.end()}; + const auto arr = G1Element::SerializeToArray(fLegacy); + return std::vector{arr.begin(), arr.end()}; } std::array G1Element::SerializeToArray(const bool fLegacy) const { uint8_t buffer[G1Element::SIZE + 1]; g1_write_bin(buffer, G1Element::SIZE + 1, p, 1); + std::array result{}; if (buffer[0] == 0x00) { // infinity - std::array result{}; result[0] = 0xc0; return result; } @@ -193,7 +193,6 @@ std::array G1Element::SerializeToArray(const bool fLeg buffer[1] |= 0x80; // indicate compression } - std::array result{}; std::copy_n(buffer + 1, G1Element::SIZE, result.begin()); return result; } @@ -394,8 +393,8 @@ G2Element G2Element::Negate() const GTElement G2Element::Pair(const G1Element& a) const { return a & (*this); } std::vector G2Element::Serialize(const bool fLegacy) const { - const auto arr = G2Element::SerializeToArray(fLegacy); - return std::vector{arr.begin(), arr.end()}; + const auto arr = G2Element::SerializeToArray(fLegacy); + return std::vector{arr.begin(), arr.end()}; } std::array G2Element::SerializeToArray(const bool fLegacy) const {