From de1746cbef0521d0462ae480b47b74e085947850 Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Wed, 12 Oct 2022 10:10:40 -0400 Subject: [PATCH 1/6] Crypto extension wrappers for C++ --- libraries/eosiolib/core/eosio/crypto_ext.hpp | 246 +++++++++++++++++- tests/CMakeLists.txt | 1 + tests/integration/crypto_tests.cpp | 167 +++++++++++- tests/unit/CMakeLists.txt | 1 + tests/unit/crypto_ext_tests.cpp | 96 +++++++ .../crypto_primitives_tests.cpp | 99 +++++++ 6 files changed, 607 insertions(+), 3 deletions(-) create mode 100644 tests/unit/crypto_ext_tests.cpp diff --git a/libraries/eosiolib/core/eosio/crypto_ext.hpp b/libraries/eosiolib/core/eosio/crypto_ext.hpp index 04fe2bc060..5823a650cf 100644 --- a/libraries/eosiolib/core/eosio/crypto_ext.hpp +++ b/libraries/eosiolib/core/eosio/crypto_ext.hpp @@ -4,6 +4,7 @@ */ #pragma once +#include "check.hpp" #include "fixed_bytes.hpp" #include "varint.hpp" #include "serialize.hpp" @@ -48,7 +49,7 @@ namespace eosio { return dg; } } - + /** * @defgroup crypto Crypto * @ingroup core @@ -56,6 +57,174 @@ namespace eosio { * require activating crypto protocol feature */ + /** + * Abstracts G1 and G2 points. Ensures sizes of x and y are valid + * + * @ingroup crypto + */ + struct point_view { + /** + * Pointer to the x coordinate + */ + char* x; + + /** + * Pointer to the y coordinate + */ + char* y; + + /** + * Number of bytes in each of x and y + */ + uint32_t size; + + /** + * Construct a point given x and y + * + * @param x_ - The x coordinate, a vector of chars + * @param y_ - The y coordinate, a vector of chars + */ + point_view(std::vector& x_, std::vector& y_) + :x(x_.data()), y(y_.data()), size(x_.size()) + { + eosio::check( x_.size() == y_.size(), "x's size must be equal to y's" ); + }; + + /** + * Construct a point given a serialized point + * + * @param p - The serialized point + */ + point_view(std::vector& p) + :x(p.data()), y(p.data() + p.size()/2), size(p.size()/2) + { + }; + + /** + * Returns packed x and y + */ + std::vector packed() const { + std::vector x_and_y( x, x + size ); + x_and_y.insert( x_and_y.end(), y, y + size ); + return x_and_y; + } + + /** + * Unpacks a seralized point and populates current point + * + * @param packed - The source serialized point + */ + void unpack(const std::vector& packed) { + eosio::check( packed.size() == 2 * size, "size of packed point must be equal to x's size" ); + std::memcpy(x, packed.data(), size); + std::memcpy(y, packed.data() + size, size); + } + }; + + static constexpr size_t g1_coordinate_size = 32; + static constexpr size_t g2_coordinate_size = 64; + static constexpr size_t blake2f_result_size = 64; + + /** + * Abstracts G1 point. Ensures sizes of x and y are 32 + * + * @ingroup crypto + */ + struct g1_view : public point_view { + /** + * Construct a G1 point given x and y + * + * @param x_ - The x coordinate, a vector of chars + * @param y_ - The y coordinate, a vector of chars + */ + g1_view(std::vector& x_, std::vector& y_) + : point_view(x_, y_) + { + eosio::check( size == g1_coordinate_size, "G1 coordinate size must be 32" ); + } + + /** + * Construct a point given a serialized point + * + * @param p - The serialized point + */ + g1_view(std::vector& p) + : point_view(p) + { + eosio::check( p.size() == g1_coordinate_size * 2, "G1 serialized size must be 64" ); + }; + }; + + /** + * Abstracts G2 point. Ensures sizes of x and y are 64 + * + * @ingroup crypto + */ + struct g2_view : public point_view { + /** + * Construct a G2 point given x and y + * + * @param x_ - The x coordinate, a vector of chars + * @param y_ - The y coordinate, a vector of chars + */ + g2_view(std::vector& x_, std::vector& y_) + : point_view(x_, y_) + { + eosio::check( size == g2_coordinate_size, "G2 coordinate size must be 64" ); + } + + /** + * Construct a point given a serialized point + * + * @param p - The serialized point + */ + g2_view(std::vector& p) + : point_view(p) + { + eosio::check( p.size() == g2_coordinate_size * 2, "G2 serialized size must be 128" ); + }; + }; + + /** + * Abstracts big integer. + * + * @ingroup crypto + */ + struct bigint { + /** + * Construct a bigint given a vector of chars (bytes) + * + * @param s - The source bytes + */ + bigint(std::vector& s) + :data(s.data()), size(s.size()) + { + }; + + char* data; + uint32_t size; + }; + + /** + * Addition operation on the elliptic curve `alt_bn128` + * + * @ingroup crypto + * @param op1 - operand 1 + * @param op2 - operand 2 + * @param result - result of the addition operation + * @return -1 if there is an error otherwise 0 + */ + inline int32_t alt_bn128_add( const g1_view& op1, const g1_view& op2, g1_view& result) { + auto op_1 = op1.packed(); + auto op_2 = op2.packed(); + std::vector rslt(2*result.size); // buffer storing x and y + auto ret = internal_use_do_not_use::alt_bn128_add( op_1.data(), op_1.size(), op_2.data(), op_2.size(), rslt.data(), rslt.size()); + if ( ret == 0 ) { + result.unpack(rslt); // unpack rslt into result + } + return ret; + } + /** * Addition operation on the elliptic curve `alt_bn128` * @@ -72,6 +241,25 @@ namespace eosio { return internal_use_do_not_use::alt_bn128_add( op1, op1_len, op2, op2_len, result, result_len); } + /** + * Scalar multiplication operation on the elliptic curve `alt_bn128` + * + * @ingroup crypto + * @param g1 - G1 point + * @param scalar - scalar factor + * @param result - result of the scalar multiplication operation + * @return -1 if there is an error otherwise 0 + */ + inline int32_t alt_bn128_mul( const g1_view& g1, const bigint& scalar, g1_view& result) { + auto g1_bin = g1.packed(); + std::vector rslt(2*result.size); + auto ret = internal_use_do_not_use::alt_bn128_mul( g1_bin.data(), g1_bin.size(), scalar.data, scalar.size, rslt.data(), rslt.size()); + if ( ret == 0 ) { + result.unpack(rslt); + } + return ret; + } + /** * Scalar multiplication operation on the elliptic curve `alt_bn128` * @@ -88,19 +276,54 @@ namespace eosio { return internal_use_do_not_use::alt_bn128_mul( g1, g1_len, scalar, scalar_len, result, result_len ); } + /** + * Optimal-Ate pairing check elliptic curve `alt_bn128` + * + * @ingroup crypto + * @param pairs - g1 and g2 pairs + * @return -1 if there is an error, 1 if false and 0 if true and successful + */ + inline int32_t alt_bn128_pair( const std::vector>& pairs ) { + std::vector g1_g2_pairs; + for ( const auto& pair: pairs ) { + auto g1_bin = pair.first.packed(); + auto g2_bin = pair.second.packed(); + g1_g2_pairs.insert( g1_g2_pairs.end(), g1_bin.begin(), g1_bin.end() ); + g1_g2_pairs.insert( g1_g2_pairs.end(), g2_bin.begin(), g2_bin.end() ); + } + return internal_use_do_not_use::alt_bn128_pair( g1_g2_pairs.data(), g1_g2_pairs.size() ); + } + /** * Optimal-Ate pairing check elliptic curve `alt_bn128` * * @ingroup crypto * @param pairs - g1 and g2 pairs * @param pairs_len - size of pairs - * @param result - result of the addition operation * @return -1 if there is an error, 1 if false and 0 if true and successful */ inline int32_t alt_bn128_pair( const char* pairs, uint32_t pairs_len ) { return internal_use_do_not_use::alt_bn128_pair( pairs, pairs_len ); } + /** + * Big integer modular exponentiation + * returns an output ( BASE^EXP ) % MOD + * + * @ingroup crypto + * @param base - base of the exponentiation (BASE) + * @param exp - exponent to raise to that power (EXP) + * @param mod - modulus (MOD) + * @param result - result of the modular exponentiation + * @return -1 if there is an error otherwise 0 + */ + + inline int32_t mod_exp( const bigint& base, const bigint& exp, const bigint& mod, bigint& result) { + eosio::check( result.size >= mod.size, "mod_exp result parameter's size must be >= mod's size" ); + auto ret = internal_use_do_not_use::mod_exp( base.data, base.size, exp.data, exp.size, mod.data, mod.size, result.data, result.size); + return ret; + } + /** * Big integer modular exponentiation * returns an output ( BASE^EXP ) % MOD @@ -121,6 +344,25 @@ namespace eosio { return internal_use_do_not_use::mod_exp( base, base_len, exp, exp_len, mod, mod_len, result, result_len); } + /** + * BLAKE2 compression function "F" + * https://eips.ethereum.org/EIPS/eip-152 + * + * @ingroup crypto + * @param rounds - the number of rounds + * @param state - state vector + * @param msg - message block vector + * @param t0_offset - offset counters + * @param t1_offset - offset counters + * @param final - final block flag + * @param result - the result of the compression + * @return -1 if there is an error otherwise 0 + */ + int32_t blake2_f( uint32_t rounds, const std::vector& state, const std::vector& msg, const std::vector& t0_offset, const std::vector& t1_offset, bool final, std::vector& result) { + eosio::check( result.size() >= blake2f_result_size, "blake2_f result parameter's size must be >= 64" ); + return internal_use_do_not_use::blake2_f( rounds, state.data(), state.size(), msg.data(), msg.size(), t0_offset.data(), t0_offset.size(), t1_offset.data(), t1_offset.size(), final, result.data(), result.size()); + } + /** * BLAKE2 compression function "F" * https://eips.ethereum.org/EIPS/eip-152 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3c2d6a4a31..9396d8b6c3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,6 +6,7 @@ endmacro() add_unit_test( asset_tests ) add_unit_test( binary_extension_tests ) add_unit_test( crypto_tests ) +add_unit_test( crypto_ext_tests ) add_unit_test( datastream_tests ) add_unit_test( fixed_bytes_tests ) add_unit_test( name_tests ) diff --git a/tests/integration/crypto_tests.cpp b/tests/integration/crypto_tests.cpp index 18cc633ced..5743f98c3b 100644 --- a/tests/integration/crypto_tests.cpp +++ b/tests/integration/crypto_tests.cpp @@ -64,4 +64,169 @@ BOOST_FIXTURE_TEST_CASE( keccak_tests, tester ) try { } FC_LOG_AND_RETHROW() -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_FIXTURE_TEST_CASE( bn128_add_tests, tester ) try { + create_accounts( { "test"_n } ); + produce_block(); + + set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); + set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); + + produce_blocks(); + + push_action("eosio"_n, "addtest"_n, "test"_n, mvo() + ("x1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c09") + ("y1", "2976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") + ("x2", "1bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f5332") + ("y2", "2a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce4649844") + ("expected_rc", 0) + ("expected_x", "16c7c4042e3a725ddbacf197c519c3dcad2bc87dfd9ac7e1e1631154ee0b7d9c") + ("expected_y", "19cd640dd28c9811ebaaa095a16b16190d08d6906c4f926fce581985fe35be0e")); + + // P1 not on curve + push_action("eosio"_n, "addtest"_n, "test"_n, mvo() + ("x1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c09") + ("y1", "2976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") + ("x2", "2a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce4649844") + ("y2", "1bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f5332") + ("expected_rc", -1) + ("expected_x", "0000000000000000000000000000000000000000000000000000000000000000") + ("expected_y", "0000000000000000000000000000000000000000000000000000000000000000")); + +} FC_LOG_AND_RETHROW() + +// Test G1 constructed from a serialized point +BOOST_FIXTURE_TEST_CASE( bn128_add_serialized_tests, tester ) try { + create_accounts( { "test"_n } ); + produce_block(); + + set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); + set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); + + produce_blocks(); + + push_action("eosio"_n, "addtest1"_n, "test"_n, mvo() + ("p1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c092976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") + ("p2", "1bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f53322a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce4649844") + ("expected_rc", 0) + ("expected_x", "16c7c4042e3a725ddbacf197c519c3dcad2bc87dfd9ac7e1e1631154ee0b7d9c") + ("expected_y", "19cd640dd28c9811ebaaa095a16b16190d08d6906c4f926fce581985fe35be0e")); + + // P1 not on curve + push_action("eosio"_n, "addtest1"_n, "test"_n, mvo() + ("p1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c092976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") + ("p2", "2a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce46498441bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f5332") + ("expected_rc", -1) + ("expected_x", "0000000000000000000000000000000000000000000000000000000000000000") + ("expected_y", "0000000000000000000000000000000000000000000000000000000000000000")); + +} FC_LOG_AND_RETHROW() + +BOOST_FIXTURE_TEST_CASE( bn128_mul_tests, tester ) try { + create_accounts( { "test"_n } ); + produce_block(); + + set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); + set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); + + produce_blocks(); + + push_action("eosio"_n, "multest"_n, "test"_n, mvo() + ("g1_x", "007c43fcd125b2b13e2521e395a81727710a46b34fe279adbf1b94c72f7f9136") + ("g1_y", "0db2f980370fb8962751c6ff064f4516a6a93d563388518bb77ab9a6b30755be") + ("scalar", "0312ed43559cf8ecbab5221256a56e567aac5035308e3f1d54954d8b97cd1c9b") + ("expected_rc", 0) + ("expected_x", "2d66cdeca5e1715896a5a924c50a149be87ddd2347b862150fbb0fd7d0b1833c") + ("expected_y", "11c76319ebefc5379f7aa6d85d40169a612597637242a4bbb39e5cd3b844becd")); +} FC_LOG_AND_RETHROW() + +BOOST_FIXTURE_TEST_CASE( bn128_pair_tests, tester ) try { + create_accounts( { "test"_n } ); + produce_block(); + + set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); + set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); + + produce_blocks(); + + push_action("eosio"_n, "pairtest"_n, "test"_n, mvo() + ("g1_a_x", "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2") + ("g1_a_y", "16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba") + ("g2_a_x", "2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3") + ("g2_a_y", "14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590") + ("g1_b_x", "1b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b8") + ("g1_b_y", "11d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21") + ("g2_b_x", "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed") + ("g2_b_y", "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa") + ("expected", 0)); +} FC_LOG_AND_RETHROW() + +// Test G1 and G2 constructed from serialized points +BOOST_FIXTURE_TEST_CASE( bn128_serialized_point_tests, tester ) try { + create_accounts( { "test"_n } ); + produce_block(); + + set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); + set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); + + produce_blocks(); + + push_action("eosio"_n, "pairtest1"_n, "test"_n, mvo() + ("g1a", "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba") + ("g2a", "2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590") + ("g1b", "1b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21") + ("g2b", "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa") + ("expected", 0)); +} FC_LOG_AND_RETHROW() + +BOOST_FIXTURE_TEST_CASE( modexp_tests, tester ) try { + create_accounts( { "test"_n } ); + produce_block(); + + set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); + set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); + + produce_blocks(); + + push_action("eosio"_n, "modexptest"_n, "test"_n, mvo() + ("base", "03") + ("exp", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e") + ("modulo", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f") + ("expected_rc", 0) + ("expected_result", "0000000000000000000000000000000000000000000000000000000000000001")); + + push_action("eosio"_n, "modexptest"_n, "test"_n, mvo() + ("base", "") + ("exp", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e") + ("modulo", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f") + ("expected_rc", 0) + ("expected_result", "0000000000000000000000000000000000000000000000000000000000000000")); + + push_action("eosio"_n, "modexptest"_n, "test"_n, mvo() + ("base", "00") + ("exp", "00") + ("modulo", "0F") + ("expected_rc", 0) + ("expected_result", "01")); +} FC_LOG_AND_RETHROW() + +BOOST_FIXTURE_TEST_CASE( blake2f_tests, tester ) try { + create_accounts( { "test"_n } ); + produce_block(); + + set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); + set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); + + produce_blocks(); + + push_action("eosio"_n, "blake2ftest"_n, "test"_n, mvo() + ("rounds", 0) + ("state", "48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b") + ("msg", "6162630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + ("t0_offset", "0300000000000000") + ("t1_offset", "0000000000000000") + ("final", true) + ("expected_rc", 0) + ("expected_result", "08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b")); +} FC_LOG_AND_RETHROW() + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 29b9004c9d..dd1cad90a9 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -11,6 +11,7 @@ endmacro() add_cdt_unit_test(asset_tests) add_cdt_unit_test(binary_extension_tests) add_cdt_unit_test(crypto_tests) +add_cdt_unit_test(crypto_ext_tests) add_cdt_unit_test(datastream_tests) add_cdt_unit_test(fixed_bytes_tests) add_cdt_unit_test(name_tests) diff --git a/tests/unit/crypto_ext_tests.cpp b/tests/unit/crypto_ext_tests.cpp new file mode 100644 index 0000000000..adf39dc0b2 --- /dev/null +++ b/tests/unit/crypto_ext_tests.cpp @@ -0,0 +1,96 @@ +/** + * @file + * @copyright defined in eosio.cdt/LICENSE.txt + */ + +#include +#include + +using namespace eosio::native; + +// Definitions in `eosio.cdt/libraries/eosio/crypto_ext.hpp` +EOSIO_TEST_BEGIN(point_view_test) + // ----------------------------------------------------- + // std::vector packed() const + std::vector x {'0', '1', '2', '3', '4', '5', '6', '7'}; + std::vector y {'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + std::vector expected {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + eosio::point_view point{x, y}; + + auto packed = point.packed(); + CHECK_EQUAL( expected, packed ); + + std::vector x1(8, '\0'); + std::vector y1(8, '\0'); + eosio::point_view point1{x1, y1}; + + point1.unpack(packed); + + std::vector unpack_x(point1.x, point1.x + point1.size); + std::vector unpack_y(point1.y, point1.y + point1.size); + CHECK_EQUAL( unpack_x, x ); + CHECK_EQUAL( unpack_y, y ); +EOSIO_TEST_END + +EOSIO_TEST_BEGIN(g1_view_test) + // ----------------------------------------------------- + // g1_view(std::vector x_, std::vector y_) + std::vector chars_1(1), chars_32(32), chars_33(33), chars_64(64), chars_65(65); + + CHECK_EQUAL( (eosio::g1_view{chars_32, chars_32}.size), 32 ); + + CHECK_ASSERT( "G1 coordinate size must be 32", ([&]() {eosio::g1_view{chars_1, chars_1};}) ); + CHECK_ASSERT( "G1 coordinate size must be 32", ([&]() {eosio::g1_view{chars_33, chars_33};}) ); + CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g1_view{chars_32, chars_33};}) ); + + // ----------------------------------------------------- + // g1_view(std::vector& p) + CHECK_EQUAL( (eosio::g1_view{chars_64}.size), 32 ); + + CHECK_ASSERT( "G1 serialized size must be 64", ([&]() {eosio::g1_view{chars_65};}) ); + CHECK_ASSERT( "G1 serialized size must be 64", ([&]() {eosio::g1_view{chars_32};}) ); +EOSIO_TEST_END + +EOSIO_TEST_BEGIN(g2_view_test) + // ----------------------------------------------------- + // g1_view(std::vector x_, std::vector y_) + std::vector chars_1(1), chars_64(64), chars_65(65), chars_128(128), chars_129(129); + + CHECK_EQUAL( (eosio::g2_view{chars_64, chars_64}.size), 64 ); + + CHECK_ASSERT( "G2 coordinate size must be 64", ([&]() {eosio::g2_view{chars_1, chars_1};}) ); + CHECK_ASSERT( "G2 coordinate size must be 64", ([&]() {eosio::g2_view{chars_65, chars_65};}) ); + CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g2_view{chars_64, chars_65};}) ); + + // ----------------------------------------------------- + // g2_view(std::vector& p) + CHECK_EQUAL( (eosio::g2_view{chars_128}.size), 64 ); + + CHECK_ASSERT( "G2 serialized size must be 128", ([&]() {eosio::g2_view{chars_129};}) ); + CHECK_ASSERT( "G2 serialized size must be 128", ([&]() {eosio::g2_view{chars_64};}) ); +EOSIO_TEST_END + +EOSIO_TEST_BEGIN(bigint_test) + // ----------------------------------------------------- + // bigint(std::vector& s) + std::vector chars_128(128), chars_256(256); + + CHECK_EQUAL( (eosio::bigint{chars_128}.size), 128 ); + CHECK_EQUAL( (eosio::bigint{chars_256}.size), 256 ); +EOSIO_TEST_END + +int main(int argc, char* argv[]) { + bool verbose = false; + if( argc >= 2 && std::strcmp( argv[1], "-v" ) == 0 ) { + verbose = true; + } + silence_output(!verbose); + + EOSIO_TEST(point_view_test) + EOSIO_TEST(g1_view_test) + EOSIO_TEST(g2_view_test) + EOSIO_TEST(bigint_test) + + return has_failed(); +} diff --git a/tests/unit/test_contracts/crypto_primitives_tests.cpp b/tests/unit/test_contracts/crypto_primitives_tests.cpp index 92d887f497..cd4d7fe3b9 100644 --- a/tests/unit/test_contracts/crypto_primitives_tests.cpp +++ b/tests/unit/test_contracts/crypto_primitives_tests.cpp @@ -24,4 +24,103 @@ class [[eosio::contract]] crypto_primitives_tests : public contract{ eosio::assert_keccak(val.c_str(), val.size(), sha3_dg); } + void addtest_helper(eosio::g1_view& p1, eosio::g1_view& p2, int32_t expected_rc, std::vector& expected_x, std::vector& expected_y) { + std::vector result_x(eosio::g1_coordinate_size); + std::vector result_y(eosio::g1_coordinate_size); + eosio::g1_view result {result_x, result_y}; + + auto rc = eosio::alt_bn128_add(p1, p2, result); + eosio::check(rc == expected_rc, "alt_bn128_add: return code not match"); + + std::vector rslt_x(result.x, result.x + result.size); + std::vector rslt_y(result.y, result.y + result.size); + eosio::check(rslt_x == expected_x, "alt_bn128_add: result x does not match"); + eosio::check(rslt_y == expected_y, "alt_bn128_add: result y does not match"); + } + + [[eosio::action]] + void addtest(std::vector& x1, std::vector& y1, std::vector& x2, std::vector& y2, int32_t expected_rc, std::vector& expected_x, std::vector& expected_y) { + eosio::g1_view point1 {x1, y1}; + eosio::g1_view point2 {x2, y2}; + + addtest_helper( point1, point2, expected_rc, expected_x, expected_y ); + } + + [[eosio::action]] + void addtest1(std::vector& p1, std::vector& p2, int32_t expected_rc, std::vector& expected_x, std::vector& expected_y) { + eosio::g1_view point1 {p1}; + eosio::g1_view point2 {p2}; + + addtest_helper( point1, point2, expected_rc, expected_x, expected_y ); + } + + [[eosio::action]] + void multest(std::vector& g1_x, std::vector& g1_y, std::vector& scalar, int32_t expected_rc, std::vector& expected_x, std::vector& expected_y) { + eosio::g1_view g1 {g1_x, g1_y}; + eosio::bigint s {scalar}; + std::vector result_x(eosio::g1_coordinate_size); + std::vector result_y(eosio::g1_coordinate_size); + eosio::g1_view result {result_x, result_y}; + + auto rc = eosio::alt_bn128_mul(g1, s, result); + eosio::check(rc == expected_rc, "alt_bn128_mul: return code not match"); + + std::vector rslt_x(result.x, result.x + result.size); + std::vector rslt_y(result.y, result.y + result.size); + eosio::check(rslt_x == expected_x, "alt_bn128_mul: Result x does not match"); + eosio::check(rslt_y == expected_y, "alt_bn128_mul: Result y does not match"); + } + + void pairtest_helper(eosio::g1_view& g1_a, eosio::g2_view& g2_a, eosio::g1_view& g1_b, eosio::g2_view& g2_b, int32_t expected) { + std::vector> pairs { {g1_a, g2_a}, {g1_b, g2_b} }; + + auto rc = eosio::alt_bn128_pair(pairs); + eosio::check(rc == expected, "alt_bn128_pair::return code not match"); + } + + [[eosio::action]] + void pairtest(std::vector& g1_a_x, std::vector& g1_a_y, std::vector& g2_a_x, std::vector& g2_a_y, std::vector& g1_b_x, std::vector& g1_b_y, std::vector& g2_b_x, std::vector& g2_b_y, int32_t expected) { + eosio::g1_view g1_a {g1_a_x, g1_a_y}; + eosio::g2_view g2_a {g2_a_x, g2_a_y}; + eosio::g1_view g1_b {g1_b_x, g1_b_y}; + eosio::g2_view g2_b {g2_b_x, g2_b_y}; + + pairtest_helper( g1_a, g2_a, g1_b, g2_b, expected ); + } + + [[eosio::action]] + void pairtest1(std::vector& g1a, std::vector& g2a, std::vector& g1b, std::vector& g2b, int32_t expected) { + eosio::g1_view g1_a { g1a }; + eosio::g2_view g2_a { g2a }; + eosio::g1_view g1_b { g1b }; + eosio::g2_view g2_b { g2b }; + + pairtest_helper( g1_a, g2_a, g1_b, g2_b, expected ); + } + + [[eosio::action]] + void modexptest(std::vector& base, std::vector& exp, std::vector& modulo, int32_t expected_rc, const std::vector& expected_result) { + eosio::bigint base_val {base}; + eosio::bigint exp_val {exp}; + eosio::bigint modulo_val {modulo}; + std::vector reslut_buf(modulo.size(), '\0'); + eosio::bigint result {reslut_buf}; + + auto rc = eosio::mod_exp(base_val, exp_val, modulo_val, result); + eosio::check(rc == expected_rc, "return code does not match"); + + std::vector actual_result(result.data, result.data + result.size); + eosio::check(actual_result == expected_result, "Result does not match"); + } + + [[eosio::action]] + void blake2ftest(uint32_t rounds, const std::vector& state, const std::vector& msg, const std::vector& t0_offset, const std::vector& t1_offset, bool final, int32_t expected_rc, const std::vector& expected_result) { + std::vector result(eosio::blake2f_result_size); + + auto rc = eosio::blake2_f(rounds, state, msg, t0_offset, t1_offset, final, result); + eosio::check(rc == expected_rc, "return code does not match"); + + std::vector actual_result(result.data(), result.data() + result.size()); + eosio::check(actual_result == expected_result, "Result does not match"); + } }; From 6c9f4d9533685bf8550942cb6a3206c9872ca3e3 Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Fri, 14 Oct 2022 16:29:36 -0400 Subject: [PATCH 2/6] add additional tests for modexp to emulate RSA usage --- tests/integration/crypto_tests.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/integration/crypto_tests.cpp b/tests/integration/crypto_tests.cpp index 5743f98c3b..77e1ecdaf0 100644 --- a/tests/integration/crypto_tests.cpp +++ b/tests/integration/crypto_tests.cpp @@ -207,6 +207,31 @@ BOOST_FIXTURE_TEST_CASE( modexp_tests, tester ) try { ("modulo", "0F") ("expected_rc", 0) ("expected_result", "01")); + + // 2048 bits. a^1 % a == 0 + push_action("eosio"_n, "modexptest"_n, "test"_n, mvo() + ("base", "a85c40266c0ba1f4d92cc6d8c8aa05bcf8c8daa112d620a3a9af9e04ed7729ccc4a53598203c1a74b0b8df82f34504f3fb06b426b37aa2830a3092b30bfdf770485c9b8a09ae4c2c894bf5089f7279b3bd2f512a50f4cf28014fba96f45d881caa474cc19e759d47d07cc16dbf8ccd8d837caae754baa91e8b52cf768c4cd8013cf575ff33faa7142fe9dabe63922dd035d74a90a5b2a31232357ac24892aaca9508aed4dd1341b7b10bd74dc2d23bf46efd511f98391f02589c98cbf64f794aecaf599c4862fb7da716fda1b6861f39fd77480a6d8f5a0472494bb4336ac77712fe00cba46ae627970e2075d4ced1c994372c4aad5af969004f859c4ab45579") + ("exp", "000001") + ("modulo", "a85c40266c0ba1f4d92cc6d8c8aa05bcf8c8daa112d620a3a9af9e04ed7729ccc4a53598203c1a74b0b8df82f34504f3fb06b426b37aa2830a3092b30bfdf770485c9b8a09ae4c2c894bf5089f7279b3bd2f512a50f4cf28014fba96f45d881caa474cc19e759d47d07cc16dbf8ccd8d837caae754baa91e8b52cf768c4cd8013cf575ff33faa7142fe9dabe63922dd035d74a90a5b2a31232357ac24892aaca9508aed4dd1341b7b10bd74dc2d23bf46efd511f98391f02589c98cbf64f794aecaf599c4862fb7da716fda1b6861f39fd77480a6d8f5a0472494bb4336ac77712fe00cba46ae627970e2075d4ced1c994372c4aad5af969004f859c4ab45579") + ("expected_rc", 0) + ("expected_result", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); + + // (a + 2) ^1 % a == 2 + push_action("eosio"_n, "modexptest"_n, "test"_n, mvo() + ("base", "a85c40266c0ba1f4d92cc6d8c8aa05bcf8c8daa112d620a3a9af9e04ed7729ccc4a53598203c1a74b0b8df82f34504f3fb06b426b37aa2830a3092b30bfdf770485c9b8a09ae4c2c894bf5089f7279b3bd2f512a50f4cf28014fba96f45d881caa474cc19e759d47d07cc16dbf8ccd8d837caae754baa91e8b52cf768c4cd8013cf575ff33faa7142fe9dabe63922dd035d74a90a5b2a31232357ac24892aaca9508aed4dd1341b7b10bd74dc2d23bf46efd511f98391f02589c98cbf64f794aecaf599c4862fb7da716fda1b6861f39fd77480a6d8f5a0472494bb4336ac77712fe00cba46ae627970e2075d4ced1c994372c4aad5af969004f859c4ab4557b") + ("exp", "000001") + ("modulo", "a85c40266c0ba1f4d92cc6d8c8aa05bcf8c8daa112d620a3a9af9e04ed7729ccc4a53598203c1a74b0b8df82f34504f3fb06b426b37aa2830a3092b30bfdf770485c9b8a09ae4c2c894bf5089f7279b3bd2f512a50f4cf28014fba96f45d881caa474cc19e759d47d07cc16dbf8ccd8d837caae754baa91e8b52cf768c4cd8013cf575ff33faa7142fe9dabe63922dd035d74a90a5b2a31232357ac24892aaca9508aed4dd1341b7b10bd74dc2d23bf46efd511f98391f02589c98cbf64f794aecaf599c4862fb7da716fda1b6861f39fd77480a6d8f5a0472494bb4336ac77712fe00cba46ae627970e2075d4ced1c994372c4aad5af969004f859c4ab45579") + ("expected_rc", 0) + ("expected_result", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002")); + + // random 2048 bits base + push_action("eosio"_n, "modexptest"_n, "test"_n, mvo() + ("base", "19c0417bb71793c2db5639403a4b5027e964f7abca64bf82fe972ccc8d966ebe22dfadaf55b336aa559647e30e672098421fa5b211613a36fd3b78e8c3e581eb4f300f8616a362ef7c626ac730ec717beec094d489d065f893a1e69ca3bb258a36ab7b6333e5704938dc9ea42821e245daf82b227938647cd5b5cff4cb22009bf2d3b7747e0567cc27e06830fff823a998bc8ffa4a51a9da409de2111d98be79be6c81c5dba9a9364add0b2fcaef332a38473018924ae8c2a7f91bdd29b58a4aa528af0e12876b01dc01dab671117c3f48cf4c73e990374bc29beb64f8e2c4f3d1e787938d2a0b4445293a8cd12c352ecb68dc673af88c6d39b2b58a8b490b52") + ("exp", "010001") // 65537 + ("modulo", "a85c40266c0ba1f4d92cc6d8c8aa05bcf8c8daa112d620a3a9af9e04ed7729ccc4a53598203c1a74b0b8df82f34504f3fb06b426b37aa2830a3092b30bfdf770485c9b8a09ae4c2c894bf5089f7279b3bd2f512a50f4cf28014fba96f45d881caa474cc19e759d47d07cc16dbf8ccd8d837caae754baa91e8b52cf768c4cd8013cf575ff33faa7142fe9dabe63922dd035d74a90a5b2a31232357ac24892aaca9508aed4dd1341b7b10bd74dc2d23bf46efd511f98391f02589c98cbf64f794aecaf599c4862fb7da716fda1b6861f39fd77480a6d8f5a0472494bb4336ac77712fe00cba46ae627970e2075d4ced1c994372c4aad5af969004f859c4ab45579") + ("expected_rc", 0) + ("expected_result", "2a3937a3ed06f7f517940f5bb43940d3357a36450bb31fe33bb1dd4fca31776b04046f6915c5b1677033da8d659834c442d4b636232ff206163ca8b0a0155e59db15c760b975a864a47b12c12f7eab6867dc824dab332b9b43a8fa19d8cfde278e839e0fbfe812d61987548d50d4044d29258db40cb68fdbdb9ec223f1bf30e632dbb9f46c7383f08d8f2bea7774f0a62f62609fa3b21f9f2455d0960555d625ee531289f6a06e2349c78cd8ef398d602b3882012ec6db95960fdc4da6b8d976950824a307f0b0a1fe028593113a0109d727b79b0ad461b894e77fd68c8f3bec1aa19dd686bbef4eb5d3482519baa8c7f22d73ed48bad9b88d76bde1af808129")); + } FC_LOG_AND_RETHROW() BOOST_FIXTURE_TEST_CASE( blake2f_tests, tester ) try { From 5d571bf343a713c69446eb25d71e03f0df895e8e Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Sat, 22 Oct 2022 18:56:39 -0400 Subject: [PATCH 3/6] use common tester class for crypto primitives tests --- tests/integration/crypto_tests.cpp | 98 ++++++------------------------ 1 file changed, 19 insertions(+), 79 deletions(-) diff --git a/tests/integration/crypto_tests.cpp b/tests/integration/crypto_tests.cpp index 77e1ecdaf0..7a97bde0c9 100644 --- a/tests/integration/crypto_tests.cpp +++ b/tests/integration/crypto_tests.cpp @@ -16,17 +16,21 @@ using namespace fc; using mvo = fc::mutable_variant_object; -BOOST_AUTO_TEST_SUITE(crypto_primitives_tests) +struct crypto_primitives_tester : tester { + crypto_primitives_tester() { + create_accounts( { "test"_n } ); + produce_block(); -BOOST_FIXTURE_TEST_CASE( sha3_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); + set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); + set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); + produce_blocks(); + } +}; - produce_blocks(); +BOOST_AUTO_TEST_SUITE(crypto_primitives_tests) +BOOST_FIXTURE_TEST_CASE( sha3_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "sha3test"_n, "test"_n, mvo() ("val", "hello") ("sha3_dg", "3338be694f50c5f338814986cdf0686453a888b84f424d792af4b9202398f392")); @@ -41,15 +45,7 @@ BOOST_FIXTURE_TEST_CASE( sha3_tests, tester ) try { } FC_LOG_AND_RETHROW() -BOOST_FIXTURE_TEST_CASE( keccak_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); - - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - - produce_blocks(); - +BOOST_FIXTURE_TEST_CASE( keccak_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "keccaktest"_n, "test"_n, mvo() ("val", "hello") ("sha3_dg", "1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8")); @@ -64,15 +60,7 @@ BOOST_FIXTURE_TEST_CASE( keccak_tests, tester ) try { } FC_LOG_AND_RETHROW() -BOOST_FIXTURE_TEST_CASE( bn128_add_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); - - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - - produce_blocks(); - +BOOST_FIXTURE_TEST_CASE( bn128_add_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "addtest"_n, "test"_n, mvo() ("x1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c09") ("y1", "2976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") @@ -95,15 +83,7 @@ BOOST_FIXTURE_TEST_CASE( bn128_add_tests, tester ) try { } FC_LOG_AND_RETHROW() // Test G1 constructed from a serialized point -BOOST_FIXTURE_TEST_CASE( bn128_add_serialized_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); - - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - - produce_blocks(); - +BOOST_FIXTURE_TEST_CASE( bn128_add_serialized_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "addtest1"_n, "test"_n, mvo() ("p1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c092976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") ("p2", "1bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f53322a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce4649844") @@ -121,15 +101,7 @@ BOOST_FIXTURE_TEST_CASE( bn128_add_serialized_tests, tester ) try { } FC_LOG_AND_RETHROW() -BOOST_FIXTURE_TEST_CASE( bn128_mul_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); - - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - - produce_blocks(); - +BOOST_FIXTURE_TEST_CASE( bn128_mul_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "multest"_n, "test"_n, mvo() ("g1_x", "007c43fcd125b2b13e2521e395a81727710a46b34fe279adbf1b94c72f7f9136") ("g1_y", "0db2f980370fb8962751c6ff064f4516a6a93d563388518bb77ab9a6b30755be") @@ -139,15 +111,7 @@ BOOST_FIXTURE_TEST_CASE( bn128_mul_tests, tester ) try { ("expected_y", "11c76319ebefc5379f7aa6d85d40169a612597637242a4bbb39e5cd3b844becd")); } FC_LOG_AND_RETHROW() -BOOST_FIXTURE_TEST_CASE( bn128_pair_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); - - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - - produce_blocks(); - +BOOST_FIXTURE_TEST_CASE( bn128_pair_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "pairtest"_n, "test"_n, mvo() ("g1_a_x", "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2") ("g1_a_y", "16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba") @@ -161,15 +125,7 @@ BOOST_FIXTURE_TEST_CASE( bn128_pair_tests, tester ) try { } FC_LOG_AND_RETHROW() // Test G1 and G2 constructed from serialized points -BOOST_FIXTURE_TEST_CASE( bn128_serialized_point_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); - - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - - produce_blocks(); - +BOOST_FIXTURE_TEST_CASE( bn128_serialized_point_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "pairtest1"_n, "test"_n, mvo() ("g1a", "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba") ("g2a", "2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590") @@ -178,15 +134,7 @@ BOOST_FIXTURE_TEST_CASE( bn128_serialized_point_tests, tester ) try { ("expected", 0)); } FC_LOG_AND_RETHROW() -BOOST_FIXTURE_TEST_CASE( modexp_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); - - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - - produce_blocks(); - +BOOST_FIXTURE_TEST_CASE( modexp_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "modexptest"_n, "test"_n, mvo() ("base", "03") ("exp", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e") @@ -234,15 +182,7 @@ BOOST_FIXTURE_TEST_CASE( modexp_tests, tester ) try { } FC_LOG_AND_RETHROW() -BOOST_FIXTURE_TEST_CASE( blake2f_tests, tester ) try { - create_accounts( { "test"_n } ); - produce_block(); - - set_code( "eosio"_n, contracts::crypto_primitives_test_wasm() ); - set_abi( "eosio"_n, contracts::crypto_primitives_test_abi().data() ); - - produce_blocks(); - +BOOST_FIXTURE_TEST_CASE( blake2f_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "blake2ftest"_n, "test"_n, mvo() ("rounds", 0) ("state", "48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b") From 3ca87ee3fc9f5acfc7f29d06611233aac5eaeb5b Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Sun, 23 Oct 2022 22:10:14 -0400 Subject: [PATCH 4/6] rename pack and unpack to avoid confusions --- libraries/eosiolib/core/eosio/crypto_ext.hpp | 31 ++++++++++---------- tests/unit/crypto_ext_tests.cpp | 16 +++++----- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/libraries/eosiolib/core/eosio/crypto_ext.hpp b/libraries/eosiolib/core/eosio/crypto_ext.hpp index 5823a650cf..feae0e2b92 100644 --- a/libraries/eosiolib/core/eosio/crypto_ext.hpp +++ b/libraries/eosiolib/core/eosio/crypto_ext.hpp @@ -101,23 +101,23 @@ namespace eosio { }; /** - * Returns packed x and y + * Return serialzed point containing only x and y */ - std::vector packed() const { + std::vector serialized() const { std::vector x_and_y( x, x + size ); x_and_y.insert( x_and_y.end(), y, y + size ); return x_and_y; } /** - * Unpacks a seralized point and populates current point + * Copy a serialized buffer to current point * - * @param packed - The source serialized point + * @param source - The source to be copied from */ - void unpack(const std::vector& packed) { - eosio::check( packed.size() == 2 * size, "size of packed point must be equal to x's size" ); - std::memcpy(x, packed.data(), size); - std::memcpy(y, packed.data() + size, size); + void copy_from(const std::vector& source) { + eosio::check( source.size() == 2 * size, "size of souce buffer must be size of x + y" ); + std::memcpy(x, source.data(), size); + std::memcpy(y, source.data() + size, size); } }; @@ -215,12 +215,13 @@ namespace eosio { * @return -1 if there is an error otherwise 0 */ inline int32_t alt_bn128_add( const g1_view& op1, const g1_view& op2, g1_view& result) { - auto op_1 = op1.packed(); - auto op_2 = op2.packed(); + auto op_1 = op1.serialized(); + auto op_2 = op2.serialized(); + std::vector rslt(2*result.size); // buffer storing x and y auto ret = internal_use_do_not_use::alt_bn128_add( op_1.data(), op_1.size(), op_2.data(), op_2.size(), rslt.data(), rslt.size()); if ( ret == 0 ) { - result.unpack(rslt); // unpack rslt into result + result.copy_from(rslt); // save rslt into result } return ret; } @@ -251,11 +252,11 @@ namespace eosio { * @return -1 if there is an error otherwise 0 */ inline int32_t alt_bn128_mul( const g1_view& g1, const bigint& scalar, g1_view& result) { - auto g1_bin = g1.packed(); + auto g1_bin = g1.serialized(); std::vector rslt(2*result.size); auto ret = internal_use_do_not_use::alt_bn128_mul( g1_bin.data(), g1_bin.size(), scalar.data, scalar.size, rslt.data(), rslt.size()); if ( ret == 0 ) { - result.unpack(rslt); + result.copy_from(rslt); } return ret; } @@ -286,8 +287,8 @@ namespace eosio { inline int32_t alt_bn128_pair( const std::vector>& pairs ) { std::vector g1_g2_pairs; for ( const auto& pair: pairs ) { - auto g1_bin = pair.first.packed(); - auto g2_bin = pair.second.packed(); + auto g1_bin = pair.first.serialized(); + auto g2_bin = pair.second.serialized(); g1_g2_pairs.insert( g1_g2_pairs.end(), g1_bin.begin(), g1_bin.end() ); g1_g2_pairs.insert( g1_g2_pairs.end(), g2_bin.begin(), g2_bin.end() ); } diff --git a/tests/unit/crypto_ext_tests.cpp b/tests/unit/crypto_ext_tests.cpp index adf39dc0b2..5ee0334a13 100644 --- a/tests/unit/crypto_ext_tests.cpp +++ b/tests/unit/crypto_ext_tests.cpp @@ -11,26 +11,26 @@ using namespace eosio::native; // Definitions in `eosio.cdt/libraries/eosio/crypto_ext.hpp` EOSIO_TEST_BEGIN(point_view_test) // ----------------------------------------------------- - // std::vector packed() const + // std::vector serialized() const std::vector x {'0', '1', '2', '3', '4', '5', '6', '7'}; std::vector y {'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; std::vector expected {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; eosio::point_view point{x, y}; - auto packed = point.packed(); - CHECK_EQUAL( expected, packed ); + auto serialized = point.serialized(); + CHECK_EQUAL( expected, serialized ); std::vector x1(8, '\0'); std::vector y1(8, '\0'); eosio::point_view point1{x1, y1}; - point1.unpack(packed); + point1.copy_from(serialized); - std::vector unpack_x(point1.x, point1.x + point1.size); - std::vector unpack_y(point1.y, point1.y + point1.size); - CHECK_EQUAL( unpack_x, x ); - CHECK_EQUAL( unpack_y, y ); + std::vector point1_x(point1.x, point1.x + point1.size); + std::vector point1_y(point1.y, point1.y + point1.size); + CHECK_EQUAL( point1_x, x ); + CHECK_EQUAL( point1_y, y ); EOSIO_TEST_END EOSIO_TEST_BEGIN(g1_view_test) From fdb19bd729f4f7eb86cfd456850ba9816726b5e9 Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Thu, 27 Oct 2022 22:12:12 -0400 Subject: [PATCH 5/6] add mutable and readonly point and point view to simplify APIs, incorporate other review comments --- libraries/eosiolib/core/eosio/crypto_ext.hpp | 180 ++++++++---------- tests/integration/crypto_tests.cpp | 29 +-- tests/unit/crypto_ext_tests.cpp | 82 ++++---- .../crypto_primitives_tests.cpp | 121 +++++++----- 4 files changed, 203 insertions(+), 209 deletions(-) diff --git a/libraries/eosiolib/core/eosio/crypto_ext.hpp b/libraries/eosiolib/core/eosio/crypto_ext.hpp index feae0e2b92..279520cadb 100644 --- a/libraries/eosiolib/core/eosio/crypto_ext.hpp +++ b/libraries/eosiolib/core/eosio/crypto_ext.hpp @@ -58,36 +58,33 @@ namespace eosio { */ /** - * Abstracts G1 and G2 points. Ensures sizes of x and y are valid + * Abstracts mutable G1 and G2 points * * @ingroup crypto */ - struct point_view { + template + struct ec_point { /** - * Pointer to the x coordinate + * Bytes of the x coordinate */ - char* x; + std::vector x; /** - * Pointer to the y coordinate + * Bytes of the y coordinate */ - char* y; - - /** - * Number of bytes in each of x and y - */ - uint32_t size; + std::vector y; /** * Construct a point given x and y * * @param x_ - The x coordinate, a vector of chars * @param y_ - The y coordinate, a vector of chars - */ - point_view(std::vector& x_, std::vector& y_) - :x(x_.data()), y(y_.data()), size(x_.size()) + */ + ec_point(std::vector& x_, std::vector& y_) + :x(x_), y(y_) { eosio::check( x_.size() == y_.size(), "x's size must be equal to y's" ); + eosio::check ( x_.size() == Size, "point size must match"); }; /** @@ -95,115 +92,92 @@ namespace eosio { * * @param p - The serialized point */ - point_view(std::vector& p) - :x(p.data()), y(p.data() + p.size()/2), size(p.size()/2) + ec_point(std::vector& p) + :x(p.data(), p.data() + p.size()/2), y(p.data() + p.size()/2, p.data() + p.size()) { + eosio::check ( p.size() == Size * 2, "point size must match"); }; /** * Return serialzed point containing only x and y */ std::vector serialized() const { - std::vector x_and_y( x, x + size ); - x_and_y.insert( x_and_y.end(), y, y + size ); + std::vector x_and_y( x ); + x_and_y.insert( x_and_y.end(), y.begin(), y.end() ); return x_and_y; } - - /** - * Copy a serialized buffer to current point - * - * @param source - The source to be copied from - */ - void copy_from(const std::vector& source) { - eosio::check( source.size() == 2 * size, "size of souce buffer must be size of x + y" ); - std::memcpy(x, source.data(), size); - std::memcpy(y, source.data() + size, size); - } }; - static constexpr size_t g1_coordinate_size = 32; - static constexpr size_t g2_coordinate_size = 64; - static constexpr size_t blake2f_result_size = 64; - /** - * Abstracts G1 point. Ensures sizes of x and y are 32 + * Abstracts read-only G1 and G2 points * * @ingroup crypto */ - struct g1_view : public point_view { + template + struct ec_point_view { /** - * Construct a G1 point given x and y - * - * @param x_ - The x coordinate, a vector of chars - * @param y_ - The y coordinate, a vector of chars + * Pointer to the x coordinate */ - g1_view(std::vector& x_, std::vector& y_) - : point_view(x_, y_) - { - eosio::check( size == g1_coordinate_size, "G1 coordinate size must be 32" ); - } + const char* x; /** - * Construct a point given a serialized point - * - * @param p - The serialized point + * Pointer to the y coordinate */ - g1_view(std::vector& p) - : point_view(p) - { - eosio::check( p.size() == g1_coordinate_size * 2, "G1 serialized size must be 64" ); - }; - }; + const char* y; - /** - * Abstracts G2 point. Ensures sizes of x and y are 64 - * - * @ingroup crypto - */ - struct g2_view : public point_view { /** - * Construct a G2 point given x and y + * Number of bytes in each of x and y + */ + uint32_t size; + + /** + * Construct a point given x and y * * @param x_ - The x coordinate, a vector of chars * @param y_ - The y coordinate, a vector of chars */ - g2_view(std::vector& x_, std::vector& y_) - : point_view(x_, y_) + ec_point_view(std::vector& x_, std::vector& y_) + :x(x_.data()), y(y_.data()), size(x_.size()) { - eosio::check( size == g2_coordinate_size, "G2 coordinate size must be 64" ); - } + eosio::check( x_.size() == y_.size(), "x's size must be equal to y's" ); + eosio::check ( size == Size, "point size must match"); + }; /** * Construct a point given a serialized point * * @param p - The serialized point */ - g2_view(std::vector& p) - : point_view(p) + ec_point_view(std::vector& p) + :x(p.data()), y(p.data() + p.size()/2), size(p.size()/2) { - eosio::check( p.size() == g2_coordinate_size * 2, "G2 serialized size must be 128" ); + eosio::check ( p.size() == Size * 2, "point size must match"); }; + + /** + * Return serialzed point containing only x and y + */ + std::vector serialized() const { + std::vector x_and_y( x, x + size ); + x_and_y.insert( x_and_y.end(), y, y + size ); + return x_and_y; + } }; + static constexpr size_t g1_coordinate_size = 32; + static constexpr size_t g2_coordinate_size = 64; + + using g1_point = ec_point; + using g2_point = ec_point; + using g1_point_view = ec_point_view; + using g2_point_view = ec_point_view; + /** - * Abstracts big integer. + * Big integer. * * @ingroup crypto */ - struct bigint { - /** - * Construct a bigint given a vector of chars (bytes) - * - * @param s - The source bytes - */ - bigint(std::vector& s) - :data(s.data()), size(s.size()) - { - }; - - char* data; - uint32_t size; - }; + using bigint = std::vector; /** * Addition operation on the elliptic curve `alt_bn128` @@ -211,19 +185,16 @@ namespace eosio { * @ingroup crypto * @param op1 - operand 1 * @param op2 - operand 2 - * @param result - result of the addition operation - * @return -1 if there is an error otherwise 0 + * @return result of the addition operation; throw if error */ - inline int32_t alt_bn128_add( const g1_view& op1, const g1_view& op2, g1_view& result) { + template + inline g1_point alt_bn128_add( const T& op1, const T& op2 ) { auto op_1 = op1.serialized(); auto op_2 = op2.serialized(); - - std::vector rslt(2*result.size); // buffer storing x and y - auto ret = internal_use_do_not_use::alt_bn128_add( op_1.data(), op_1.size(), op_2.data(), op_2.size(), rslt.data(), rslt.size()); - if ( ret == 0 ) { - result.copy_from(rslt); // save rslt into result - } - return ret; + std::vector buf ( 2 * g1_coordinate_size ); // buffer storing x and y + auto ret = internal_use_do_not_use::alt_bn128_add( op_1.data(), op_1.size(), op_2.data(), op_2.size(), buf.data(), buf.size()); + eosio::check ( ret == 0, "internal_use_do_not_use::alt_bn128_add failed" ); + return g1_point { buf }; } /** @@ -248,17 +219,15 @@ namespace eosio { * @ingroup crypto * @param g1 - G1 point * @param scalar - scalar factor - * @param result - result of the scalar multiplication operation - * @return -1 if there is an error otherwise 0 + * @return result of the scalar multiplication operation; throw if error */ - inline int32_t alt_bn128_mul( const g1_view& g1, const bigint& scalar, g1_view& result) { + template + inline g1_point alt_bn128_mul( const T& g1, const bigint& scalar) { auto g1_bin = g1.serialized(); - std::vector rslt(2*result.size); - auto ret = internal_use_do_not_use::alt_bn128_mul( g1_bin.data(), g1_bin.size(), scalar.data, scalar.size, rslt.data(), rslt.size()); - if ( ret == 0 ) { - result.copy_from(rslt); - } - return ret; + std::vector buf( 2 * g1_coordinate_size ); // buffer storing x and y + auto ret = internal_use_do_not_use::alt_bn128_mul( g1_bin.data(), g1_bin.size(), scalar.data(), scalar.size(), buf.data(), buf.size()); + eosio::check ( ret == 0, "internal_use_do_not_use::alt_bn128_mul failed"); + return g1_point { buf }; } /** @@ -284,7 +253,8 @@ namespace eosio { * @param pairs - g1 and g2 pairs * @return -1 if there is an error, 1 if false and 0 if true and successful */ - inline int32_t alt_bn128_pair( const std::vector>& pairs ) { + template + inline int32_t alt_bn128_pair( const std::vector>& pairs ) { std::vector g1_g2_pairs; for ( const auto& pair: pairs ) { auto g1_bin = pair.first.serialized(); @@ -320,8 +290,8 @@ namespace eosio { */ inline int32_t mod_exp( const bigint& base, const bigint& exp, const bigint& mod, bigint& result) { - eosio::check( result.size >= mod.size, "mod_exp result parameter's size must be >= mod's size" ); - auto ret = internal_use_do_not_use::mod_exp( base.data, base.size, exp.data, exp.size, mod.data, mod.size, result.data, result.size); + eosio::check( result.size() >= mod.size(), "mod_exp result parameter's size must be >= mod's size" ); + auto ret = internal_use_do_not_use::mod_exp( base.data(), base.size(), exp.data(), exp.size(), mod.data(), mod.size(), result.data(), result.size()); return ret; } @@ -345,6 +315,8 @@ namespace eosio { return internal_use_do_not_use::mod_exp( base, base_len, exp, exp_len, mod, mod_len, result, result_len); } + static constexpr size_t blake2f_result_size = 64; + /** * BLAKE2 compression function "F" * https://eips.ethereum.org/EIPS/eip-152 diff --git a/tests/integration/crypto_tests.cpp b/tests/integration/crypto_tests.cpp index 7a97bde0c9..93ba59b975 100644 --- a/tests/integration/crypto_tests.cpp +++ b/tests/integration/crypto_tests.cpp @@ -60,44 +60,43 @@ BOOST_FIXTURE_TEST_CASE( keccak_tests, crypto_primitives_tester ) try { } FC_LOG_AND_RETHROW() +// test add where points are constructed from x and y BOOST_FIXTURE_TEST_CASE( bn128_add_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "addtest"_n, "test"_n, mvo() ("x1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c09") ("y1", "2976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") ("x2", "1bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f5332") ("y2", "2a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce4649844") - ("expected_rc", 0) ("expected_x", "16c7c4042e3a725ddbacf197c519c3dcad2bc87dfd9ac7e1e1631154ee0b7d9c") ("expected_y", "19cd640dd28c9811ebaaa095a16b16190d08d6906c4f926fce581985fe35be0e")); - // P1 not on curve - push_action("eosio"_n, "addtest"_n, "test"_n, mvo() + // P1 not on curve, will throw + BOOST_CHECK_THROW(push_action("eosio"_n, "addtest"_n, "test"_n, mvo() ("x1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c09") ("y1", "2976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") ("x2", "2a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce4649844") ("y2", "1bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f5332") - ("expected_rc", -1) ("expected_x", "0000000000000000000000000000000000000000000000000000000000000000") - ("expected_y", "0000000000000000000000000000000000000000000000000000000000000000")); + ("expected_y", "0000000000000000000000000000000000000000000000000000000000000000")), + eosio_assert_message_exception); } FC_LOG_AND_RETHROW() -// Test G1 constructed from a serialized point +// test add where points are constructed from other points BOOST_FIXTURE_TEST_CASE( bn128_add_serialized_tests, crypto_primitives_tester ) try { push_action("eosio"_n, "addtest1"_n, "test"_n, mvo() ("p1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c092976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") ("p2", "1bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f53322a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce4649844") - ("expected_rc", 0) ("expected_x", "16c7c4042e3a725ddbacf197c519c3dcad2bc87dfd9ac7e1e1631154ee0b7d9c") ("expected_y", "19cd640dd28c9811ebaaa095a16b16190d08d6906c4f926fce581985fe35be0e")); // P1 not on curve - push_action("eosio"_n, "addtest1"_n, "test"_n, mvo() + BOOST_CHECK_THROW(push_action("eosio"_n, "addtest1"_n, "test"_n, mvo() ("p1", "222480c9f95409bfa4ac6ae890b9c150bc88542b87b352e92950c340458b0c092976efd698cf23b414ea622b3f720dd9080d679042482ff3668cb2e32cad8ae2") ("p2", "2a53edf6b48bcf5cb1c0b4ad1d36dfce06a79dcd6526f1c386a14d8ce46498441bd20beca3d8d28e536d2b5bd3bf36d76af68af5e6c96ca6e5519ba9ff8f5332") - ("expected_rc", -1) ("expected_x", "0000000000000000000000000000000000000000000000000000000000000000") - ("expected_y", "0000000000000000000000000000000000000000000000000000000000000000")); + ("expected_y", "0000000000000000000000000000000000000000000000000000000000000000")), + eosio_assert_message_exception); } FC_LOG_AND_RETHROW() @@ -106,9 +105,17 @@ BOOST_FIXTURE_TEST_CASE( bn128_mul_tests, crypto_primitives_tester ) try { ("g1_x", "007c43fcd125b2b13e2521e395a81727710a46b34fe279adbf1b94c72f7f9136") ("g1_y", "0db2f980370fb8962751c6ff064f4516a6a93d563388518bb77ab9a6b30755be") ("scalar", "0312ed43559cf8ecbab5221256a56e567aac5035308e3f1d54954d8b97cd1c9b") - ("expected_rc", 0) ("expected_x", "2d66cdeca5e1715896a5a924c50a149be87ddd2347b862150fbb0fd7d0b1833c") ("expected_y", "11c76319ebefc5379f7aa6d85d40169a612597637242a4bbb39e5cd3b844becd")); + + // scalar size < 256 bits, will throw + BOOST_CHECK_THROW(push_action("eosio"_n, "multest"_n, "test"_n, mvo() + ("g1_x", "007c43fcd125b2b13e2521e395a81727710a46b34fe279adbf1b94c72f7f9136") + ("g1_y", "0db2f980370fb8962751c6ff064f4516a6a93d563388518bb77ab9a6b30755be") + ("scalar", "03") + ("expected_x", "00") + ("expected_y", "00")), + eosio_assert_message_exception); } FC_LOG_AND_RETHROW() BOOST_FIXTURE_TEST_CASE( bn128_pair_tests, crypto_primitives_tester ) try { diff --git a/tests/unit/crypto_ext_tests.cpp b/tests/unit/crypto_ext_tests.cpp index 5ee0334a13..a31a143545 100644 --- a/tests/unit/crypto_ext_tests.cpp +++ b/tests/unit/crypto_ext_tests.cpp @@ -11,64 +11,58 @@ using namespace eosio::native; // Definitions in `eosio.cdt/libraries/eosio/crypto_ext.hpp` EOSIO_TEST_BEGIN(point_view_test) // ----------------------------------------------------- - // std::vector serialized() const - std::vector x {'0', '1', '2', '3', '4', '5', '6', '7'}; - std::vector y {'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - std::vector expected {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - - eosio::point_view point{x, y}; - - auto serialized = point.serialized(); - CHECK_EQUAL( expected, serialized ); - - std::vector x1(8, '\0'); - std::vector y1(8, '\0'); - eosio::point_view point1{x1, y1}; - - point1.copy_from(serialized); - - std::vector point1_x(point1.x, point1.x + point1.size); - std::vector point1_y(point1.y, point1.y + point1.size); - CHECK_EQUAL( point1_x, x ); - CHECK_EQUAL( point1_y, y ); + std::string x_str = "0123456789abcdeffedcba9876543210"; + std::string y_str = "fedcba98765432100123456789abcdef"; + std::string serialized_str = "0123456789abcdeffedcba9876543210fedcba98765432100123456789abcdef"; + std::vector x( x_str.begin(), x_str.end() ); + std::vector y( y_str.begin(), y_str.end() ); + std::vector serialized( serialized_str.begin(), serialized_str.end() ); + + eosio::ec_point point{x, y}; + auto point_serialized = point.serialized(); + CHECK_EQUAL( serialized, point_serialized ); + + eosio::ec_point_view view{x, y}; + auto view_serialized = view.serialized(); + CHECK_EQUAL( serialized, view_serialized ); EOSIO_TEST_END -EOSIO_TEST_BEGIN(g1_view_test) +EOSIO_TEST_BEGIN(g1_point_view_test) // ----------------------------------------------------- - // g1_view(std::vector x_, std::vector y_) + // g1_point_view(std::vector x_, std::vector y_) std::vector chars_1(1), chars_32(32), chars_33(33), chars_64(64), chars_65(65); - CHECK_EQUAL( (eosio::g1_view{chars_32, chars_32}.size), 32 ); + CHECK_EQUAL( (eosio::g1_point_view{chars_32, chars_32}.size), 32 ); - CHECK_ASSERT( "G1 coordinate size must be 32", ([&]() {eosio::g1_view{chars_1, chars_1};}) ); - CHECK_ASSERT( "G1 coordinate size must be 32", ([&]() {eosio::g1_view{chars_33, chars_33};}) ); - CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g1_view{chars_32, chars_33};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_1, chars_1};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_33, chars_33};}) ); + CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g1_point_view{chars_32, chars_33};}) ); // ----------------------------------------------------- - // g1_view(std::vector& p) - CHECK_EQUAL( (eosio::g1_view{chars_64}.size), 32 ); + // g1_point_view(std::vector& p) + CHECK_EQUAL( (eosio::g1_point_view{chars_64}.size), 32 ); - CHECK_ASSERT( "G1 serialized size must be 64", ([&]() {eosio::g1_view{chars_65};}) ); - CHECK_ASSERT( "G1 serialized size must be 64", ([&]() {eosio::g1_view{chars_32};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_65};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_32};}) ); EOSIO_TEST_END -EOSIO_TEST_BEGIN(g2_view_test) +EOSIO_TEST_BEGIN(g2_point_view_test) // ----------------------------------------------------- - // g1_view(std::vector x_, std::vector y_) + // g1_point_view(std::vector x_, std::vector y_) std::vector chars_1(1), chars_64(64), chars_65(65), chars_128(128), chars_129(129); - CHECK_EQUAL( (eosio::g2_view{chars_64, chars_64}.size), 64 ); + CHECK_EQUAL( (eosio::g2_point_view{chars_64, chars_64}.size), 64 ); - CHECK_ASSERT( "G2 coordinate size must be 64", ([&]() {eosio::g2_view{chars_1, chars_1};}) ); - CHECK_ASSERT( "G2 coordinate size must be 64", ([&]() {eosio::g2_view{chars_65, chars_65};}) ); - CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g2_view{chars_64, chars_65};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_1, chars_1};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_65, chars_65};}) ); + CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g2_point_view{chars_64, chars_65};}) ); // ----------------------------------------------------- - // g2_view(std::vector& p) - CHECK_EQUAL( (eosio::g2_view{chars_128}.size), 64 ); + // g2_point_view(std::vector& p) + CHECK_EQUAL( (eosio::g2_point_view{chars_128}.size), 64 ); - CHECK_ASSERT( "G2 serialized size must be 128", ([&]() {eosio::g2_view{chars_129};}) ); - CHECK_ASSERT( "G2 serialized size must be 128", ([&]() {eosio::g2_view{chars_64};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_129};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_64};}) ); EOSIO_TEST_END EOSIO_TEST_BEGIN(bigint_test) @@ -76,8 +70,8 @@ EOSIO_TEST_BEGIN(bigint_test) // bigint(std::vector& s) std::vector chars_128(128), chars_256(256); - CHECK_EQUAL( (eosio::bigint{chars_128}.size), 128 ); - CHECK_EQUAL( (eosio::bigint{chars_256}.size), 256 ); + CHECK_EQUAL( (eosio::bigint{chars_128}.size()), 128 ); + CHECK_EQUAL( (eosio::bigint{chars_256}.size()), 256 ); EOSIO_TEST_END int main(int argc, char* argv[]) { @@ -88,8 +82,8 @@ int main(int argc, char* argv[]) { silence_output(!verbose); EOSIO_TEST(point_view_test) - EOSIO_TEST(g1_view_test) - EOSIO_TEST(g2_view_test) + EOSIO_TEST(g1_point_view_test) + EOSIO_TEST(g2_point_view_test) EOSIO_TEST(bigint_test) return has_failed(); diff --git a/tests/unit/test_contracts/crypto_primitives_tests.cpp b/tests/unit/test_contracts/crypto_primitives_tests.cpp index cd4d7fe3b9..3c0e5b5457 100644 --- a/tests/unit/test_contracts/crypto_primitives_tests.cpp +++ b/tests/unit/test_contracts/crypto_primitives_tests.cpp @@ -24,78 +24,102 @@ class [[eosio::contract]] crypto_primitives_tests : public contract{ eosio::assert_keccak(val.c_str(), val.size(), sha3_dg); } - void addtest_helper(eosio::g1_view& p1, eosio::g1_view& p2, int32_t expected_rc, std::vector& expected_x, std::vector& expected_y) { - std::vector result_x(eosio::g1_coordinate_size); - std::vector result_y(eosio::g1_coordinate_size); - eosio::g1_view result {result_x, result_y}; - - auto rc = eosio::alt_bn128_add(p1, p2, result); - eosio::check(rc == expected_rc, "alt_bn128_add: return code not match"); - - std::vector rslt_x(result.x, result.x + result.size); - std::vector rslt_y(result.y, result.y + result.size); - eosio::check(rslt_x == expected_x, "alt_bn128_add: result x does not match"); - eosio::check(rslt_y == expected_y, "alt_bn128_add: result y does not match"); + template + void addtest_helper(T& p1, T& p2, std::vector& expected_x, std::vector& expected_y) { + auto result = eosio::alt_bn128_add(p1, p2); + eosio::check(result.x == expected_x, "alt_bn128_add: result x does not match"); + eosio::check(result.y == expected_y, "alt_bn128_add: result y does not match"); } + // test add where points are constructed from x and y [[eosio::action]] - void addtest(std::vector& x1, std::vector& y1, std::vector& x2, std::vector& y2, int32_t expected_rc, std::vector& expected_x, std::vector& expected_y) { - eosio::g1_view point1 {x1, y1}; - eosio::g1_view point2 {x2, y2}; - - addtest_helper( point1, point2, expected_rc, expected_x, expected_y ); + void addtest(std::vector& x1, std::vector& y1, std::vector& x2, std::vector& y2, std::vector& expected_x, std::vector& expected_y) { + // point + eosio::g1_point point1 {x1, y1}; + eosio::g1_point point2 {x2, y2}; + addtest_helper( point1, point2, expected_x, expected_y ); + + // view + eosio::g1_point_view point_view1 {x1, y1}; + eosio::g1_point_view point_view2 {x2, y2}; + addtest_helper( point_view1, point_view2, expected_x, expected_y ); } + // test add where points are constructed from other points [[eosio::action]] - void addtest1(std::vector& p1, std::vector& p2, int32_t expected_rc, std::vector& expected_x, std::vector& expected_y) { - eosio::g1_view point1 {p1}; - eosio::g1_view point2 {p2}; + void addtest1(std::vector& p1, std::vector& p2, std::vector& expected_x, std::vector& expected_y) { + // point + eosio::g1_point point1 {p1}; + eosio::g1_point point2 {p2}; + addtest_helper( point1, point2, expected_x, expected_y ); + + // view + eosio::g1_point_view point_view1 {p1}; + eosio::g1_point_view point_view2 {p2}; + addtest_helper( point_view1, point_view2, expected_x, expected_y ); + } - addtest_helper( point1, point2, expected_rc, expected_x, expected_y ); + template + void multest_helper(T& g1, eosio::bigint& s, std::vector& expected_x, std::vector& expected_y) { + auto result = eosio::alt_bn128_mul(g1, s); + eosio::check(result.x == expected_x, "alt_bn128_mul: Result x does not match"); + eosio::check(result.y == expected_y, "alt_bn128_mul: Result y does not match"); } [[eosio::action]] - void multest(std::vector& g1_x, std::vector& g1_y, std::vector& scalar, int32_t expected_rc, std::vector& expected_x, std::vector& expected_y) { - eosio::g1_view g1 {g1_x, g1_y}; + void multest(std::vector& g1_x, std::vector& g1_y, std::vector& scalar, std::vector& expected_x, std::vector& expected_y) { eosio::bigint s {scalar}; - std::vector result_x(eosio::g1_coordinate_size); - std::vector result_y(eosio::g1_coordinate_size); - eosio::g1_view result {result_x, result_y}; - auto rc = eosio::alt_bn128_mul(g1, s, result); - eosio::check(rc == expected_rc, "alt_bn128_mul: return code not match"); + // point + eosio::g1_point g1_point {g1_x, g1_y}; + multest_helper(g1_point, s, expected_x, expected_y); - std::vector rslt_x(result.x, result.x + result.size); - std::vector rslt_y(result.y, result.y + result.size); - eosio::check(rslt_x == expected_x, "alt_bn128_mul: Result x does not match"); - eosio::check(rslt_y == expected_y, "alt_bn128_mul: Result y does not match"); + // view + eosio::g1_point_view g1_view {g1_x, g1_y}; + multest_helper(g1_view, s, expected_x, expected_y); } - void pairtest_helper(eosio::g1_view& g1_a, eosio::g2_view& g2_a, eosio::g1_view& g1_b, eosio::g2_view& g2_b, int32_t expected) { - std::vector> pairs { {g1_a, g2_a}, {g1_b, g2_b} }; - + template + void pairtest_helper(G1_T& g1_a, G2_T& g2_a, G1_T& g1_b, G2_T& g2_b, int32_t expected) { + std::vector> pairs { {g1_a, g2_a}, {g1_b, g2_b} }; auto rc = eosio::alt_bn128_pair(pairs); eosio::check(rc == expected, "alt_bn128_pair::return code not match"); } + // test pairtest where points are constructed from x and y [[eosio::action]] void pairtest(std::vector& g1_a_x, std::vector& g1_a_y, std::vector& g2_a_x, std::vector& g2_a_y, std::vector& g1_b_x, std::vector& g1_b_y, std::vector& g2_b_x, std::vector& g2_b_y, int32_t expected) { - eosio::g1_view g1_a {g1_a_x, g1_a_y}; - eosio::g2_view g2_a {g2_a_x, g2_a_y}; - eosio::g1_view g1_b {g1_b_x, g1_b_y}; - eosio::g2_view g2_b {g2_b_x, g2_b_y}; - + // point + eosio::g1_point g1_a {g1_a_x, g1_a_y}; + eosio::g2_point g2_a {g2_a_x, g2_a_y}; + eosio::g1_point g1_b {g1_b_x, g1_b_y}; + eosio::g2_point g2_b {g2_b_x, g2_b_y}; pairtest_helper( g1_a, g2_a, g1_b, g2_b, expected ); + + // view + eosio::g1_point_view g1_view_a {g1_a_x, g1_a_y}; + eosio::g2_point_view g2_view_a {g2_a_x, g2_a_y}; + eosio::g1_point_view g1_view_b {g1_b_x, g1_b_y}; + eosio::g2_point_view g2_view_b {g2_b_x, g2_b_y}; + pairtest_helper( g1_view_a, g2_view_a, g1_view_b, g2_view_b, expected ); } + // test pairtest where points are constructed from other points [[eosio::action]] void pairtest1(std::vector& g1a, std::vector& g2a, std::vector& g1b, std::vector& g2b, int32_t expected) { - eosio::g1_view g1_a { g1a }; - eosio::g2_view g2_a { g2a }; - eosio::g1_view g1_b { g1b }; - eosio::g2_view g2_b { g2b }; - + // point + eosio::g1_point g1_a { g1a }; + eosio::g2_point g2_a { g2a }; + eosio::g1_point g1_b { g1b }; + eosio::g2_point g2_b { g2b }; pairtest_helper( g1_a, g2_a, g1_b, g2_b, expected ); + + // view + eosio::g1_point_view g1_view_a { g1a }; + eosio::g2_point_view g2_view_a { g2a }; + eosio::g1_point_view g1_view_b { g1b }; + eosio::g2_point_view g2_view_b { g2b }; + pairtest_helper( g1_view_a, g2_view_a, g1_view_b, g2_view_b, expected ); } [[eosio::action]] @@ -103,14 +127,11 @@ class [[eosio::contract]] crypto_primitives_tests : public contract{ eosio::bigint base_val {base}; eosio::bigint exp_val {exp}; eosio::bigint modulo_val {modulo}; - std::vector reslut_buf(modulo.size(), '\0'); - eosio::bigint result {reslut_buf}; + eosio::bigint result( modulo.size(), '\0' ); auto rc = eosio::mod_exp(base_val, exp_val, modulo_val, result); eosio::check(rc == expected_rc, "return code does not match"); - - std::vector actual_result(result.data, result.data + result.size); - eosio::check(actual_result == expected_result, "Result does not match"); + eosio::check(result == expected_result, "Result does not match"); } [[eosio::action]] From d3d97168c906ea77d9bc6c95b82c373b9a6e12c6 Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Tue, 1 Nov 2022 22:57:18 -0400 Subject: [PATCH 6/6] add an ec_point_view constructor taking ec_point as an input; change an existing ec_point_view constructor to take char* as an input --- libraries/eosiolib/core/eosio/crypto_ext.hpp | 32 ++++++---- tests/unit/crypto_ext_tests.cpp | 60 +++++++++++-------- .../crypto_primitives_tests.cpp | 31 +++++++--- 3 files changed, 80 insertions(+), 43 deletions(-) diff --git a/libraries/eosiolib/core/eosio/crypto_ext.hpp b/libraries/eosiolib/core/eosio/crypto_ext.hpp index 279520cadb..a787819060 100644 --- a/libraries/eosiolib/core/eosio/crypto_ext.hpp +++ b/libraries/eosiolib/core/eosio/crypto_ext.hpp @@ -93,7 +93,7 @@ namespace eosio { * @param p - The serialized point */ ec_point(std::vector& p) - :x(p.data(), p.data() + p.size()/2), y(p.data() + p.size()/2, p.data() + p.size()) + :x(p.data(), p.data() + Size), y(p.data() + Size, p.data() + p.size()) { eosio::check ( p.size() == Size * 2, "point size must match"); }; @@ -131,29 +131,41 @@ namespace eosio { uint32_t size; /** - * Construct a point given x and y + * Construct a point view from x and y * - * @param x_ - The x coordinate, a vector of chars - * @param y_ - The y coordinate, a vector of chars + * @param x_ - The x coordinate, poiter to chars + * @param x_size - x's size + * @param y_ - The y coordinate, poiter to chars + * @param y_size - y's size */ - ec_point_view(std::vector& x_, std::vector& y_) - :x(x_.data()), y(y_.data()), size(x_.size()) + ec_point_view(const char* x_, uint32_t x_size, const char* y_, uint32_t y_size) + :x(x_), y(y_), size(x_size) { - eosio::check( x_.size() == y_.size(), "x's size must be equal to y's" ); + eosio::check ( x_size == y_size, "x's size must be equal to y's"); eosio::check ( size == Size, "point size must match"); }; /** - * Construct a point given a serialized point + * Construct a point view from a serialized point * * @param p - The serialized point */ - ec_point_view(std::vector& p) - :x(p.data()), y(p.data() + p.size()/2), size(p.size()/2) + ec_point_view(const std::vector& p) + :x(p.data()), y(p.data() + Size), size(Size) { eosio::check ( p.size() == Size * 2, "point size must match"); }; + /** + * Construct a point view from a point + * + * @param p - The point + */ + ec_point_view(const ec_point& p) + :x(p.x.data()), y(p.y.data()), size(Size) + { + }; + /** * Return serialzed point containing only x and y */ diff --git a/tests/unit/crypto_ext_tests.cpp b/tests/unit/crypto_ext_tests.cpp index a31a143545..f700366290 100644 --- a/tests/unit/crypto_ext_tests.cpp +++ b/tests/unit/crypto_ext_tests.cpp @@ -9,8 +9,7 @@ using namespace eosio::native; // Definitions in `eosio.cdt/libraries/eosio/crypto_ext.hpp` -EOSIO_TEST_BEGIN(point_view_test) - // ----------------------------------------------------- +EOSIO_TEST_BEGIN(ec_point_test) std::string x_str = "0123456789abcdeffedcba9876543210"; std::string y_str = "fedcba98765432100123456789abcdef"; std::string serialized_str = "0123456789abcdeffedcba9876543210fedcba98765432100123456789abcdef"; @@ -22,43 +21,54 @@ EOSIO_TEST_BEGIN(point_view_test) auto point_serialized = point.serialized(); CHECK_EQUAL( serialized, point_serialized ); - eosio::ec_point_view view{x, y}; + eosio::ec_point point_from_serialized {point_serialized}; + CHECK_EQUAL( point_from_serialized.serialized(), point_serialized); + + eosio::ec_point_view view{x.data(), static_cast(x.size()), y.data(), static_cast(y.size())}; auto view_serialized = view.serialized(); CHECK_EQUAL( serialized, view_serialized ); + + eosio::ec_point_view view1{ view_serialized }; + CHECK_EQUAL( view1.serialized(), view_serialized ); + + eosio::ec_point_view view2{ point }; + CHECK_EQUAL( view2.serialized(), serialized ); EOSIO_TEST_END -EOSIO_TEST_BEGIN(g1_point_view_test) - // ----------------------------------------------------- - // g1_point_view(std::vector x_, std::vector y_) +EOSIO_TEST_BEGIN(g1_point_test) std::vector chars_1(1), chars_32(32), chars_33(33), chars_64(64), chars_65(65); - CHECK_EQUAL( (eosio::g1_point_view{chars_32, chars_32}.size), 32 ); + CHECK_EQUAL( (eosio::g1_point{chars_32, chars_32}.serialized().size()), 64 ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point{chars_1, chars_1};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point{chars_33, chars_33};}) ); + CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g1_point{chars_32, chars_33};}) ); - CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_1, chars_1};}) ); - CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_33, chars_33};}) ); - CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g1_point_view{chars_32, chars_33};}) ); + CHECK_EQUAL( (eosio::g1_point_view{chars_32.data(), static_cast(chars_32.size()), chars_32.data(), static_cast(chars_32.size())}.size), 32 ); + + CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_1.data(), static_cast(chars_1.size()), chars_1.data(), static_cast(chars_1.size())};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_33.data(), static_cast(chars_33.size()), chars_33.data(), static_cast(chars_33.size())};}) ); + CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g1_point_view{chars_32.data(), static_cast(chars_32.size()), chars_33.data(), static_cast(chars_33.size())};}) ); - // ----------------------------------------------------- - // g1_point_view(std::vector& p) CHECK_EQUAL( (eosio::g1_point_view{chars_64}.size), 32 ); CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_65};}) ); CHECK_ASSERT( "point size must match", ([&]() {eosio::g1_point_view{chars_32};}) ); EOSIO_TEST_END -EOSIO_TEST_BEGIN(g2_point_view_test) - // ----------------------------------------------------- - // g1_point_view(std::vector x_, std::vector y_) +EOSIO_TEST_BEGIN(g2_point_test) std::vector chars_1(1), chars_64(64), chars_65(65), chars_128(128), chars_129(129); - CHECK_EQUAL( (eosio::g2_point_view{chars_64, chars_64}.size), 64 ); + CHECK_EQUAL( (eosio::g2_point{chars_64, chars_64}.serialized().size()), 128 ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point{chars_1, chars_1};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point{chars_65, chars_65};}) ); + CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g2_point{chars_64, chars_65};}) ); + + CHECK_EQUAL( (eosio::g2_point_view{chars_64.data(), static_cast(chars_64.size()), chars_64.data(), static_cast(chars_64.size())}.size), 64 ); - CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_1, chars_1};}) ); - CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_65, chars_65};}) ); - CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g2_point_view{chars_64, chars_65};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_1.data(), static_cast(chars_1.size()), chars_1.data(), static_cast(chars_1.size())};}) ); + CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_65.data(), static_cast(chars_65.size()), chars_65.data(), static_cast(chars_65.size())};}) ); + CHECK_ASSERT( "x's size must be equal to y's", ([&]() {eosio::g2_point_view{chars_64.data(), static_cast(chars_64.size()), chars_65.data(), static_cast(chars_65.size())};}) ); - // ----------------------------------------------------- - // g2_point_view(std::vector& p) CHECK_EQUAL( (eosio::g2_point_view{chars_128}.size), 64 ); CHECK_ASSERT( "point size must match", ([&]() {eosio::g2_point_view{chars_129};}) ); @@ -66,8 +76,6 @@ EOSIO_TEST_BEGIN(g2_point_view_test) EOSIO_TEST_END EOSIO_TEST_BEGIN(bigint_test) - // ----------------------------------------------------- - // bigint(std::vector& s) std::vector chars_128(128), chars_256(256); CHECK_EQUAL( (eosio::bigint{chars_128}.size()), 128 ); @@ -81,9 +89,9 @@ int main(int argc, char* argv[]) { } silence_output(!verbose); - EOSIO_TEST(point_view_test) - EOSIO_TEST(g1_point_view_test) - EOSIO_TEST(g2_point_view_test) + EOSIO_TEST(ec_point_test) + EOSIO_TEST(g1_point_test) + EOSIO_TEST(g2_point_test) EOSIO_TEST(bigint_test) return has_failed(); diff --git a/tests/unit/test_contracts/crypto_primitives_tests.cpp b/tests/unit/test_contracts/crypto_primitives_tests.cpp index 3c0e5b5457..3525947359 100644 --- a/tests/unit/test_contracts/crypto_primitives_tests.cpp +++ b/tests/unit/test_contracts/crypto_primitives_tests.cpp @@ -40,9 +40,13 @@ class [[eosio::contract]] crypto_primitives_tests : public contract{ addtest_helper( point1, point2, expected_x, expected_y ); // view - eosio::g1_point_view point_view1 {x1, y1}; - eosio::g1_point_view point_view2 {x2, y2}; + eosio::g1_point_view point_view1 {x1.data(), x1.size(), y1.data(), y1.size()}; + eosio::g1_point_view point_view2 {x2.data(), x2.size(), y2.data(), y2.size()}; addtest_helper( point_view1, point_view2, expected_x, expected_y ); + + eosio::g1_point_view point_view1_1 {point1}; + eosio::g1_point_view point_view2_1 {point2}; + addtest_helper( point_view1_1, point_view2_1, expected_x, expected_y ); } // test add where points are constructed from other points @@ -57,6 +61,10 @@ class [[eosio::contract]] crypto_primitives_tests : public contract{ eosio::g1_point_view point_view1 {p1}; eosio::g1_point_view point_view2 {p2}; addtest_helper( point_view1, point_view2, expected_x, expected_y ); + + eosio::g1_point_view point_view1_1 {point1}; + eosio::g1_point_view point_view2_1 {point2}; + addtest_helper( point_view1_1, point_view2_1, expected_x, expected_y ); } template @@ -75,8 +83,11 @@ class [[eosio::contract]] crypto_primitives_tests : public contract{ multest_helper(g1_point, s, expected_x, expected_y); // view - eosio::g1_point_view g1_view {g1_x, g1_y}; + eosio::g1_point_view g1_view {g1_x.data(), g1_x.size(), g1_y.data(), g1_y.size()}; multest_helper(g1_view, s, expected_x, expected_y); + + eosio::g1_point_view g1_view_1 {g1_point}; + multest_helper(g1_view_1, s, expected_x, expected_y); } template @@ -97,11 +108,17 @@ class [[eosio::contract]] crypto_primitives_tests : public contract{ pairtest_helper( g1_a, g2_a, g1_b, g2_b, expected ); // view - eosio::g1_point_view g1_view_a {g1_a_x, g1_a_y}; - eosio::g2_point_view g2_view_a {g2_a_x, g2_a_y}; - eosio::g1_point_view g1_view_b {g1_b_x, g1_b_y}; - eosio::g2_point_view g2_view_b {g2_b_x, g2_b_y}; + eosio::g1_point_view g1_view_a {g1_a_x.data(), g1_a_x.size(), g1_a_y.data(), g1_a_y.size()}; + eosio::g2_point_view g2_view_a {g2_a_x.data(), g2_a_x.size(), g2_a_y.data(), g2_a_y.size()}; + eosio::g1_point_view g1_view_b {g1_b_x.data(), g1_b_x.size(), g1_b_y.data(), g1_b_y.size()}; + eosio::g2_point_view g2_view_b {g2_b_x.data(), g2_b_x.size(), g2_b_y.data(), g2_b_y.size()}; pairtest_helper( g1_view_a, g2_view_a, g1_view_b, g2_view_b, expected ); + + eosio::g1_point_view g1_view_a_1 { g1_a }; + eosio::g2_point_view g2_view_a_1 { g2_a }; + eosio::g1_point_view g1_view_b_1 { g1_b }; + eosio::g2_point_view g2_view_b_1 { g2_b }; + pairtest_helper( g1_view_a_1, g2_view_a_1, g1_view_b_1, g2_view_b_1, expected ); } // test pairtest where points are constructed from other points