Skip to content

Commit

Permalink
Add to_bytes method
Browse files Browse the repository at this point in the history
  • Loading branch information
smlu committed Dec 21, 2023
1 parent 1120ae6 commit 3311478
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 0 deletions.
33 changes: 33 additions & 0 deletions include/ack/fe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ namespace ack {
return Derived::one();
}

/**
* Returns the max element bytes size.
* @return max element size.
*/
constexpr std::size_t max_byte_length() const
{
return underlying().max_byte_length();
}

/**
* Casts this element to big integer.
* @return const reference to big integer representation of this element.
Expand Down Expand Up @@ -82,6 +91,30 @@ namespace ack {
return underlying().is_negative();
}

/**
* Returns the byte-encoded representation of this object.
*
* @param len - The desired length of the byte-encoded representation
* The full byte-encoded representation is returned if len is smaller
* than the byte length of the original object.
*
* @return The byte-encoded representation of this object.
*/
bytes to_bytes(std::size_t len) const
{
return underlying().to_bytes( len );
}

/**
* Returns the byte-encoded representation of this object of size max_byte_length().
* @return The byte-encoded representation of this object.
*/
bytes to_bytes() const
{
auto len = max_byte_length();
return to_bytes( len );
}

/**
* Returns the inverse of this element, i.e. 1 / this.
* @return Inverse of this element.
Expand Down
34 changes: 34 additions & 0 deletions include/ack/fp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ namespace ack {
public:
using base_type = field_element<fp_element<IntT, PrimeFieldTag>, IntT, PrimeFieldTag>;
using base_type::base_type;
using base_type::to_bytes;

/**
* Constructs a zero finite field element.
Expand Down Expand Up @@ -527,6 +528,18 @@ namespace ack {
constexpr fp_element& operator=(const fp_element& other) = default;
constexpr fp_element& operator=(fp_element&& other) = default;

/**
* Returns the max element bytes size.
* @return max element size.
*/
constexpr std::size_t max_byte_length() const
{
if ( !is_valid()) {
return 0;
}
return ( *pm_ - 1 ).byte_length();
}

/**
* Assigns big integer value to the finite field element.
* If element is invalid, then it will not be changed.
Expand Down Expand Up @@ -638,6 +651,27 @@ namespace ack {
return v_.is_negative();
}

/**
* Returns the byte-encoded representation of this object.
*
* @param len - The desired length of the byte-encoded representation
* The full byte-encoded representation is returned if len is smaller
* than the byte length of the original object.
*
* @return The byte-encoded representation of this object.
*/
bytes to_bytes(std::size_t len) const
{
bytes ev;
if ( is_valid() ) {
ev = v_.to_bytes();
if ( len > ev.size() ) {
ev = bytes( len - ev.size(), 0 ) + ev;
}
}
return ev;
}

/**
* Calculates modular inverse of this finite field element.
* @return (1 / this) % modulus.
Expand Down
17 changes: 17 additions & 0 deletions include/ack/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,21 @@ namespace ack {
ds.skip( s );
return ds;
}

template<typename T, typename AllocA = std::allocator<T>, typename AllocB = std::allocator<T>>
inline std::vector<T, AllocA> operator + (const std::vector<T, AllocA>& a, const std::vector<T, AllocB>& b)
{
std::vector<T, AllocA> c;
c.reserve(a.size() + b.size() );
std::copy( a.begin(), a.end(), std::back_inserter( c) );
std::copy( b.begin(), b.end(), std::back_inserter( c) );
return c;
}

template<typename T, typename AllocA = std::allocator<T>, typename AllocB = std::allocator<T>>
inline std::vector<T, AllocA>& operator += (std::vector<T, AllocA>& a, const std::vector<T, AllocB>& b)
{
a.insert( a.end(), b.begin(), b.end() );
return a;
}
}
111 changes: 111 additions & 0 deletions tests/include/ack/tests/fp_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3552,6 +3552,117 @@ namespace ack::tests {
fe /= b;
REQUIRE_EQUAL( fe, "2F1F1FE098ED612AC09FE67F0DF9AE18AC979376C" )
}

// misc
{
// encoding to bytes
auto mod = bn_t( "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" );
auto fe = fpe_t( 0U, mod );
REQUIRE_EQUAL( fe.to_bytes( 0 ), "00"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "00"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "0000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "000000"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000000000000"_hex )

fe = 1;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "01"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "01"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "0001"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "000001"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000000000001"_hex )

fe = 0x0f;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "0F"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "0F"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "000F"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "00000F"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "000000000000000000000000000000000000000000000000000000000000000F"_hex )

fe = 0xff;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "FF"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "FF"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "00FF"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "0000FF"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "00000000000000000000000000000000000000000000000000000000000000FF"_hex )

fe = 0x100;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "0100"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "0100"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "0100"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "000100"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000000000100"_hex )

fe = 0x1000;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "1000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "1000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "1000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "001000"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000000001000"_hex )

fe = 0x10000;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "010000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "010000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "010000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "010000"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000000010000"_hex )

fe = 0x100000;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "100000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "100000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "100000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "100000"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000000100000"_hex )

fe = 0xffffff;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "FFFFFF"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "FFFFFF"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "FFFFFF"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "FFFFFF"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000000FFFFFF"_hex )

fe = 0x1000000;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "01000000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "01000000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "01000000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "01000000"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000001000000"_hex )

fe = 0x10000000;
REQUIRE_EQUAL( fe.to_bytes( 0 ), "10000000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ), "10000000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ), "10000000"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ), "10000000"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "0000000000000000000000000000000000000000000000000000000010000000"_hex )

fe = "2F1F1FE098ED612AC09FE67F0DF9AE18AC979376C";
REQUIRE_EQUAL( fe.to_bytes( 0 ) , "02F1F1FE098ED612AC09FE67F0DF9AE18AC979376C"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ) , "02F1F1FE098ED612AC09FE67F0DF9AE18AC979376C"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ) , "02F1F1FE098ED612AC09FE67F0DF9AE18AC979376C"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ) , "02F1F1FE098ED612AC09FE67F0DF9AE18AC979376C"_hex )
REQUIRE_EQUAL( fe.to_bytes( 21 ), "02F1F1FE098ED612AC09FE67F0DF9AE18AC979376C"_hex )
REQUIRE_EQUAL( fe.to_bytes( 22 ), "0002F1F1FE098ED612AC09FE67F0DF9AE18AC979376C"_hex )
REQUIRE_EQUAL( fe.to_bytes( 23 ), "000002F1F1FE098ED612AC09FE67F0DF9AE18AC979376C"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "000000000000000000000002F1F1FE098ED612AC09FE67F0DF9AE18AC979376C"_hex )

fe = mod - 1;
REQUIRE_EQUAL( fe.to_bytes( 0 ) , "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 1 ) , "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 2 ) , "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 3 ) , "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 21 ), "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 22 ), "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 23 ), "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 32 ), "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 33 ), "00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes( 34 ), "0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )
REQUIRE_EQUAL( fe.to_bytes() , "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"_hex )

// Should return empty bytes when invalid field element
fe = mod + 1;
REQUIRE_EQUAL( fe.to_bytes(), ""_hex )
REQUIRE_EQUAL( fpe_t::zero().to_bytes(), ""_hex )
REQUIRE_EQUAL( fpe_t::one().to_bytes(), ""_hex )
}
EOSIO_TEST_END // fp_element_test

EOSIO_TEST_BEGIN(fp_test)
Expand Down

0 comments on commit 3311478

Please sign in to comment.