From 71e1784875670c81c6ae3d4d48bf35a6369f9406 Mon Sep 17 00:00:00 2001
From: Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
Date: Tue, 3 Sep 2024 12:28:33 +0300
Subject: [PATCH] work in progress on implementing the marshalling #318

Fixing the compilation.

Finished with marshalling of all supported curves #318

remove comment

rm curve25519
---
 .../nil/crypto3/algebra/curves/curve25519.hpp |    2 +-
 .../algebra/curves/detail/babyjubjub/g1.hpp   |    1 -
 .../algebra/curves/detail/curve25519/g1.hpp   |    1 -
 libs/algebra/test/curves.cpp                  |    2 -
 .../algebra/processing/alt_bn128.hpp          |  284 ++++
 .../algebra/processing/babyjubjub.hpp         |  171 +++
 .../marshalling/algebra/processing/bls12.hpp  |  549 ++++++++
 .../algebra/processing/curve_element.hpp      | 1159 +----------------
 .../processing/detail/curve_element.hpp       |   17 +-
 .../algebra/processing/ed25519.hpp            |  161 +++
 .../marshalling/algebra/processing/jubjub.hpp |  150 +++
 .../marshalling/algebra/processing/mnt4.hpp   |  312 +++++
 .../marshalling/algebra/processing/mnt6.hpp   |  323 +++++
 .../marshalling/algebra/processing/pallas.hpp |  186 +++
 .../algebra/processing/secp_k1.hpp            |  190 +++
 .../algebra/processing/secp_r1.hpp            |  190 +++
 .../marshalling/algebra/processing/vesta.hpp  |  186 +++
 .../algebra/test/curve_element.cpp            |  104 +-
 18 files changed, 2770 insertions(+), 1218 deletions(-)
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/alt_bn128.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/babyjubjub.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/bls12.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/ed25519.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/jubjub.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/mnt4.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/mnt6.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/pallas.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_k1.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_r1.hpp
 create mode 100644 libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/vesta.hpp

diff --git a/libs/algebra/include/nil/crypto3/algebra/curves/curve25519.hpp b/libs/algebra/include/nil/crypto3/algebra/curves/curve25519.hpp
index 38395ffd37..6fbae6d144 100644
--- a/libs/algebra/include/nil/crypto3/algebra/curves/curve25519.hpp
+++ b/libs/algebra/include/nil/crypto3/algebra/curves/curve25519.hpp
@@ -46,7 +46,7 @@ namespace nil {
                     typedef typename policy_type::scalar_field_type scalar_field_type;
 
                     template<typename Coordinates = coordinates::extended_with_a_minus_1,
-                             typename Form = forms::montgomery>
+                             typename Form = forms::twisted_edwards>
                     using g1_type = typename detail::curve25519_g1<Form, Coordinates>;
                 };
             }    // namespace curves
diff --git a/libs/algebra/include/nil/crypto3/algebra/curves/detail/babyjubjub/g1.hpp b/libs/algebra/include/nil/crypto3/algebra/curves/detail/babyjubjub/g1.hpp
index 3a429a479f..ff014051ed 100644
--- a/libs/algebra/include/nil/crypto3/algebra/curves/detail/babyjubjub/g1.hpp
+++ b/libs/algebra/include/nil/crypto3/algebra/curves/detail/babyjubjub/g1.hpp
@@ -31,7 +31,6 @@
 
 #include <nil/crypto3/algebra/curves/forms.hpp>
 #include <nil/crypto3/algebra/curves/detail/forms/twisted_edwards/element_g1_affine.hpp>
-#include <nil/crypto3/algebra/curves/detail/forms/montgomery/element_g1_affine.hpp>
 
 namespace nil {
     namespace crypto3 {
diff --git a/libs/algebra/include/nil/crypto3/algebra/curves/detail/curve25519/g1.hpp b/libs/algebra/include/nil/crypto3/algebra/curves/detail/curve25519/g1.hpp
index b445a24020..cbaed496cc 100644
--- a/libs/algebra/include/nil/crypto3/algebra/curves/detail/curve25519/g1.hpp
+++ b/libs/algebra/include/nil/crypto3/algebra/curves/detail/curve25519/g1.hpp
@@ -31,7 +31,6 @@
 #include <nil/crypto3/algebra/curves/detail/forms/twisted_edwards/coordinates.hpp>
 #ifdef __ZKLLVM__
 #else
-// #include <nil/crypto3/algebra/curves/detail/forms/montgomery/xz/element_g1.hpp>
 #include <nil/crypto3/algebra/curves/detail/forms/twisted_edwards/extended_with_a_minus_1/element_g1.hpp>
 #endif
 
diff --git a/libs/algebra/test/curves.cpp b/libs/algebra/test/curves.cpp
index 1dd208bd17..d3ff117875 100644
--- a/libs/algebra/test/curves.cpp
+++ b/libs/algebra/test/curves.cpp
@@ -50,7 +50,6 @@
 #include <nil/crypto3/algebra/curves/secp_k1.hpp>
 #include <nil/crypto3/algebra/curves/secp_r1.hpp>
 #include <nil/crypto3/algebra/curves/ed25519.hpp>
-#include <nil/crypto3/algebra/curves/curve25519.hpp>
 #include <nil/crypto3/algebra/curves/detail/forms/short_weierstrass/coordinates.hpp>
 
 
@@ -573,7 +572,6 @@ BOOST_DATA_TEST_CASE(curve_operation_test_edwards25519, string_data("curve_opera
     using policy_type = curves::ed25519::g1_type<>;
 
     static_assert(std::is_same<typename curves::ed25519::g1_type<>::curve_type, curves::ed25519>::value);
-    static_assert(std::is_same<typename curves::curve25519::g1_type<>::curve_type, curves::curve25519>::value);
 
     curve_operation_test_twisted_edwards<policy_type>(data_set, fp_extended_curve_twisted_edwards_test_init<policy_type>);
 }
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/alt_bn128.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/alt_bn128.hpp
new file mode 100644
index 0000000000..ae71759f61
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/alt_bn128.hpp
@@ -0,0 +1,284 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
+// Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_ALT_BN128_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_ALT_BN128_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+#include <limits>
+#include <iterator>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/alt_bn128.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::alt_bn128_254::template g1_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::alt_bn128_254::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using g1_value_type = group_value_type;
+                    using g1_field_type = typename group_value_type::field_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+
+                        /* Point is always encoded in compressed form, only X coordinate.
+                         * Highest bit is Infinity flag
+                         * Second highest bit is sign of Y coordinate */
+
+                        using chunk_type = typename TIter::value_type;
+                        constexpr static const chunk_type I_bit = 0x80;
+                        constexpr static const chunk_type S_bit = 0x40;
+
+                        auto point_affine = point.to_affine();
+
+                        write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+
+                        if (point_affine.is_zero()) {
+                            *iter |= I_bit;
+                        }
+
+                        if (detail::sign_gf_p<g1_field_type>(point_affine.Y)) {
+                            *iter |= S_bit;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::alt_bn128_254::template g2_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::alt_bn128_254::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using g2_value_type = group_value_type;
+                    using g2_field_type = typename group_value_type::field_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+
+                        /* Point is always encoded in compressed form, only X coordinate.
+                         * Highest bit is Infinity flag
+                         * Second highest bit is sign of Y coordinate */
+
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+
+                        constexpr static const chunk_type I_bit = 0x80;
+                        constexpr static const chunk_type S_bit = 0x40;
+                        typename group_type::curve_type::template g2_type<
+                            typename algebra::curves::coordinates::affine,
+                            form>::value_type point_affine = point.to_affine();
+
+                        TIter write_iter = iter;
+                        // We assume here, that write_data doesn't change the iter
+                        write_data<sizeof_field_element, endianness>(
+                            static_cast<typename group_value_type::field_type::integral_type>(
+                                point_affine.X.data[1].data),
+                            write_iter);
+                        write_iter += sizeof_field_element_chunks_count;
+                        // We assume here, that write_data doesn't change the iter
+                        write_data<sizeof_field_element, endianness>(
+                            static_cast<typename group_value_type::field_type::integral_type>(
+                                point_affine.X.data[0].data),
+                            write_iter);
+
+                        if(point.is_zero()) {
+                            *iter |= I_bit;
+                        }
+
+                        if (detail::sign_gf_p<g2_field_type>(point_affine.Y)) {
+                            *iter |= S_bit;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::alt_bn128_254::template g1_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::alt_bn128_254::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        using g1_value_type = group_value_type;
+                        using g1_field_type = typename group_value_type::field_type;
+                        using g1_field_value_type = typename g1_field_type::value_type;
+                        using integral_type = typename g1_value_type::field_type::integral_type;
+
+                        chunk_type I_bit = *iter & 0x80;
+                        chunk_type S_bit = *iter & 0x40;
+
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        if (I_bit) {
+                            // point at infinity
+                            point = g1_value_type();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod.pow(3) + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
+                        if (Y_bit == bool(S_bit)) {
+                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::alt_bn128_254::template g2_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::alt_bn128_254::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+                        using g2_value_type = group_value_type;
+                        using g2_field_type = typename g2_value_type::field_type;
+                        using g2_field_value_type = typename g2_field_type::value_type;
+                        using integral_type = typename g2_value_type::field_type::integral_type;
+
+                        chunk_type I_bit = *iter & 0x80;
+                        chunk_type S_bit = *iter & 0x40;
+
+                        TIter read_iter = iter;
+                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+                        read_iter += sizeof_field_element_chunks_count;
+                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+
+                        if (I_bit) {
+                            // point at infinity
+                            point = group_value_type();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        g2_field_value_type x_mod(x_0, x_1);
+                        g2_field_value_type y2_mod = x_mod.pow(3) + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g2_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
+                        if (Y_bit == bool(S_bit)) {
+                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/babyjubjub.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/babyjubjub.hpp
new file mode 100644
index 0000000000..76e3ce76db
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/babyjubjub.hpp
@@ -0,0 +1,171 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
+// Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_BABYJUBJUB_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_BABYJUBJUB_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+#include <iterator>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/fields/field.hpp>
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/babyjubjub.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                // Encoding of babyjubjub curve as described in Nocturne:
+                // https://nocturne-xyz.gitbook.io/nocturne/protocol-details/encodings
+                // Only Y coordinate is encoded, plus 's' - the "sign" of X coordinate
+                // uint256(signBit) << 254 | y
+                // TODO: update reference or invent our own rules
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::little_endian,
+                    typename algebra::curves::babyjubjub::template g1_type<Coordinates,
+                                                                           algebra::curves::forms::twisted_edwards>> {
+                    using group_type =
+                        typename algebra::curves::babyjubjub::template g1_type<Coordinates,
+                                                                               algebra::curves::forms::twisted_edwards>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::little_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+                    using encoded_integral_type = typename algebra::fields::field<256>::integral_type;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                    std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                        process(const group_value_type &point, TIter &iter) {
+                        using base_field_type = typename group_type::field_type;
+                        using base_integral_type = typename base_field_type::integral_type;
+
+                        constexpr std::size_t encoded_size = 32;
+                        using encoded_value_type = std::array<std::uint8_t, encoded_size>;
+                        encoded_value_type encoded_value {0};
+
+                        auto point_affine = point.to_affine();
+
+                        /* Zero point is encoded as (0,1) */
+                        if (point.is_zero()) {
+                            point_affine.Y = 1u;
+                            point_affine.X = 0u;
+                        }
+
+                        uint8_t s = detail::sign_gf_p<base_field_type>(point_affine.X) ? (0x40) : 0;
+
+                        auto tmp_iter = std::begin(encoded_value);
+                        write_data<encoded_size, endianness>(static_cast<base_integral_type>(point_affine.Y.data),
+                                tmp_iter);
+                        assert(!(encoded_value[encoded_size - 1] & 0xC0));
+
+                        encoded_value[encoded_size - 1] |= s;
+
+                        std::copy(std::cbegin(encoded_value), std::cend(encoded_value), iter);
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::little_endian,
+                    typename algebra::curves::babyjubjub::template g1_type<Coordinates,
+                                                                           algebra::curves::forms::twisted_edwards>> {
+                    using group_type =
+                        typename algebra::curves::babyjubjub::template g1_type<Coordinates,
+                                                                               algebra::curves::forms::twisted_edwards>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::little_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    using group_affine_value_type =
+                            typename algebra::curves::babyjubjub::g1_type<algebra::curves::coordinates::affine,
+                                                                          form>::value_type;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                        process(group_value_type &point, TIter &iter)
+                    {
+
+                        // somehow add size check of container pointed by iter
+                        // assert(TSize == std::distance(first, last));
+                        using base_field_type = typename group_type::field_type;
+                        using base_integral_type = typename base_field_type::integral_type;
+                        using group_affine_value_type =
+                            typename algebra::curves::babyjubjub::g1_type<algebra::curves::coordinates::affine,
+                                                                          form>::value_type;
+                        constexpr std::size_t encoded_size = 32;
+                        static_assert(encoded_size ==
+                                          (params_type::bit_length() / 8 + (params_type::bit_length() % 8 ? 1 : 0)),
+                                      "wrong size");
+
+                        base_integral_type y =
+                            read_data<params_type::bit_length(), base_integral_type, endianness>(iter);
+                        bool sign = *(iter + encoded_size - 1) & (1 << 6);
+
+                        auto decoded_point_affine =
+                                detail::recover_x<group_affine_value_type>(y, sign);
+
+                        if (!decoded_point_affine) {
+                            return decoded_point_affine.error();
+                        }
+
+                        // TODO: remove hard-coded call for type conversion, implement type conversion between
+                        // coordinates
+                        //  through operator
+                        point = decoded_point_affine.value();
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_BABYJUBJUB_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/bls12.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/bls12.hpp
new file mode 100644
index 0000000000..5b821ee012
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/bls12.hpp
@@ -0,0 +1,549 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
+// Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_BLS12_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_BLS12_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/bls12.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+
+                /* Specialization for bls12_377::g2_type */
+                template<typename Coordinates>
+                struct curve_element_marshalling_params<algebra::curves::bls12_377::
+                template g2_type<Coordinates, algebra::curves::forms::short_weierstrass> >
+                {
+                    using group_type = algebra::curves::bls12_381::template
+                        g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+
+                    static constexpr std::size_t length() {
+                        return bit_length() / 8 + ((bit_length() % 8) != 0);
+                    }
+
+                    static constexpr std::size_t min_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t max_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t bit_length() {
+                        constexpr std::size_t modulus_bits_round_up = (group_type::field_type::modulus_bits + 7) & ~7;
+                        return modulus_bits_round_up * group_type::field_type::arity;
+                    }
+
+                    static constexpr std::size_t min_bit_length() {
+                        return bit_length();
+                    }
+
+                    static constexpr std::size_t max_bit_length() {
+                        return bit_length();
+                    }
+                };
+
+                /* Specialization for bls12_381::g2_type */
+                template<typename Coordinates>
+                struct curve_element_marshalling_params<algebra::curves::bls12_381::
+                template g2_type<Coordinates, algebra::curves::forms::short_weierstrass> >
+                {
+                    using group_type = algebra::curves::bls12_381::template
+                        g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+
+                    static constexpr std::size_t length() {
+                        return bit_length() / 8 + ((bit_length() % 8) != 0);
+                    }
+
+                    static constexpr std::size_t min_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t max_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t bit_length() {
+                        constexpr std::size_t modulus_bits_round_up = (group_type::field_type::modulus_bits + 7) & ~7;
+                        return modulus_bits_round_up * group_type::field_type::arity;
+                    }
+
+                    static constexpr std::size_t min_bit_length() {
+                        return bit_length();
+                    }
+
+                    static constexpr std::size_t max_bit_length() {
+                        return bit_length();
+                    }
+                };
+
+                template<typename Endianness, typename Coordinates>
+                struct curve_element_writer<
+                    Endianness,
+                    typename algebra::curves::bls12_381::template g1_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::bls12_381::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = Endianness;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const chunk_type I_bit = 0x40;
+                        typename group_type::curve_type::template g1_type<typename algebra::curves::coordinates::affine,
+                                                                          form>::value_type point_affine =
+                            point.to_affine();
+                        chunk_type m_unit = detail::evaluate_m_unit<chunk_type>(point, true);
+                        if (!(I_bit & m_unit)) {
+                            // We assume here, that write_data doesn't change the iter
+                            write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+                        }
+                        (*iter) |= m_unit;
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+
+                template<typename Endianness, typename Coordinates>
+                struct curve_element_writer<
+                    Endianness,
+                    typename algebra::curves::bls12_381::template g2_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::bls12_381::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = Endianness;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+
+                        constexpr static const chunk_type I_bit = 0x40;
+                        typename group_type::curve_type::template g2_type<typename algebra::curves::coordinates::affine,
+                                                                          form>::value_type point_affine =
+                            point.to_affine();
+                        chunk_type m_unit = detail::evaluate_m_unit<chunk_type>(point, true);
+                        if (!(I_bit & m_unit)) {
+                            TIter write_iter = iter;
+                            // We assume here, that write_data doesn't change the iter
+                            write_data<sizeof_field_element, endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(
+                                    point_affine.X.data[1].data),
+                                write_iter);
+                            write_iter += sizeof_field_element_chunks_count;
+                            // We assume here, that write_data doesn't change the iter
+                            write_data<sizeof_field_element, endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(
+                                    point_affine.X.data[0].data),
+                                write_iter);
+                        }
+                        (*iter) |= m_unit;
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Endianness, typename Coordinates>
+                struct curve_element_writer<
+                    Endianness,
+                    typename algebra::curves::bls12_377::template g1_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::bls12_377::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = Endianness;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const chunk_type I_bit = 0x40;
+                        typename group_type::curve_type::template g1_type<typename algebra::curves::coordinates::affine,
+                                                                          form>::value_type point_affine =
+                            point.to_affine();
+                        chunk_type m_unit = detail::evaluate_m_unit<chunk_type>(point, true);
+                        if (!(I_bit & m_unit)) {
+                            // We assume here, that write_data doesn't change the iter
+                            write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+                        }
+                        (*iter) |= m_unit;
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+
+                template<typename Endianness, typename Coordinates>
+                struct curve_element_writer<
+                    Endianness,
+                    typename algebra::curves::bls12_377::template g2_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::bls12_377::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = Endianness;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+
+                        constexpr static const chunk_type I_bit = 0x40;
+                        typename group_type::curve_type::template g2_type<typename algebra::curves::coordinates::affine,
+                                                                          form>::value_type point_affine =
+                            point.to_affine();
+                        chunk_type m_unit = detail::evaluate_m_unit<chunk_type>(point, true);
+                        if (!(I_bit & m_unit)) {
+                            TIter write_iter = iter;
+                            // We assume here, that write_data doesn't change the iter
+                            write_data<sizeof_field_element, endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(
+                                    point_affine.X.data[1].data),
+                                write_iter);
+                            write_iter += sizeof_field_element_chunks_count;
+                            // We assume here, that write_data doesn't change the iter
+                            write_data<sizeof_field_element, endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(
+                                    point_affine.X.data[0].data),
+                                write_iter);
+                        }
+                        (*iter) |= m_unit;
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::bls12_381::template g1_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::bls12_381::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        const chunk_type m_unit = *iter & 0xE0;
+                        BOOST_ASSERT(m_unit != 0x20 && m_unit != 0x60 && m_unit != 0xE0);
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+                        using g1_value_type = group_value_type;
+                        using g1_field_type = typename group_value_type::field_type;
+                        using g1_field_value_type = typename g1_field_type::value_type;
+                        using integral_type = typename g1_value_type::field_type::integral_type;
+
+                        constexpr static const chunk_type I_bit = 0x40;
+                        constexpr static const chunk_type S_bit = 0x20;
+
+                        if (m_unit & I_bit) {
+                            BOOST_VERIFY(iter + sizeof_field_element_chunks_count ==
+                                         std::find(iter, iter + sizeof_field_element_chunks_count, true));
+                            point = g1_value_type();    // point at infinity
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod.pow(3u) + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
+                        if (Y_bit == bool(m_unit & S_bit)) {
+                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::bls12_381::template g2_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::bls12_381::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        const chunk_type m_unit = *iter & 0xE0;
+                        BOOST_ASSERT(m_unit != 0x20 && m_unit != 0x60 && m_unit != 0xE0);
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+                        using g2_value_type = group_value_type;
+                        using g2_field_type = typename g2_value_type::field_type;
+                        using g2_field_value_type = typename g2_field_type::value_type;
+                        using integral_type = typename g2_value_type::field_type::integral_type;
+
+                        constexpr static const chunk_type I_bit = 0x40;
+                        constexpr static const chunk_type S_bit = 0x20;
+
+                        if (m_unit & I_bit) {
+                            BOOST_ASSERT(iter + 2 * sizeof_field_element_chunks_count ==
+                                         std::find(iter, iter + 2 * sizeof_field_element_chunks_count, true));
+                            point = g2_value_type();    // point at infinity
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        TIter read_iter = iter;
+
+                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+                        read_iter += sizeof_field_element_chunks_count;
+
+                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+
+                        g2_field_value_type x_mod(x_0, x_1);
+                        g2_field_value_type y2_mod = x_mod.pow(3u) + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g2_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
+                        if (Y_bit == bool(m_unit & S_bit)) {
+                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::bls12_377::template g1_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::bls12_377::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        const chunk_type m_unit = *iter & 0xE0;
+                        BOOST_ASSERT(m_unit != 0x20 && m_unit != 0x60 && m_unit != 0xE0);
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+                        using g1_value_type = group_value_type;
+                        using g1_field_type = typename group_value_type::field_type;
+                        using g1_field_value_type = typename g1_field_type::value_type;
+                        using integral_type = typename g1_value_type::field_type::integral_type;
+
+                        constexpr static const chunk_type I_bit = 0x40;
+                        constexpr static const chunk_type S_bit = 0x20;
+
+                        if (m_unit & I_bit) {
+                            BOOST_VERIFY(iter + sizeof_field_element_chunks_count ==
+                                         std::find(iter, iter + sizeof_field_element_chunks_count, true));
+                            point = g1_value_type();    // point at infinity
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod.pow(3u) + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
+                        if (Y_bit == bool(m_unit & S_bit)) {
+                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::bls12_377::template g2_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::bls12_377::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        const chunk_type m_unit = *iter & 0xE0;
+                        BOOST_ASSERT(m_unit != 0x20 && m_unit != 0x60 && m_unit != 0xE0);
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+                        using g2_value_type = group_value_type;
+                        using g2_field_type = typename g2_value_type::field_type;
+                        using g2_field_value_type = typename g2_field_type::value_type;
+                        using integral_type = typename g2_value_type::field_type::integral_type;
+
+                        constexpr static const chunk_type I_bit = 0x40;
+                        constexpr static const chunk_type S_bit = 0x20;
+
+                        if (m_unit & I_bit) {
+                            BOOST_ASSERT(iter + 2 * sizeof_field_element_chunks_count ==
+                                         std::find(iter, iter + 2 * sizeof_field_element_chunks_count, true));
+                            point = g2_value_type();    // point at infinity
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        TIter read_iter = iter;
+
+                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+                        read_iter += sizeof_field_element_chunks_count;
+
+                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+
+                        g2_field_value_type x_mod(x_0, x_1);
+                        g2_field_value_type y2_mod = x_mod.pow(3u) + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g2_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
+                        if (Y_bit == bool(m_unit & S_bit)) {
+                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/curve_element.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/curve_element.hpp
index a792f811f5..12d3a0b045 100644
--- a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/curve_element.hpp
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/curve_element.hpp
@@ -1,6 +1,7 @@
 //---------------------------------------------------------------------------//
 // Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
 //
 // MIT License
 //
@@ -37,13 +38,6 @@
 
 #include <nil/crypto3/algebra/type_traits.hpp>
 
-#include <nil/crypto3/algebra/curves/bls12.hpp>
-#include <nil/crypto3/algebra/curves/curve25519.hpp>
-#include <nil/crypto3/algebra/curves/jubjub.hpp>
-#include <nil/crypto3/algebra/curves/alt_bn128.hpp>
-#include <nil/crypto3/algebra/curves/mnt4.hpp>
-#include <nil/crypto3/algebra/curves/mnt6.hpp>
-
 #include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
 
 #include <nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp>
@@ -83,73 +77,6 @@ namespace nil {
                     }
                 };
 
-                /* Specialization for mnt4_298::g2_type */
-                template<typename Coordinates>
-                struct curve_element_marshalling_params<algebra::curves::mnt4_298::
-                template g2_type<Coordinates, algebra::curves::forms::short_weierstrass> >
-                {
-                    using group_type = algebra::curves::mnt4_298::template
-                        g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-
-                    static constexpr std::size_t length() {
-                        return bit_length() / 8 + ((bit_length() % 8) != 0);
-                    }
-
-                    static constexpr std::size_t min_length() {
-                        return length();
-                    }
-
-                    static constexpr std::size_t max_length() {
-                        return length();
-                    }
-
-                    static constexpr std::size_t bit_length() {
-                        constexpr std::size_t modulus_bits_round_up = (group_type::field_type::modulus_bits + 7) & ~7;
-                        return modulus_bits_round_up * group_type::field_type::arity;
-                    }
-
-                    static constexpr std::size_t min_bit_length() {
-                        return bit_length();
-                    }
-
-                    static constexpr std::size_t max_bit_length() {
-                        return bit_length();
-                    }
-                };
-
-                /* Specialization for mnt6_298::g2_type */
-                template<typename Coordinates>
-                struct curve_element_marshalling_params<algebra::curves::mnt6_298::
-                template g2_type<Coordinates, algebra::curves::forms::short_weierstrass> >
-                {
-                    using group_type = algebra::curves::mnt6_298::template
-                        g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-
-                    static constexpr std::size_t length() {
-                        return bit_length() / 8 + ((bit_length() % 8) != 0);
-                    }
-
-                    static constexpr std::size_t min_length() {
-                        return length();
-                    }
-
-                    static constexpr std::size_t max_length() {
-                        return length();
-                    }
-
-                    static constexpr std::size_t bit_length() {
-                        constexpr std::size_t modulus_bits_round_up = (group_type::field_type::modulus_bits + 7) & ~7;
-                        return modulus_bits_round_up * group_type::field_type::arity;
-                    }
-
-                    static constexpr std::size_t min_bit_length() {
-                        return bit_length();
-                    }
-
-                    static constexpr std::size_t max_bit_length() {
-                        return bit_length();
-                    }
-                };
 
                 // TODO: do not specify marshalling algorithm by curve group, instead specify marshalling procedure only
                 //  by form, coordinates and specification policy
@@ -161,1090 +88,6 @@ namespace nil {
                 template<typename Endianness, typename Group>
                 struct curve_element_reader;
 
-                template<typename Endianness, typename Coordinates>
-                struct curve_element_writer<
-                    Endianness,
-                    typename algebra::curves::bls12_381::template g1_type<Coordinates,
-                                                                          algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::bls12_381::
-                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = Endianness;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const chunk_type I_bit = 0x40;
-                        typename group_type::curve_type::template g1_type<typename algebra::curves::coordinates::affine,
-                                                                          form>::value_type point_affine =
-                            point.to_affine();
-                        chunk_type m_unit = detail::evaluate_m_unit<chunk_type>(point, true);
-                        if (!(I_bit & m_unit)) {
-                            // We assume here, that write_data doesn't change the iter
-                            write_data<params_type::bit_length(), endianness>(
-                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
-                                iter);
-                        }
-                        (*iter) |= m_unit;
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-
-                template<typename Endianness, typename Coordinates>
-                struct curve_element_writer<
-                    Endianness,
-                    typename algebra::curves::bls12_381::template g2_type<Coordinates,
-                                                                          algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::bls12_381::
-                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = Endianness;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-
-                        constexpr static const chunk_type I_bit = 0x40;
-                        typename group_type::curve_type::template g2_type<typename algebra::curves::coordinates::affine,
-                                                                          form>::value_type point_affine =
-                            point.to_affine();
-                        chunk_type m_unit = detail::evaluate_m_unit<chunk_type>(point, true);
-                        if (!(I_bit & m_unit)) {
-                            TIter write_iter = iter;
-                            // We assume here, that write_data doesn't change the iter
-                            write_data<sizeof_field_element, endianness>(
-                                static_cast<typename group_value_type::field_type::integral_type>(
-                                    point_affine.X.data[1].data),
-                                write_iter);
-                            write_iter += sizeof_field_element_chunks_count;
-                            // We assume here, that write_data doesn't change the iter
-                            write_data<sizeof_field_element, endianness>(
-                                static_cast<typename group_value_type::field_type::integral_type>(
-                                    point_affine.X.data[0].data),
-                                write_iter);
-                        }
-                        (*iter) |= m_unit;
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_writer<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::alt_bn128_254::template g1_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::alt_bn128_254::
-                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using g1_value_type = group_value_type;
-                    using g1_field_type = typename group_value_type::field_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
-
-                        /* Point is always encoded in compressed form, only X coordinate.
-                         * Highest bit is Infinity flag
-                         * Second highest bit is sign of Y coordinate */
-
-                        using chunk_type = typename TIter::value_type;
-                        constexpr static const chunk_type I_bit = 0x80;
-                        constexpr static const chunk_type S_bit = 0x40;
-
-                        auto point_affine = point.to_affine();
-
-                        write_data<params_type::bit_length(), endianness>(
-                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
-                                iter);
-
-                        if (point_affine.is_zero()) {
-                            *iter |= I_bit;
-                        }
-
-                        if (detail::sign_gf_p<g1_field_type>(point_affine.Y)) {
-                            *iter |= S_bit;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_writer<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::alt_bn128_254::template g2_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::alt_bn128_254::
-                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using g2_value_type = group_value_type;
-                    using g2_field_type = typename group_value_type::field_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
-
-                        /* Point is always encoded in compressed form, only X coordinate.
-                         * Highest bit is Infinity flag
-                         * Second highest bit is sign of Y coordinate */
-
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-
-                        constexpr static const chunk_type I_bit = 0x80;
-                        constexpr static const chunk_type S_bit = 0x40;
-                        typename group_type::curve_type::template g2_type<
-                            typename algebra::curves::coordinates::affine,
-                            form>::value_type point_affine = point.to_affine();
-
-                        TIter write_iter = iter;
-                        // We assume here, that write_data doesn't change the iter
-                        write_data<sizeof_field_element, endianness>(
-                            static_cast<typename group_value_type::field_type::integral_type>(
-                                point_affine.X.data[1].data),
-                            write_iter);
-                        write_iter += sizeof_field_element_chunks_count;
-                        // We assume here, that write_data doesn't change the iter
-                        write_data<sizeof_field_element, endianness>(
-                            static_cast<typename group_value_type::field_type::integral_type>(
-                                point_affine.X.data[0].data),
-                            write_iter);
-
-                        if(point.is_zero()) {
-                            *iter |= I_bit;
-                        }
-
-                        if (detail::sign_gf_p<g2_field_type>(point_affine.Y)) {
-                            *iter |= S_bit;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_writer<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::mnt4_298::template g1_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::mnt4_298::
-                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using g1_value_type = group_value_type;
-                    using g1_field_type = typename group_value_type::field_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
-
-                        /* Point is encoded in compressed form, only X coordinate.
-                         * Highest bit is Infinity flag
-                         * Second highest bit is sign of Y coordinate */
-
-                        using chunk_type = typename TIter::value_type;
-                        constexpr static const chunk_type I_bit = 0x80;
-                        constexpr static const chunk_type S_bit = 0x40;
-
-                        auto point_affine = point.to_affine();
-
-                        write_data<params_type::bit_length(), endianness>(
-                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
-                                iter);
-
-                        if (point_affine.is_zero()) {
-                            *iter |= I_bit;
-                        }
-
-                        if (detail::sign_gf_p<g1_field_type>(point_affine.Y)) {
-                            *iter |= S_bit;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_writer<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::mnt4_298::template g2_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::mnt4_298::
-                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using g2_value_type = group_value_type;
-                    using g2_field_type = typename group_value_type::field_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
-
-                        /* Point is always encoded in compressed form, only X coordinate.
-                         * Highest bit is Infinity flag
-                         * Second highest bit is sign of Y coordinate */
-
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-
-                        constexpr static const chunk_type I_bit = 0x80;
-                        constexpr static const chunk_type S_bit = 0x40;
-                        auto point_affine = point.to_affine();
-
-                        TIter write_iter = iter;
-                        // We assume here, that write_data doesn't change the iter
-                        write_data<sizeof_field_element, endianness>(
-                            static_cast<typename group_value_type::field_type::integral_type>(
-                                point_affine.X.data[1].data),
-                            write_iter);
-                        write_iter += sizeof_field_element_chunks_count;
-                        // We assume here, that write_data doesn't change the iter
-                        write_data<sizeof_field_element, endianness>(
-                            static_cast<typename group_value_type::field_type::integral_type>(
-                                point_affine.X.data[0].data),
-                            write_iter);
-                        if(point.is_zero()) {
-                            *iter |= I_bit;
-                        }
-
-                        if (detail::sign_gf_p<g2_field_type>(point_affine.Y)) {
-                            *iter |= S_bit;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_writer<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::mnt6_298::template g1_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::mnt6_298::
-                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using g1_value_type = group_value_type;
-                    using g1_field_type = typename group_value_type::field_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
-
-                        /* Point is encoded in compressed form, only X coordinate.
-                         * Highest bit is Infinity flag
-                         * Second highest bit is sign of Y coordinate */
-
-                        using chunk_type = typename TIter::value_type;
-                        constexpr static const chunk_type I_bit = 0x80;
-                        constexpr static const chunk_type S_bit = 0x40;
-
-                        auto point_affine = point.to_affine();
-
-                        write_data<params_type::bit_length(), endianness>(
-                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
-                                iter);
-
-                        if (point_affine.is_zero()) {
-                            *iter |= I_bit;
-                        }
-
-                        if (detail::sign_gf_p<g1_field_type>(point_affine.Y)) {
-                            *iter |= S_bit;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_writer<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::mnt6_298::template g2_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::mnt6_298::
-                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using g2_value_type = group_value_type;
-                    using g2_field_type = typename group_value_type::field_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
-
-                        /* Point is always encoded in compressed form, only X coordinate.
-                         * Highest bit is Infinity flag
-                         * Second highest bit is sign of Y coordinate */
-
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-
-                        constexpr static const chunk_type I_bit = 0x80;
-                        constexpr static const chunk_type S_bit = 0x40;
-                        auto point_affine = point.to_affine();
-
-                        TIter write_iter = iter;
-                        write_data<sizeof_field_element, endianness>(
-                            static_cast<typename group_value_type::field_type::integral_type>(
-                                point_affine.X.data[2].data),
-                            write_iter);
-                        write_iter += sizeof_field_element_chunks_count;
-
-                        write_data<sizeof_field_element, endianness>(
-                            static_cast<typename group_value_type::field_type::integral_type>(
-                                point_affine.X.data[1].data),
-                            write_iter);
-                        write_iter += sizeof_field_element_chunks_count;
-
-                        write_data<sizeof_field_element, endianness>(
-                            static_cast<typename group_value_type::field_type::integral_type>(
-                                point_affine.X.data[0].data),
-                            write_iter);
-
-                        if(point.is_zero()) {
-                            *iter |= I_bit;
-                        }
-
-                        if (detail::sign_gf_p<g2_field_type>(point_affine.Y)) {
-                            *iter |= S_bit;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_writer<
-                    nil::marshalling::endian::little_endian,
-                    typename algebra::curves::curve25519::template g1_type<Coordinates,
-                                                                           algebra::curves::forms::twisted_edwards>> {
-                    using group_type =
-                        typename algebra::curves::curve25519::template g1_type<Coordinates,
-                                                                               algebra::curves::forms::twisted_edwards>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::little_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static typename std::enable_if<
-                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
-                        nil::marshalling::status_type>::type
-                        process(const group_value_type &point, TIter &iter) {
-                        using base_field_type = typename group_type::field_type;
-                        using base_integral_type = typename base_field_type::integral_type;
-                        using group_affine_value_type =
-                            typename algebra::curves::curve25519::g1_type<algebra::curves::coordinates::affine,
-                                                                          form>::value_type;
-                        // TODO: somehow add size check of container pointed by iter
-                        constexpr std::size_t encoded_size = 32;
-                        static_assert(encoded_size ==
-                                          (params_type::bit_length() / 8 + (params_type::bit_length() % 8 ? 1 : 0)),
-                                      "wrong size");
-                        using encoded_value_type = std::array<std::uint8_t, encoded_size>;
-
-                        group_affine_value_type point_affine = point.to_affine();
-                        // TODO: remove crating of temporary array encoded_value
-                        encoded_value_type encoded_value {0};
-                        // TODO: remove lvalue iterator
-                        auto tmp_iter = std::begin(encoded_value);
-                        write_data<encoded_size, endianness>(static_cast<base_integral_type>(point_affine.Y.data),
-                                                             tmp_iter);
-                        // TODO: throw catchable error, for example return status
-                        assert(!(encoded_value[encoded_size - 1] & 0x80));
-                        encoded_value[encoded_size - 1] |=
-                            (static_cast<std::uint8_t>(static_cast<base_integral_type>(point_affine.X.data) & 1) << 7);
-
-                        std::copy(std::cbegin(encoded_value), std::cend(encoded_value), iter);
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_writer<
-                    nil::marshalling::endian::little_endian,
-                    typename algebra::curves::jubjub::template g1_type<Coordinates,
-                                                                       algebra::curves::forms::twisted_edwards>> {
-                    using group_type =
-                        typename algebra::curves::jubjub::template g1_type<Coordinates,
-                                                                           algebra::curves::forms::twisted_edwards>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::little_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    /// https://zips.z.cash/protocol/protocol.pdf#concreteextractorjubjub
-                    template<typename TIter>
-                    static nil::marshalling::status_type
-                        process(const group_value_type &point, TIter &iter) {
-                        write_data<params_type::bit_length(), endianness>(
-                            static_cast<typename group_value_type::field_type::integral_type>(point.to_affine().X.data),
-                            iter);
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::bls12_381::template g1_type<Coordinates,
-                                                                          algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::bls12_381::
-                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        const chunk_type m_unit = *iter & 0xE0;
-                        BOOST_ASSERT(m_unit != 0x20 && m_unit != 0x60 && m_unit != 0xE0);
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-                        using g1_value_type = group_value_type;
-                        using g1_field_type = typename group_value_type::field_type;
-                        using g1_field_value_type = typename g1_field_type::value_type;
-                        using integral_type = typename g1_value_type::field_type::integral_type;
-
-                        constexpr static const chunk_type I_bit = 0x40;
-                        constexpr static const chunk_type S_bit = 0x20;
-
-                        if (m_unit & I_bit) {
-                            BOOST_VERIFY(iter + sizeof_field_element_chunks_count ==
-                                         std::find(iter, iter + sizeof_field_element_chunks_count, true));
-                            point = g1_value_type();    // point at infinity
-                            return nil::marshalling::status_type::success;
-                        }
-
-                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
-
-                        g1_field_value_type x_mod(x);
-                        g1_field_value_type y2_mod = x_mod.pow(3u) + g1_field_value_type(4u);
-                        BOOST_ASSERT(y2_mod.is_square());
-                        g1_field_value_type y_mod = y2_mod.sqrt();
-                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
-                        if (Y_bit == bool(m_unit & S_bit)) {
-                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        } else {
-                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::bls12_381::template g2_type<Coordinates,
-                                                                          algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::bls12_381::
-                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        const chunk_type m_unit = *iter & 0xE0;
-                        BOOST_ASSERT(m_unit != 0x20 && m_unit != 0x60 && m_unit != 0xE0);
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-                        using g2_value_type = group_value_type;
-                        using g2_field_type = typename g2_value_type::field_type;
-                        using g2_field_value_type = typename g2_field_type::value_type;
-                        using integral_type = typename g2_value_type::field_type::integral_type;
-
-                        constexpr static const chunk_type I_bit = 0x40;
-                        constexpr static const chunk_type S_bit = 0x20;
-
-                        if (m_unit & I_bit) {
-                            BOOST_ASSERT(iter + 2 * sizeof_field_element_chunks_count ==
-                                         std::find(iter, iter + 2 * sizeof_field_element_chunks_count, true));
-                            point = g2_value_type();    // point at infinity
-                            return nil::marshalling::status_type::success;
-                        }
-
-                        TIter read_iter = iter;
-
-                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-                        read_iter += sizeof_field_element_chunks_count;
-
-                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-
-                        g2_field_value_type x_mod(x_0, x_1);
-                        g2_field_value_type y2_mod = x_mod.pow(3u) + g2_field_value_type(4u, 4u);
-                        BOOST_ASSERT(y2_mod.is_square());
-                        g2_field_value_type y_mod = y2_mod.sqrt();
-                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
-                        if (Y_bit == bool(m_unit & S_bit)) {
-                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        } else {
-                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::alt_bn128_254::template g1_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::alt_bn128_254::
-                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        using g1_value_type = group_value_type;
-                        using g1_field_type = typename group_value_type::field_type;
-                        using g1_field_value_type = typename g1_field_type::value_type;
-                        using integral_type = typename g1_value_type::field_type::integral_type;
-
-                        chunk_type I_bit = *iter & 0x80;
-                        chunk_type S_bit = *iter & 0x40;
-
-                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
-
-                        if (I_bit) {
-                            // point at infinity
-                            point = g1_value_type();
-                            return nil::marshalling::status_type::success;
-                        }
-
-                        g1_field_value_type x_mod(x);
-                        g1_field_value_type y2_mod = x_mod.pow(3) + group_type::params_type::b;
-                        BOOST_ASSERT(y2_mod.is_square());
-                        g1_field_value_type y_mod = y2_mod.sqrt();
-                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
-                        if (Y_bit == bool(S_bit)) {
-                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        } else {
-                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::alt_bn128_254::template g2_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::alt_bn128_254::
-                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-                        using g2_value_type = group_value_type;
-                        using g2_field_type = typename g2_value_type::field_type;
-                        using g2_field_value_type = typename g2_field_type::value_type;
-                        using integral_type = typename g2_value_type::field_type::integral_type;
-
-                        chunk_type I_bit = *iter & 0x80;
-                        chunk_type S_bit = *iter & 0x40;
-
-                        TIter read_iter = iter;
-                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-                        read_iter += sizeof_field_element_chunks_count;
-                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-
-                        if (I_bit) {
-                            // point at infinity
-                            point = group_value_type();
-                            return nil::marshalling::status_type::success;
-                        }
-
-                        g2_field_value_type x_mod(x_0, x_1);
-                        g2_field_value_type y2_mod = x_mod.pow(3) + group_type::params_type::b;
-                        BOOST_ASSERT(y2_mod.is_square());
-                        g2_field_value_type y_mod = y2_mod.sqrt();
-                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
-                        if (Y_bit == bool(S_bit)) {
-                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        } else {
-                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::mnt4_298::template g1_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::mnt4_298::
-                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        using g1_value_type = group_value_type;
-                        using g1_field_type = typename group_value_type::field_type;
-                        using g1_field_value_type = typename g1_field_type::value_type;
-                        using integral_type = typename g1_value_type::field_type::integral_type;
-
-                        chunk_type I_bit = *iter & 0x80;
-                        chunk_type S_bit = *iter & 0x40;
-
-                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
-
-                        if (I_bit) {
-                            // point at infinity
-                            point = g1_value_type();
-                            return nil::marshalling::status_type::success;
-                        }
-
-                        g1_field_value_type x_mod(x);
-                        g1_field_value_type y2_mod = x_mod.pow(3)
-                            + group_type::params_type::a * x_mod
-                            + group_type::params_type::b;
-                        BOOST_ASSERT(y2_mod.is_square());
-                        g1_field_value_type y_mod = y2_mod.sqrt();
-                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
-                        if (Y_bit == bool(S_bit)) {
-                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        } else {
-                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::mnt4_298::template g2_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::mnt4_298::
-                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-                        using g2_value_type = group_value_type;
-                        using g2_field_type = typename g2_value_type::field_type;
-                        using g2_field_value_type = typename g2_field_type::value_type;
-                        using integral_type = typename g2_value_type::field_type::integral_type;
-
-                        chunk_type I_bit = *iter & 0x80;
-                        chunk_type S_bit = *iter & 0x40;
-
-                        TIter read_iter = iter;
-                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-                        read_iter += sizeof_field_element_chunks_count;
-                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-
-                        if (I_bit) {
-                            // point at infinity
-                            point = group_value_type();
-                            return nil::marshalling::status_type::success;
-                        }
-
-                        g2_field_value_type x_mod(x_0, x_1);
-                        g2_field_value_type y2_mod = x_mod.pow(3)
-                            + group_type::params_type::a * x_mod
-                            + group_type::params_type::b;
-                        BOOST_ASSERT(y2_mod.is_square());
-                        g2_field_value_type y_mod = y2_mod.sqrt();
-                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
-                        if (Y_bit == bool(S_bit)) {
-                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        } else {
-                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::mnt6_298::template g1_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::mnt6_298::
-                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        using g1_value_type = group_value_type;
-                        using g1_field_type = typename group_value_type::field_type;
-                        using g1_field_value_type = typename g1_field_type::value_type;
-                        using integral_type = typename g1_value_type::field_type::integral_type;
-
-                        chunk_type I_bit = *iter & 0x80;
-                        chunk_type S_bit = *iter & 0x40;
-
-                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
-
-                        if (I_bit) {
-                            // point at infinity
-                            point = g1_value_type();
-                            return nil::marshalling::status_type::success;
-                        }
-
-                        g1_field_value_type x_mod(x);
-                        g1_field_value_type y2_mod = x_mod.pow(3)
-                            + group_type::params_type::a * x_mod
-                            + group_type::params_type::b;
-                        BOOST_ASSERT(y2_mod.is_square());
-                        g1_field_value_type y_mod = y2_mod.sqrt();
-                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
-                        if (Y_bit == bool(S_bit)) {
-                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        } else {
-                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::big_endian,
-                    typename algebra::curves::mnt6_298::template g2_type<
-                        Coordinates,
-                        algebra::curves::forms::short_weierstrass>> {
-                    using group_type = typename algebra::curves::mnt6_298::
-                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::big_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
-                        using chunk_type = typename TIter::value_type;
-
-                        constexpr static const std::size_t sizeof_field_element =
-                            params_type::bit_length() / (group_value_type::field_type::arity);
-                        constexpr static const std::size_t units_bits = 8;
-                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
-                        constexpr static const std::size_t sizeof_field_element_chunks_count =
-                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
-                        using g2_value_type = group_value_type;
-                        using g2_field_type = typename g2_value_type::field_type;
-                        using g2_field_value_type = typename g2_field_type::value_type;
-                        using integral_type = typename g2_value_type::field_type::integral_type;
-
-                        chunk_type I_bit = *iter & 0x80;
-                        chunk_type S_bit = *iter & 0x40;
-
-                        TIter read_iter = iter;
-                        integral_type x_2 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-                        read_iter += sizeof_field_element_chunks_count;
-                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-                        read_iter += sizeof_field_element_chunks_count;
-                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
-
-                        if (I_bit) {
-                            // point at infinity
-                            point = group_value_type();
-                            return nil::marshalling::status_type::success;
-                        }
-
-                        g2_field_value_type x_mod(x_0, x_1, x_2);
-                        g2_field_value_type y2_mod = x_mod.pow(3)
-                            + group_type::params_type::a * x_mod
-                            + group_type::params_type::b;
-                        BOOST_ASSERT(y2_mod.is_square());
-                        g2_field_value_type y_mod = y2_mod.sqrt();
-                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
-                        if (Y_bit == bool(S_bit)) {
-                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        } else {
-                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
-                            BOOST_ASSERT(result.is_well_formed());
-                            point = result;
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<typename Coordinates>
-                struct curve_element_reader<
-                    nil::marshalling::endian::little_endian,
-                    typename algebra::curves::curve25519::template g1_type<Coordinates,
-                                                                           algebra::curves::forms::twisted_edwards>> {
-                    using group_type =
-                        typename algebra::curves::curve25519::template g1_type<Coordinates,
-                                                                               algebra::curves::forms::twisted_edwards>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::little_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    template<typename TIter>
-                    static typename std::enable_if<
-                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
-                        nil::marshalling::status_type>::type
-                        process(group_value_type &point, TIter &iter) {
-                        // somehow add size check of container pointed by iter
-                        // assert(TSize == std::distance(first, last));
-                        using base_field_type = typename group_type::field_type;
-                        using base_integral_type = typename base_field_type::integral_type;
-                        using group_affine_value_type =
-                            typename algebra::curves::curve25519::g1_type<algebra::curves::coordinates::affine,
-                                                                          form>::value_type;
-                        constexpr std::size_t encoded_size = 32;
-                        static_assert(encoded_size ==
-                                          (params_type::bit_length() / 8 + (params_type::bit_length() % 8 ? 1 : 0)),
-                                      "wrong size");
-
-                        base_integral_type y =
-                            read_data<params_type::bit_length(), base_integral_type, endianness>(iter);
-                        bool sign = *(iter + encoded_size - 1) & (1 << 7);
-
-                        auto decoded_point_affine =
-                                detail::recover_x<group_affine_value_type>(y, sign);
-
-                        if (!decoded_point_affine) {
-                            return decoded_point_affine.error();
-                        }
-
-                        // TODO: remove hard-coded call for type conversion, implement type conversion between
-                        // coordinates
-                        //  through operator
-                        point = decoded_point_affine.value().to_extended_with_a_minus_1();
-                        return nil::marshalling::status_type::success;
-                    }
-                };
-
-                template<>
-                struct curve_element_reader<
-                    nil::marshalling::endian::little_endian,
-                    typename algebra::curves::jubjub::template g1_type<algebra::curves::coordinates::affine,
-                                                                       algebra::curves::forms::twisted_edwards>> {
-                    using group_type =
-                        typename algebra::curves::jubjub::template g1_type<algebra::curves::coordinates::affine,
-                                                                           algebra::curves::forms::twisted_edwards>;
-                    using group_value_type = typename group_type::value_type;
-                    using coordinates = typename group_value_type::coordinates;
-                    using form = typename group_value_type::form;
-                    using endianness = nil::marshalling::endian::little_endian;
-                    using params_type = curve_element_marshalling_params<group_type>;
-
-                    /// abst_J(LEOS2BSP_{256}(iter))
-                    /// See https://zips.z.cash/protocol/protocol.pdf#concretegrouphashjubjub
-                    template<typename TIter>
-                    static typename std::enable_if<
-                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
-                        nil::marshalling::status_type>::type
-                        process(group_value_type &point, TIter &iter) {
-                        using field_type = typename group_value_type::field_type;
-                        using integral_type = typename field_type::integral_type;
-
-                        const std::size_t chunk_number =
-                            params_type::bit_length() / 8 + (params_type::bit_length() % 8 != 0);
-                        assert(chunk_number == 32);
-
-                        integral_type int_v = read_data<params_type::bit_length(), integral_type, endianness>(iter);
-                        if (int_v >= group_value_type::field_type::modulus) {
-                            return nil::marshalling::status_type::invalid_msg_data;
-                        }
-                        field_type::value_type field_v(int_v);
-                        field_type::value_type vv = field_v.squared();
-                        field_type::value_type denominator = (field_type::value_type(group_type::params_type::a) -
-                                                              field_type::value_type(group_type::params_type::d) * vv);
-                        if (denominator.is_zero()) {
-                            return nil::marshalling::status_type::invalid_msg_data;
-                        }
-                        field_type::value_type fraction = (field_type::value_type::one() - vv) * denominator.inversed();
-
-                        field_type::value_type u;
-                        if (fraction.is_one()) {
-                            u = field_type::modulus - 1;
-                        } else if (fraction.is_zero()) {
-                            u = field_type::value_type::zero();
-                        } else {
-                            if ( !fraction.is_square() ) {
-                                return nil::marshalling::status_type::invalid_msg_data;
-                            }
-                            u = fraction.sqrt();
-                        }
-
-                        if ((*(iter + chunk_number - 1) >> 7) == (static_cast<integral_type>(u.data) & 1)) {
-                            point = group_value_type(u, field_v);
-                        } else {
-                            point = group_value_type(-u, field_v);
-                        }
-
-                        return nil::marshalling::status_type::success;
-                    }
-                };
             }    // namespace processing
         }        // namespace marshalling
     }            // namespace crypto3
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp
index bbed22937c..ccb4f390d5 100644
--- a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp
@@ -1,6 +1,7 @@
 //---------------------------------------------------------------------------//
 // Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
 //
 // MIT License
 //
@@ -88,6 +89,16 @@ namespace nil {
                         return result;
                     }
 
+                    /** @brief Recover X coordinate from Y coordinate and given sign
+                     * This is specific to Ed25519 Twisted Edwards curve, but could be used for
+                     * any other curve in twisted edwards form.
+                     *
+                     * The curve equation in twisted edwards form is A*x^2+y^2=1+D*x^2*y^2
+                     * Given Y, we compute
+                     * X^2 = ( 1 - Y^2 ) / ( A - D*Y^2 )
+                     * If X^2 is not a square, then there is no such point and input should be rejected
+                     * Otherwise X or -X are chosen by the sign parameter
+                     */
                     template<typename GroupAffineElement>
                     static inline typename 
                     std::enable_if<
@@ -106,12 +117,12 @@ namespace nil {
                         }
                         base_field_value_type y(y_int);
                         base_field_value_type y2 = y * y;
-                        base_field_value_type y2dp1 = y2 * group_type::params_type::d + base_integral_type(1);
+                        base_field_value_type y2dp1 = group_type::params_type::a - y2 * group_type::params_type::d;
                         if (y2dp1.is_zero()) {
                             return nil::marshalling::status_type::invalid_msg_data;
                         }
                         base_field_value_type x2 =
-                            (y2 - base_integral_type(1)) * y2dp1.inversed();
+                            (base_integral_type(1) - y2) * y2dp1.inversed();
                         if (x2.is_zero()) {
                             return group_affine_value_type(base_field_value_type::zero(), y);
                         }
@@ -120,7 +131,7 @@ namespace nil {
                         }
                         base_field_value_type x = x2.sqrt();
                         auto x_int = static_cast<base_integral_type>(x.data);
-                        if (static_cast<bool>(x_int & 1) != sign) {
+                        if (sign_gf_p<base_field_type>(x_int) != sign) {
                             x_int = base_field_type::modulus - x_int;
                         }
                         return group_affine_value_type(x_int, y);
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/ed25519.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/ed25519.hpp
new file mode 100644
index 0000000000..8828545bb6
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/ed25519.hpp
@@ -0,0 +1,161 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
+// Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_ED25519_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_ED25519_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+#include <iterator>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/ed25519.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::little_endian,
+                    typename algebra::curves::ed25519::template g1_type<Coordinates,
+                                                                           algebra::curves::forms::twisted_edwards>> {
+                    using group_type =
+                        typename algebra::curves::ed25519::template g1_type<Coordinates,
+                                                                               algebra::curves::forms::twisted_edwards>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::little_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                    std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                        process(const group_value_type &point, TIter &iter) {
+                        using base_field_type = typename group_type::field_type;
+                        using base_integral_type = typename base_field_type::integral_type;
+
+                        constexpr std::size_t encoded_size = 32;
+                        using encoded_value_type = std::array<std::uint8_t, encoded_size>;
+                        encoded_value_type encoded_value {0};
+
+                        auto point_affine = point.to_affine();
+
+                        /* Zero point is encoded as (0,1) */
+                        if (point.is_zero()) {
+                            point_affine.Y = 1u;
+                            point_affine.X = 0u;
+                        }
+
+                        auto tmp_iter = std::begin(encoded_value);
+                        write_data<encoded_size, endianness>(static_cast<base_integral_type>(point_affine.Y.data),
+                                tmp_iter);
+                        assert(!(encoded_value[encoded_size - 1] & 0x80));
+                        bool sign = detail::sign_gf_p<base_field_type>(point_affine.X.data);
+                        encoded_value[encoded_size - 1] |=
+                            (static_cast<std::uint8_t>(sign ? 1 : 0) << 7);
+
+                        std::copy(std::cbegin(encoded_value), std::cend(encoded_value), iter);
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::little_endian,
+                    typename algebra::curves::ed25519::template g1_type<Coordinates,
+                                                                           algebra::curves::forms::twisted_edwards>> {
+                    using group_type =
+                        typename algebra::curves::ed25519::template g1_type<Coordinates,
+                                                                               algebra::curves::forms::twisted_edwards>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::little_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    using group_affine_value_type =
+                            typename algebra::curves::ed25519::g1_type<algebra::curves::coordinates::affine,
+                                                                          form>::value_type;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                        process(group_value_type &point, TIter &iter)
+                    {
+
+                        // somehow add size check of container pointed by iter
+                        // assert(TSize == std::distance(first, last));
+                        using base_field_type = typename group_type::field_type;
+                        using base_integral_type = typename base_field_type::integral_type;
+                        using group_affine_value_type =
+                            typename algebra::curves::ed25519::g1_type<algebra::curves::coordinates::affine,
+                                                                          form>::value_type;
+                        constexpr std::size_t encoded_size = 32;
+                        static_assert(encoded_size ==
+                                          (params_type::bit_length() / 8 + (params_type::bit_length() % 8 ? 1 : 0)),
+                                      "wrong size");
+
+                        base_integral_type y =
+                            read_data<params_type::bit_length(), base_integral_type, endianness>(iter);
+                        bool sign = *(iter + encoded_size - 1) & (1 << 7);
+
+                        auto decoded_point_affine =
+                                detail::recover_x<group_affine_value_type>(y, sign);
+
+                        if (!decoded_point_affine) {
+                            return decoded_point_affine.error();
+                        }
+
+                        // TODO: remove hard-coded call for type conversion, implement type conversion between
+                        // coordinates
+                        //  through operator
+                        point = decoded_point_affine.value().to_extended_with_a_minus_1();
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_ED25519_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/jubjub.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/jubjub.hpp
new file mode 100644
index 0000000000..c972a3d16a
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/jubjub.hpp
@@ -0,0 +1,150 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
+// Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_JUBJUB_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_JUBJUB_CURVE_ELEMENT_HPP
+
+#include <cstdint>
+#include <type_traits>
+#include <iterator>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/jubjub.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::little_endian,
+                    typename algebra::curves::jubjub::template g1_type<Coordinates,
+                                                                       algebra::curves::forms::twisted_edwards>> {
+                    using group_type =
+                        typename algebra::curves::jubjub::template g1_type<Coordinates,
+                                                                           algebra::curves::forms::twisted_edwards>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::little_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    /// https://zips.z.cash/protocol/protocol.pdf#concreteextractorjubjub
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter)
+                    {
+                        write_data<params_type::bit_length(), endianness>(
+                            static_cast<typename group_value_type::field_type::integral_type>(point.to_affine().X.data),
+                            iter);
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<>
+                struct curve_element_reader<
+                    nil::marshalling::endian::little_endian,
+                    typename algebra::curves::jubjub::template g1_type<algebra::curves::coordinates::affine,
+                                                                       algebra::curves::forms::twisted_edwards>> {
+                    using group_type =
+                        typename algebra::curves::jubjub::template g1_type<algebra::curves::coordinates::affine,
+                                                                           algebra::curves::forms::twisted_edwards>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::little_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    /// abst_J(LEOS2BSP_{256}(iter))
+                    /// See https://zips.z.cash/protocol/protocol.pdf#concretegrouphashjubjub
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(group_value_type &point, TIter &iter)
+                    {
+                        using field_type = typename group_value_type::field_type;
+                        using scalar_type = typename algebra::curves::jubjub::scalar_field_type;
+                        using integral_type = typename field_type::integral_type;
+
+                        integral_type int_u = read_data<params_type::bit_length(), integral_type, endianness>(iter);
+                        if (int_u >= group_value_type::field_type::modulus) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        if (int_u.is_zero()) {
+                            point = group_value_type();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        field_type::value_type field_u(int_u);
+                        field_type::value_type uu = field_u.squared();
+                        field_type::value_type denominator =
+                            (field_type::value_type::one() - field_type::value_type(group_type::params_type::d) * uu);
+                        if (denominator.is_zero()) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        field_type::value_type fraction =
+                            (field_type::value_type::one() - field_type::value_type(group_type::params_type::a) * uu)
+                            * denominator.inversed();
+
+                        if (!fraction.is_square()) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        field_type::value_type v = fraction.sqrt();
+
+                        // ... at most one of (u, v) and (u, −v) is in J(𝑟)
+                        point = group_value_type(field_u, v);
+                        if ( (point * (scalar_type::modulus - 1) + point).is_zero() ) {
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        point = group_value_type(field_u, -v);
+                        if ( (point * (scalar_type::modulus - 1) + point).is_zero() ) {
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        // If neither has order r, then point is of mixed order and should be rejected
+                        point = group_value_type();
+                        return nil::marshalling::status_type::invalid_msg_data;
+                    }
+                };
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/mnt4.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/mnt4.hpp
new file mode 100644
index 0000000000..79e71ebbd7
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/mnt4.hpp
@@ -0,0 +1,312 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
+// Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_MNT4_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_MNT4_CURVE_ELEMENT_HPP
+
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/mnt4.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                /* Specialization for mnt4_298::g2_type */
+                template<typename Coordinates>
+                struct curve_element_marshalling_params<algebra::curves::mnt4_298::
+                template g2_type<Coordinates, algebra::curves::forms::short_weierstrass> >
+                {
+                    using group_type = algebra::curves::mnt4_298::template
+                        g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+
+                    static constexpr std::size_t length() {
+                        return bit_length() / 8 + ((bit_length() % 8) != 0);
+                    }
+
+                    static constexpr std::size_t min_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t max_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t bit_length() {
+                        constexpr std::size_t modulus_bits_round_up = (group_type::field_type::modulus_bits + 7) & ~7;
+                        return modulus_bits_round_up * group_type::field_type::arity;
+                    }
+
+                    static constexpr std::size_t min_bit_length() {
+                        return bit_length();
+                    }
+
+                    static constexpr std::size_t max_bit_length() {
+                        return bit_length();
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::mnt4_298::template g1_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::mnt4_298::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using g1_value_type = group_value_type;
+                    using g1_field_type = typename group_value_type::field_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+
+                        /* Point is encoded in compressed form, only X coordinate.
+                         * Highest bit is Infinity flag
+                         * Second highest bit is sign of Y coordinate */
+
+                        using chunk_type = typename TIter::value_type;
+                        constexpr static const chunk_type I_bit = 0x80;
+                        constexpr static const chunk_type S_bit = 0x40;
+
+                        auto point_affine = point.to_affine();
+
+                        write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+
+                        if (point_affine.is_zero()) {
+                            *iter |= I_bit;
+                        }
+
+                        if (detail::sign_gf_p<g1_field_type>(point_affine.Y)) {
+                            *iter |= S_bit;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::mnt4_298::template g2_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::mnt4_298::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using g2_value_type = group_value_type;
+                    using g2_field_type = typename group_value_type::field_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+
+                        /* Point is always encoded in compressed form, only X coordinate.
+                         * Highest bit is Infinity flag
+                         * Second highest bit is sign of Y coordinate */
+
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+
+                        constexpr static const chunk_type I_bit = 0x80;
+                        constexpr static const chunk_type S_bit = 0x40;
+                        auto point_affine = point.to_affine();
+
+                        TIter write_iter = iter;
+                        // We assume here, that write_data doesn't change the iter
+                        write_data<sizeof_field_element, endianness>(
+                            static_cast<typename group_value_type::field_type::integral_type>(
+                                point_affine.X.data[1].data),
+                            write_iter);
+                        write_iter += sizeof_field_element_chunks_count;
+                        // We assume here, that write_data doesn't change the iter
+                        write_data<sizeof_field_element, endianness>(
+                            static_cast<typename group_value_type::field_type::integral_type>(
+                                point_affine.X.data[0].data),
+                            write_iter);
+                        if(point.is_zero()) {
+                            *iter |= I_bit;
+                        }
+
+                        if (detail::sign_gf_p<g2_field_type>(point_affine.Y)) {
+                            *iter |= S_bit;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::mnt4_298::template g1_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::mnt4_298::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        using g1_value_type = group_value_type;
+                        using g1_field_type = typename group_value_type::field_type;
+                        using g1_field_value_type = typename g1_field_type::value_type;
+                        using integral_type = typename g1_value_type::field_type::integral_type;
+
+                        chunk_type I_bit = *iter & 0x80;
+                        chunk_type S_bit = *iter & 0x40;
+
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        if (I_bit) {
+                            // point at infinity
+                            point = g1_value_type();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod.pow(3)
+                            + group_type::params_type::a * x_mod
+                            + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
+                        if (Y_bit == bool(S_bit)) {
+                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::mnt4_298::template g2_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::mnt4_298::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+                        using g2_value_type = group_value_type;
+                        using g2_field_type = typename g2_value_type::field_type;
+                        using g2_field_value_type = typename g2_field_type::value_type;
+                        using integral_type = typename g2_value_type::field_type::integral_type;
+
+                        chunk_type I_bit = *iter & 0x80;
+                        chunk_type S_bit = *iter & 0x40;
+
+                        TIter read_iter = iter;
+                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+                        read_iter += sizeof_field_element_chunks_count;
+                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+
+                        if (I_bit) {
+                            // point at infinity
+                            point = group_value_type();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        g2_field_value_type x_mod(x_0, x_1);
+                        g2_field_value_type y2_mod = x_mod.pow(3)
+                            + group_type::params_type::a * x_mod
+                            + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g2_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
+                        if (Y_bit == bool(S_bit)) {
+                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_MNT4_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/mnt6.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/mnt6.hpp
new file mode 100644
index 0000000000..6f051e1ea9
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/mnt6.hpp
@@ -0,0 +1,323 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017-2021 Mikhail Komarov <nemo@nil.foundation>
+// Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_MNT6_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_MNT6_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/mnt6.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/detail/curve_element.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                /* Specialization for mnt6_298::g2_type */
+                template<typename Coordinates>
+                struct curve_element_marshalling_params<algebra::curves::mnt6_298::
+                template g2_type<Coordinates, algebra::curves::forms::short_weierstrass> >
+                {
+                    using group_type = algebra::curves::mnt6_298::template
+                        g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+
+                    static constexpr std::size_t length() {
+                        return bit_length() / 8 + ((bit_length() % 8) != 0);
+                    }
+
+                    static constexpr std::size_t min_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t max_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t bit_length() {
+                        constexpr std::size_t modulus_bits_round_up = (group_type::field_type::modulus_bits + 7) & ~7;
+                        return modulus_bits_round_up * group_type::field_type::arity;
+                    }
+
+                    static constexpr std::size_t min_bit_length() {
+                        return bit_length();
+                    }
+
+                    static constexpr std::size_t max_bit_length() {
+                        return bit_length();
+                    }
+                };
+
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::mnt6_298::template g1_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::mnt6_298::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using g1_value_type = group_value_type;
+                    using g1_field_type = typename group_value_type::field_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+
+                        /* Point is encoded in compressed form, only X coordinate.
+                         * Highest bit is Infinity flag
+                         * Second highest bit is sign of Y coordinate */
+
+                        using chunk_type = typename TIter::value_type;
+                        constexpr static const chunk_type I_bit = 0x80;
+                        constexpr static const chunk_type S_bit = 0x40;
+
+                        auto point_affine = point.to_affine();
+
+                        write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+
+                        if (point_affine.is_zero()) {
+                            *iter |= I_bit;
+                        }
+
+                        if (detail::sign_gf_p<g1_field_type>(point_affine.Y)) {
+                            *iter |= S_bit;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::mnt6_298::template g2_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::mnt6_298::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using g2_value_type = group_value_type;
+                    using g2_field_type = typename group_value_type::field_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(const group_value_type &point, TIter &iter) {
+
+                        /* Point is always encoded in compressed form, only X coordinate.
+                         * Highest bit is Infinity flag
+                         * Second highest bit is sign of Y coordinate */
+
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(typename TIter::value_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+
+                        constexpr static const chunk_type I_bit = 0x80;
+                        constexpr static const chunk_type S_bit = 0x40;
+                        auto point_affine = point.to_affine();
+
+                        TIter write_iter = iter;
+                        write_data<sizeof_field_element, endianness>(
+                            static_cast<typename group_value_type::field_type::integral_type>(
+                                point_affine.X.data[2].data),
+                            write_iter);
+                        write_iter += sizeof_field_element_chunks_count;
+
+                        write_data<sizeof_field_element, endianness>(
+                            static_cast<typename group_value_type::field_type::integral_type>(
+                                point_affine.X.data[1].data),
+                            write_iter);
+                        write_iter += sizeof_field_element_chunks_count;
+
+                        write_data<sizeof_field_element, endianness>(
+                            static_cast<typename group_value_type::field_type::integral_type>(
+                                point_affine.X.data[0].data),
+                            write_iter);
+
+                        if(point.is_zero()) {
+                            *iter |= I_bit;
+                        }
+
+                        if (detail::sign_gf_p<g2_field_type>(point_affine.Y)) {
+                            *iter |= S_bit;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::mnt6_298::template g1_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::mnt6_298::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        using g1_value_type = group_value_type;
+                        using g1_field_type = typename group_value_type::field_type;
+                        using g1_field_value_type = typename g1_field_type::value_type;
+                        using integral_type = typename g1_value_type::field_type::integral_type;
+
+                        chunk_type I_bit = *iter & 0x80;
+                        chunk_type S_bit = *iter & 0x40;
+
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        if (I_bit) {
+                            // point at infinity
+                            point = g1_value_type();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod.pow(3)
+                            + group_type::params_type::a * x_mod
+                            + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
+                        if (Y_bit == bool(S_bit)) {
+                            g1_value_type result(x_mod, y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g1_value_type result(x_mod, -y_mod, g1_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::mnt6_298::template g2_type<
+                        Coordinates,
+                        algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::mnt6_298::
+                        template g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static nil::marshalling::status_type process(group_value_type &point, TIter &iter) {
+                        using chunk_type = typename TIter::value_type;
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        constexpr static const std::size_t units_bits = 8;
+                        constexpr static const std::size_t chunk_bits = sizeof(chunk_type) * units_bits;
+                        constexpr static const std::size_t sizeof_field_element_chunks_count =
+                            (sizeof_field_element / chunk_bits) + ((sizeof_field_element % chunk_bits) ? 1 : 0);
+                        using g2_value_type = group_value_type;
+                        using g2_field_type = typename g2_value_type::field_type;
+                        using g2_field_value_type = typename g2_field_type::value_type;
+                        using integral_type = typename g2_value_type::field_type::integral_type;
+
+                        chunk_type I_bit = *iter & 0x80;
+                        chunk_type S_bit = *iter & 0x40;
+
+                        TIter read_iter = iter;
+                        integral_type x_2 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+                        read_iter += sizeof_field_element_chunks_count;
+                        integral_type x_1 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+                        read_iter += sizeof_field_element_chunks_count;
+                        integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
+
+                        if (I_bit) {
+                            // point at infinity
+                            point = group_value_type();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        g2_field_value_type x_mod(x_0, x_1, x_2);
+                        g2_field_value_type y2_mod = x_mod.pow(3)
+                            + group_type::params_type::a * x_mod
+                            + group_type::params_type::b;
+                        BOOST_ASSERT(y2_mod.is_square());
+                        g2_field_value_type y_mod = y2_mod.sqrt();
+                        bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
+                        if (Y_bit == bool(S_bit)) {
+                            g2_value_type result(x_mod, y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        } else {
+                            g2_value_type result(x_mod, -y_mod, g2_field_value_type::one());
+                            BOOST_ASSERT(result.is_well_formed());
+                            point = result;
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_MNT6_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/pallas.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/pallas.hpp
new file mode 100644
index 0000000000..8352df0da2
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/pallas.hpp
@@ -0,0 +1,186 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_PALLAS_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_PALLAS_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+#include <iterator>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/pallas.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                template<typename Coordinates>
+                struct curve_element_marshalling_params<
+                    algebra::curves::pallas::g1_type<Coordinates, algebra::curves::forms::short_weierstrass>
+                > {
+                    using group_type = algebra::curves::pallas::g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+
+                    static constexpr std::size_t length() {
+                        return 1 + bit_length() / 8 + ((bit_length() % 8) != 0);
+                    }
+
+                    static constexpr std::size_t min_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t max_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t bit_length() {
+                        return group_type::field_type::value_bits;
+                    }
+
+                    static constexpr std::size_t min_bit_length() {
+                        return bit_length();
+                    }
+
+                    static constexpr std::size_t max_bit_length() {
+                        return bit_length();
+                    }
+                };
+
+                /*
+                 * Encoding of elliptic curve point according to https://www.secg.org/sec1-v2.pdf
+                 * Curve must be in short weierstrass form, Y^2 = X^3 + A*X + B
+                 * Only X coordinate is encoded, prefixed with either 02 or 03 depending on whether Y is even or odd
+                 * The encoding is big-endian
+                 * Infinity is encoded as 00
+                 * */
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::pallas::template g1_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::pallas::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(const group_value_type &point, TIter &iter)
+                    {
+                        if (point.is_zero()) {
+                            *iter++ = 0x00;
+                            return nil::marshalling::status_type::success;
+                        }
+                        typename group_type::curve_type::template g1_type<typename algebra::curves::coordinates::affine, form>::value_type
+                            point_affine = point.to_affine();
+
+                        *iter++ = (point_affine.Y.data & 1) == 0u ? 0x02 : 0x03;
+                        write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::pallas::template g1_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::pallas::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+                    using curve_params = typename group_type::params_type;
+                    using integral_type = typename group_value_type::field_type::integral_type;
+                    using g1_field_type = typename group_value_type::field_type;
+                    using g1_field_value_type = typename g1_field_type::value_type;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(group_value_type &point, TIter &iter)
+                    {
+                        using chunk_type = typename TIter::value_type;
+
+                        const chunk_type prefix = *iter++;
+
+                        if (0x00 == prefix) {
+                            point = group_value_type::zero();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        if (prefix != 0x02 && prefix != 0x03) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod * x_mod * x_mod + curve_params::a * x_mod + curve_params::b;
+                        if (!y2_mod.is_square()) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+
+                        const chunk_type expected_prefix = (y_mod.data & 1) == 0u ? 0x02 : 0x03;
+
+                        if (expected_prefix == prefix) {
+                            point = group_value_type(x_mod, y_mod);
+                        } else {
+                            point = group_value_type(x_mod, -y_mod);
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_PALLAS_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_k1.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_k1.hpp
new file mode 100644
index 0000000000..0ab5ca6d4f
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_k1.hpp
@@ -0,0 +1,190 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_SECP_K1_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_SECP_K1_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+#include <iterator>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+#include <nil/crypto3/algebra/curves/detail/secp_k1/types.hpp>
+#include <nil/crypto3/algebra/curves/detail/secp_k1/g1.hpp>
+#include <nil/crypto3/algebra/curves/secp_k1.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                template<std::size_t Version>
+                struct curve_element_marshalling_params<
+                    typename algebra::curves::detail::secp_k1_g1<
+                        Version,
+                        algebra::curves::forms::short_weierstrass,
+                        algebra::curves::coordinates::jacobian_with_a4_0>
+                > {
+                    using group_type = typename algebra::curves::secp_k1<Version>::template g1_type<>;
+
+                    static constexpr std::size_t length() {
+                        return 1 + bit_length() / 8 + ((bit_length() % 8) != 0);
+                    }
+
+                    static constexpr std::size_t min_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t max_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t bit_length() {
+                        return group_type::field_type::value_bits;
+                    }
+
+                    static constexpr std::size_t min_bit_length() {
+                        return bit_length();
+                    }
+
+                    static constexpr std::size_t max_bit_length() {
+                        return bit_length();
+                    }
+                };
+
+                /*
+                 * Encoding of elliptic curve point according to https://www.secg.org/sec1-v2.pdf
+                 * Curve must be in short weierstrass form, Y^2 = X^3 + A*X + B
+                 * Only X coordinate is encoded, prefixed with either 02 or 03 depending on whether Y is even or odd
+                 * The encoding is big-endian
+                 * Infinity is encoded as 00
+                 * */
+                template<std::size_t Version>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::detail::secp_k1_g1<
+                        Version,
+                        algebra::curves::forms::short_weierstrass,
+                        algebra::curves::coordinates::jacobian_with_a4_0> > {
+                    using group_type = typename algebra::curves::secp_k1<Version>::template g1_type<>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(const group_value_type &point, TIter &iter)
+                    {
+                        if (point.is_zero()) {
+                            *iter++ = 0x00;
+                            return nil::marshalling::status_type::success;
+                        }
+                        typename group_type::curve_type::template g1_type<typename algebra::curves::coordinates::affine, form>::value_type
+                            point_affine = point.to_affine();
+
+                        *iter++ = (point_affine.Y.data & 1) == 0u ? 0x02 : 0x03;
+                        write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates, std::size_t Version>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::detail::secp_k1_g1<Version, algebra::curves::forms::short_weierstrass, Coordinates >> {
+
+                    using group_type = typename algebra::curves::secp_k1<Version>::template g1_type<>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+                    using curve_params = typename group_type::params_type;
+                    using integral_type = typename group_value_type::field_type::integral_type;
+                    using g1_field_type = typename group_value_type::field_type;
+                    using g1_field_value_type = typename g1_field_type::value_type;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(group_value_type &point, TIter &iter)
+                    {
+                        using chunk_type = typename TIter::value_type;
+
+                        const chunk_type prefix = *iter++;
+
+                        if (0x00 == prefix) {
+                            point = group_value_type::zero();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        if (prefix != 0x02 && prefix != 0x03) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod * x_mod * x_mod + curve_params::a * x_mod + curve_params::b;
+                        if (!y2_mod.is_square()) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+
+                        const chunk_type expected_prefix = (y_mod.data & 1) == 0u ? 0x02 : 0x03;
+
+                        if (expected_prefix == prefix) {
+                            point = group_value_type(x_mod, y_mod);
+                        } else {
+                            point = group_value_type(x_mod, -y_mod);
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_SECP_K1_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_r1.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_r1.hpp
new file mode 100644
index 0000000000..bccaa173ab
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_r1.hpp
@@ -0,0 +1,190 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_SECP_R1_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_SECP_R1_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+#include <iterator>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+#include <nil/crypto3/algebra/curves/detail/secp_r1/types.hpp>
+#include <nil/crypto3/algebra/curves/detail/secp_r1/g1.hpp>
+#include <nil/crypto3/algebra/curves/secp_r1.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                template<std::size_t Version>
+                struct curve_element_marshalling_params<
+                    typename algebra::curves::detail::secp_r1_g1<
+                        Version,
+                        algebra::curves::forms::short_weierstrass,
+                        algebra::curves::coordinates::projective>
+                > {
+                    using group_type = typename algebra::curves::secp_r1<Version>::template g1_type<>;
+
+                    static constexpr std::size_t length() {
+                        return 1 + bit_length() / 8 + ((bit_length() % 8) != 0);
+                    }
+
+                    static constexpr std::size_t min_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t max_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t bit_length() {
+                        return group_type::field_type::value_bits;
+                    }
+
+                    static constexpr std::size_t min_bit_length() {
+                        return bit_length();
+                    }
+
+                    static constexpr std::size_t max_bit_length() {
+                        return bit_length();
+                    }
+                };
+
+                /*
+                 * Encoding of elliptic curve point according to https://www.secg.org/sec1-v2.pdf
+                 * Curve must be in short weierstrass form, Y^2 = X^3 + A*X + B
+                 * Only X coordinate is encoded, prefixed with either 02 or 03 depending on whether Y is even or odd
+                 * The encoding is big-endian
+                 * Infinity is encoded as 00
+                 * */
+                template<std::size_t Version>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::detail::secp_r1_g1<
+                        Version,
+                        algebra::curves::forms::short_weierstrass,
+                        algebra::curves::coordinates::projective> > {
+                    using group_type = typename algebra::curves::secp_r1<Version>::template g1_type<>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(const group_value_type &point, TIter &iter)
+                    {
+                        if (point.is_zero()) {
+                            *iter++ = 0x00;
+                            return nil::marshalling::status_type::success;
+                        }
+                        typename group_type::curve_type::template g1_type<typename algebra::curves::coordinates::affine, form>::value_type
+                            point_affine = point.to_affine();
+
+                        *iter++ = (point_affine.Y.data & 1) == 0u ? 0x02 : 0x03;
+                        write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates, std::size_t Version>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::detail::secp_r1_g1<Version, algebra::curves::forms::short_weierstrass, Coordinates >> {
+
+                    using group_type = typename algebra::curves::secp_r1<Version>::template g1_type<>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+                    using curve_params = typename group_type::params_type;
+                    using integral_type = typename group_value_type::field_type::integral_type;
+                    using g1_field_type = typename group_value_type::field_type;
+                    using g1_field_value_type = typename g1_field_type::value_type;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(group_value_type &point, TIter &iter)
+                    {
+                        using chunk_type = typename TIter::value_type;
+
+                        const chunk_type prefix = *iter++;
+
+                        if (0x00 == prefix) {
+                            point = group_value_type::zero();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        if (prefix != 0x02 && prefix != 0x03) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod * x_mod * x_mod + curve_params::a * x_mod + curve_params::b;
+                        if (!y2_mod.is_square()) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+
+                        const chunk_type expected_prefix = (y_mod.data & 1) == 0u ? 0x02 : 0x03;
+
+                        if (expected_prefix == prefix) {
+                            point = group_value_type(x_mod, y_mod);
+                        } else {
+                            point = group_value_type(x_mod, -y_mod);
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_SECP_R1_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/vesta.hpp b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/vesta.hpp
new file mode 100644
index 0000000000..8b3afa47f4
--- /dev/null
+++ b/libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/vesta.hpp
@@ -0,0 +1,186 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@nil.foundation>
+//
+// MIT License
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//---------------------------------------------------------------------------//
+
+#ifndef CRYPTO3_MARSHALLING_PROCESSING_VESTA_CURVE_ELEMENT_HPP
+#define CRYPTO3_MARSHALLING_PROCESSING_VESTA_CURVE_ELEMENT_HPP
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+#include <iterator>
+
+#include <nil/marshalling/endianness.hpp>
+#include <nil/marshalling/status_type.hpp>
+
+#include <nil/crypto3/algebra/type_traits.hpp>
+
+#include <nil/crypto3/algebra/curves/vesta.hpp>
+
+#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
+
+namespace nil {
+    namespace crypto3 {
+        namespace marshalling {
+            namespace processing {
+
+                template<typename Coordinates>
+                struct curve_element_marshalling_params<
+                    algebra::curves::vesta::g1_type<Coordinates, algebra::curves::forms::short_weierstrass>
+                > {
+                    using group_type = algebra::curves::vesta::g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+
+                    static constexpr std::size_t length() {
+                        return 1 + bit_length() / 8 + ((bit_length() % 8) != 0);
+                    }
+
+                    static constexpr std::size_t min_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t max_length() {
+                        return length();
+                    }
+
+                    static constexpr std::size_t bit_length() {
+                        return group_type::field_type::value_bits;
+                    }
+
+                    static constexpr std::size_t min_bit_length() {
+                        return bit_length();
+                    }
+
+                    static constexpr std::size_t max_bit_length() {
+                        return bit_length();
+                    }
+                };
+
+                /*
+                 * Encoding of elliptic curve point according to https://www.secg.org/sec1-v2.pdf
+                 * Curve must be in short weierstrass form, Y^2 = X^3 + A*X + B
+                 * Only X coordinate is encoded, prefixed with either 02 or 03 depending on whether Y is even or odd
+                 * The encoding is big-endian
+                 * Infinity is encoded as 00
+                 * */
+                template<typename Coordinates>
+                struct curve_element_writer<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::vesta::template g1_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::vesta::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(const group_value_type &point, TIter &iter)
+                    {
+                        if (point.is_zero()) {
+                            *iter++ = 0x00;
+                            return nil::marshalling::status_type::success;
+                        }
+                        typename group_type::curve_type::template g1_type<typename algebra::curves::coordinates::affine, form>::value_type
+                            point_affine = point.to_affine();
+
+                        *iter++ = (point_affine.Y.data & 1) == 0u ? 0x02 : 0x03;
+                        write_data<params_type::bit_length(), endianness>(
+                                static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
+                                iter);
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+                template<typename Coordinates>
+                struct curve_element_reader<
+                    nil::marshalling::endian::big_endian,
+                    typename algebra::curves::vesta::template g1_type<Coordinates,
+                                                                          algebra::curves::forms::short_weierstrass>> {
+                    using group_type = typename algebra::curves::vesta::
+                        template g1_type<Coordinates, algebra::curves::forms::short_weierstrass>;
+                    using group_value_type = typename group_type::value_type;
+                    using coordinates = typename group_value_type::coordinates;
+                    using form = typename group_value_type::form;
+                    using endianness = nil::marshalling::endian::big_endian;
+                    using params_type = curve_element_marshalling_params<group_type>;
+                    using curve_params = typename group_type::params_type;
+                    using integral_type = typename group_value_type::field_type::integral_type;
+                    using g1_field_type = typename group_value_type::field_type;
+                    using g1_field_value_type = typename g1_field_type::value_type;
+
+                    template<typename TIter>
+                    static typename std::enable_if<
+                        std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
+                        nil::marshalling::status_type>::type
+                    process(group_value_type &point, TIter &iter)
+                    {
+                        using chunk_type = typename TIter::value_type;
+
+                        const chunk_type prefix = *iter++;
+
+                        if (0x00 == prefix) {
+                            point = group_value_type::zero();
+                            return nil::marshalling::status_type::success;
+                        }
+
+                        if (prefix != 0x02 && prefix != 0x03) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        constexpr static const std::size_t sizeof_field_element =
+                            params_type::bit_length() / (group_value_type::field_type::arity);
+                        integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
+
+                        g1_field_value_type x_mod(x);
+                        g1_field_value_type y2_mod = x_mod * x_mod * x_mod + curve_params::a * x_mod + curve_params::b;
+                        if (!y2_mod.is_square()) {
+                            return nil::marshalling::status_type::invalid_msg_data;
+                        }
+
+                        g1_field_value_type y_mod = y2_mod.sqrt();
+
+                        const chunk_type expected_prefix = (y_mod.data & 1) == 0u ? 0x02 : 0x03;
+
+                        if (expected_prefix == prefix) {
+                            point = group_value_type(x_mod, y_mod);
+                        } else {
+                            point = group_value_type(x_mod, -y_mod);
+                        }
+
+                        return nil::marshalling::status_type::success;
+                    }
+                };
+
+            }    // namespace processing
+        }        // namespace marshalling
+    }            // namespace crypto3
+}    // namespace nil
+#endif    // CRYPTO3_MARSHALLING_PROCESSING_VESTA_CURVE_ELEMENT_HPP
diff --git a/libs/marshalling/algebra/test/curve_element.cpp b/libs/marshalling/algebra/test/curve_element.cpp
index f6d6a8977d..2b76da7b17 100644
--- a/libs/marshalling/algebra/test/curve_element.cpp
+++ b/libs/marshalling/algebra/test/curve_element.cpp
@@ -63,25 +63,32 @@
 #include <nil/crypto3/algebra/curves/secp_k1.hpp>
 #include <nil/crypto3/algebra/curves/secp_r1.hpp>
 #include <nil/crypto3/algebra/curves/ed25519.hpp>
-#include <nil/crypto3/algebra/curves/curve25519.hpp>
 
 #include <nil/marshalling/algorithms/pack.hpp>
 
 #include <nil/crypto3/marshalling/algebra/types/curve_element.hpp>
 
-template<typename TIter>
-void print_byteblob(TIter iter_begin, TIter iter_end) {
-    for (TIter it = iter_begin; it != iter_end; it++) {
-        std::cout << std::hex << std::setw(2) << std::setfill('0') << int(*it);
-    }
-    std::cout << std::endl;
-}
+#include <nil/crypto3/marshalling/algebra/processing/mnt4.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/mnt6.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/bls12.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/alt_bn128.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/jubjub.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/babyjubjub.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/ed25519.hpp>
 
-template<typename T>
-void test_group_element_big_endian(T val) {
+#include <nil/crypto3/marshalling/algebra/processing/pallas.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/vesta.hpp>
+
+#include <nil/crypto3/marshalling/algebra/processing/secp_k1.hpp>
+#include <nil/crypto3/marshalling/algebra/processing/secp_r1.hpp>
+
+template<typename T, typename endianness>
+void test_group_element(T val) {
     using namespace nil::crypto3::marshalling;
 
-    using Endianness = nil::marshalling::option::big_endian;
 
     using unit_type = unsigned char;
 
@@ -94,21 +101,21 @@ void test_group_element_big_endian(T val) {
     static_assert(nil::marshalling::is_compatible<T>::value);
     nil::marshalling::status_type status;
 
-    std::vector<unit_type> cv = nil::marshalling::pack<Endianness>(val, status);
+    std::vector<unit_type> cv = nil::marshalling::pack<endianness>(val, status);
     BOOST_CHECK(status == nil::marshalling::status_type::success);
 
-    T test_val = nil::marshalling::pack<Endianness>(cv, status);
+    T test_val = nil::marshalling::pack<endianness>(cv, status);
     BOOST_CHECK(status == nil::marshalling::status_type::success);
 
-    BOOST_CHECK(val == test_val);
+    BOOST_CHECK_EQUAL(val.to_affine(), test_val.to_affine());
 }
 
-template<typename group_type>
-void test_group_element() {
+template<typename group_type, typename endianness>
+void test_group_element_set() {
 
     /* test default element - zero for GT and infinity for G1/G2 */
     typename group_type::value_type val = typename group_type::value_type();
-    test_group_element_big_endian(val);
+    test_group_element<typename group_type::value_type, endianness>(val);
 
     /* test 128 random points */
     for (std::size_t i = 0; i < 128; ++i) {
@@ -116,34 +123,34 @@ void test_group_element() {
             std::cout << std::dec << i << " tested" << std::endl;
         }
         val = nil::crypto3::algebra::random_element<group_type>();
-        test_group_element_big_endian(val);
+        test_group_element<typename group_type::value_type, endianness>(val);
     }
 }
 
-template<typename curve_type>
+template<typename curve_type, typename endianness>
 void test_curve(std::string curve_name)
 {
     std::cout << "Testing curve: " << curve_name << std::endl;
 
     std::cout << "Marshaling of G1 group elements" << std::endl;
-    test_group_element<typename curve_type::template g1_type<>>();
+    test_group_element_set<typename curve_type::template g1_type<>, endianness>();
 
     std::cout << "Testing of " << curve_name << " finished" << std::endl;
 
 }
 
-template<typename curve_type>
+template<typename curve_type, typename endianness>
 void test_pairing_curve(std::string curve_name)
 {
     std::cout << "Testing curve: " << curve_name << std::endl;
 
     std::cout << "Marshaling of G1 group elements" << std::endl;
-    test_group_element<typename curve_type::template g1_type<>>();
+    test_group_element_set<typename curve_type::template g1_type<>, endianness>();
 
     std::cout << "Marshaling of G2 group elements" << std::endl;
-    test_group_element<typename curve_type::template g2_type<>>();
+    test_group_element_set<typename curve_type::template g2_type<>, endianness>();
 
-    /* TODO: do we really need to marshal GT elements? 
+    /* TODO: do we really need to marshal GT elements?
     std::cout << "Marshaling of GT group elements" << std::endl;
     test_group_element<typename curve_type::gt_type>();
     */
@@ -154,68 +161,61 @@ void test_pairing_curve(std::string curve_name)
 
 BOOST_AUTO_TEST_SUITE(curve_element_test_suite)
 
+using big_endian = nil::marshalling::option::big_endian;
+using little_endian = nil::marshalling::option::little_endian;
+
 BOOST_AUTO_TEST_CASE(curve_element_mnt4) {
-    test_pairing_curve<nil::crypto3::algebra::curves::mnt4_298>("mnt4_298");
+    test_pairing_curve<nil::crypto3::algebra::curves::mnt4_298, big_endian>("mnt4_298");
 }
 
 BOOST_AUTO_TEST_CASE(curve_element_mnt6) {
-    test_pairing_curve<nil::crypto3::algebra::curves::mnt6_298>("mnt6_298");
+    test_pairing_curve<nil::crypto3::algebra::curves::mnt6_298, big_endian>("mnt6_298");
 }
 
 BOOST_AUTO_TEST_CASE(curve_element_bls12_381) {
-    test_pairing_curve<nil::crypto3::algebra::curves::bls12_381>("bls12_381");
+    test_pairing_curve<nil::crypto3::algebra::curves::bls12_381, big_endian>("bls12_381");
 }
 
-// TODO: implement marshalling for bls12<377>
-#if 0
 BOOST_AUTO_TEST_CASE(curve_element_bls12_377) {
-    test_curve<nil::crypto3::algebra::curves::bls12_377>("bls12_377");
+    test_pairing_curve<nil::crypto3::algebra::curves::bls12_377, big_endian>("bls12_377");
 }
-#endif
 
 BOOST_AUTO_TEST_CASE(curve_element_bn254) {
-    test_pairing_curve<nil::crypto3::algebra::curves::alt_bn128_254>("alt_bn128_254");
+    test_pairing_curve<nil::crypto3::algebra::curves::alt_bn128_254, big_endian>("alt_bn128_254");
 }
 
-// TODO: implement marshalling for pasta curves
-#if 0
 BOOST_AUTO_TEST_CASE(curve_element_pallas) {
-    test_curve<nil::crypto3::algebra::curves::pallas>("pallas");
+    test_curve<nil::crypto3::algebra::curves::pallas, big_endian>("pallas");
 }
 
 BOOST_AUTO_TEST_CASE(curve_element_vesta) {
-    test_curve<nil::crypto3::algebra::curves::vesta>("vesta");
+    test_curve<nil::crypto3::algebra::curves::vesta, big_endian>("vesta");
 }
-#endif
 
-// TODO: implement marshalling for secp_k1/secp_r1 curves
-#if 0
 BOOST_AUTO_TEST_CASE(curve_element_secp_k1) {
-    test_curve<nil::crypto3::algebra::curves::secp_k1<160>>("secp_k1<160>");
+    test_curve<nil::crypto3::algebra::curves::secp_k1<160>, big_endian>("secp_k1<160>");
+    test_curve<nil::crypto3::algebra::curves::secp_k1<192>, big_endian>("secp_k1<192>");
+    test_curve<nil::crypto3::algebra::curves::secp_k1<224>, big_endian>("secp_k1<224>");
+    test_curve<nil::crypto3::algebra::curves::secp_k1<256>, big_endian>("secp_k1<256>");
 }
 
 BOOST_AUTO_TEST_CASE(curve_element_secp_r1) {
-    test_curve<nil::crypto3::algebra::curves::secp_r1<160>>("secp_r1<160>");
+    test_curve<nil::crypto3::algebra::curves::secp_r1<160>, big_endian>("secp_r1<160>");
+    test_curve<nil::crypto3::algebra::curves::secp_r1<192>, big_endian>("secp_r1<192>");
+    test_curve<nil::crypto3::algebra::curves::secp_r1<224>, big_endian>("secp_r1<224>");
+    test_curve<nil::crypto3::algebra::curves::secp_r1<256>, big_endian>("secp_r1<256>");
 }
-#endif
 
-/* TODO: add marshalling for jubjub/babyjubjub/ed25519/curve25519, it is broken for now */
-#if 0
 BOOST_AUTO_TEST_CASE(curve_element_jubjub) {
-    test_curve<nil::crypto3::algebra::curves::jubjub>("jubjub");
+    test_curve<nil::crypto3::algebra::curves::jubjub, little_endian>("jubjub");
 }
 
 BOOST_AUTO_TEST_CASE(curve_element_babyjubjub) {
-    test_curve<nil::crypto3::algebra::curves::jubjub>("babyjubjub");
+    test_curve<nil::crypto3::algebra::curves::babyjubjub, little_endian>("babyjubjub");
 }
 
 BOOST_AUTO_TEST_CASE(curve_element_ed25519) {
-    test_curve<nil::crypto3::algebra::curves::ed25519>("ed25519");
-}
-
-BOOST_AUTO_TEST_CASE(curve_element_curve25519) {
-    test_curve<nil::crypto3::algebra::curves::curve25519>("curve25519");
+    test_curve<nil::crypto3::algebra::curves::ed25519, little_endian>("ed25519");
 }
-#endif
 
 BOOST_AUTO_TEST_SUITE_END()