diff --git a/benchmark/benchmark.cpp b/benchmark/benchmark.cpp index 5c142c4162..a8ede0f68f 100644 --- a/benchmark/benchmark.cpp +++ b/benchmark/benchmark.cpp @@ -19,7 +19,7 @@ std::map> features { }; // values to control cout format -constexpr auto name_width = 28; +constexpr auto name_width = 40; constexpr auto runs_width = 5; constexpr auto time_width = 12; constexpr auto ns_width = 2; diff --git a/benchmark/bls.cpp b/benchmark/bls.cpp index abcf78af2c..4c86e78ba1 100644 --- a/benchmark/bls.cpp +++ b/benchmark/bls.cpp @@ -107,6 +107,32 @@ std::array random_scalar() }; } +// utilility to create a random fp +fp random_fe() +{ + std::random_device rd; + std::mt19937_64 gen(rd()); + std::uniform_int_distribution dis; + + return fp({ + dis(gen) % 0xb9feffffffffaaab, + dis(gen) % 0x1eabfffeb153ffff, + dis(gen) % 0x6730d2a0f6b0f624, + dis(gen) % 0x64774b84f38512bf, + dis(gen) % 0x4b1ba7b6434bacd7, + dis(gen) % 0x1a0111ea397fe69a + }); +} + +// utilility to create a random fp2 +fp2 random_fe2() +{ + return fp2({ + random_fe(), + random_fe() + }); +} + // utilility to create a random g1 bls12_381::g1 random_g1() { @@ -125,34 +151,30 @@ bls12_381::g2 random_g2() void benchmark_bls_g1_add() { // prepare g1 operand in Jacobian LE format g1 p = random_g1(); - std::vector buf(96); - p.toAffineBytesLE(std::span((uint8_t*)buf.data(), 96), true); - eosio::chain::span op1(buf.data(), buf.size()); + std::array op; + p.toAffineBytesLE(std::span((uint8_t*)op.data(), 96), false); // prepare result operand - std::vector result_buf(96); - eosio::chain::span result(result_buf.data(), result_buf.size()); + std::array result; // set up bls_g1_add to be benchmarked interface_in_benchmark interface; - auto g1_add_func = [&]() { - interface.interface->bls_g1_add(op1, op1, result); + auto benchmarked_func = [&]() { + interface.interface->bls_g1_add(op, op, result); }; - benchmarking("bls_g1_add", g1_add_func); + benchmarking("bls_g1_add", benchmarked_func); } // bls_g2_add benchmarking void benchmark_bls_g2_add() { // prepare g2 operand in Jacobian LE format g2 p = random_g2(); - std::vector buf(192); - p.toAffineBytesLE(std::span((uint8_t*)buf.data(), 192), true); - eosio::chain::span op(buf.data(), buf.size()); + std::array op; + p.toAffineBytesLE(std::span((uint8_t*)op.data(), 192), false); // prepare result operand - std::vector result_buf(192); - eosio::chain::span result(result_buf.data(), result_buf.size()); + std::array result; // set up bls_g2_add to be benchmarked interface_in_benchmark interface; @@ -164,12 +186,12 @@ void benchmark_bls_g2_add() { } // bls_g1_weighted_sum benchmarking utility -void benchmark_bls_g1_weighted_sum(std::string test_name, uint32_t num_points) { +void benchmark_bls_g1_weighted_sum_impl(const std::string& test_name, uint32_t num_points) { // prepare g1 points operand std::vector g1_buf(96*num_points); for (auto i=0u; i < num_points; ++i) { g1 p = random_g1(); - p.toAffineBytesLE(std::span((uint8_t*)g1_buf.data() + i * 96, 96), true); + p.toAffineBytesLE(std::span((uint8_t*)g1_buf.data() + i * 96, 96), false); } chain::span g1_points(g1_buf.data(), g1_buf.size()); @@ -182,8 +204,7 @@ void benchmark_bls_g1_weighted_sum(std::string test_name, uint32_t num_points) { chain::span scalars(scalars_buf.data(), scalars_buf.size()); // prepare result operand - std::vector result_buf(96); - eosio::chain::span result(result_buf.data(), result_buf.size()); + std::array result; // set up bls_g1_weighted_sum to be benchmarked interface_in_benchmark interface; @@ -196,21 +217,26 @@ void benchmark_bls_g1_weighted_sum(std::string test_name, uint32_t num_points) { // bls_g1_weighted_sum benchmarking with 1 input point void benchmark_bls_g1_weighted_sum_one_point() { - benchmark_bls_g1_weighted_sum("bls_g1_weighted_sum 1 point", 1); + benchmark_bls_g1_weighted_sum_impl("bls_g1_weighted_sum 1 point", 1); } // bls_g1_weighted_sum benchmarking with 3 input points void benchmark_bls_g1_weighted_sum_three_point() { - benchmark_bls_g1_weighted_sum("bls_g1_weighted_sum 3 points", 3); + benchmark_bls_g1_weighted_sum_impl("bls_g1_weighted_sum 3 points", 3); +} + +// bls_g1_weighted_sum benchmarking with 5 input points +void benchmark_bls_g1_weighted_sum_five_point() { + benchmark_bls_g1_weighted_sum_impl("bls_g1_weighted_sum 5 points", 5); } // bls_g2_weighted_sum benchmarking utility -void benchmark_bls_g2_weighted_sum(std::string test_name, uint32_t num_points) { +void benchmark_bls_g2_weighted_sum_impl(const std::string& test_name, uint32_t num_points) { // prepare g2 points operand std::vector g2_buf(192*num_points); for (auto i=0u; i < num_points; ++i) { g2 p = random_g2(); - p.toAffineBytesLE(std::span((uint8_t*)g2_buf.data() + i * 192, 192), true); + p.toAffineBytesLE(std::span((uint8_t*)g2_buf.data() + i * 192, 192), false); } eosio::chain::span g2_points(g2_buf.data(), g2_buf.size()); @@ -223,12 +249,11 @@ void benchmark_bls_g2_weighted_sum(std::string test_name, uint32_t num_points) { eosio::chain::span scalars(scalars_buf.data(), scalars_buf.size()); // prepare result operand - std::vector result_buf(192); - eosio::chain::span result(result_buf.data(), result_buf.size()); + std::array result; // set up bls_g2_weighted_sum to be benchmarked interface_in_benchmark interface; - auto benchmarked_func = [&]() { + auto benchmarked_func = [&]() { interface.interface->bls_g2_weighted_sum(g2_points, scalars, num_points, result); }; @@ -237,22 +262,26 @@ void benchmark_bls_g2_weighted_sum(std::string test_name, uint32_t num_points) { // bls_g2_weighted_sum benchmarking with 1 input point void benchmark_bls_g2_weighted_sum_one_point() { - benchmark_bls_g2_weighted_sum("bls_g2_weighted_sum 1 point", 1); + benchmark_bls_g2_weighted_sum_impl("bls_g2_weighted_sum 1 point", 1); } // bls_g2_weighted_sum benchmarking with 3 input points void benchmark_bls_g2_weighted_sum_three_point() { - benchmark_bls_g2_weighted_sum("bls_g2_weighted_sum 3 points", 3); + benchmark_bls_g2_weighted_sum_impl("bls_g2_weighted_sum 3 points", 3); +} + +// bls_g2_weighted_sum benchmarking with 5 input points +void benchmark_bls_g2_weighted_sum_five_point() { + benchmark_bls_g2_weighted_sum_impl("bls_g2_weighted_sum 5 points", 5); } // bls_pairing benchmarking utility -void benchmark_bls_pairing(std::string test_name, uint32_t num_pairs) { +void benchmark_bls_pairing_impl(const std::string& test_name, uint32_t num_pairs) { // prepare g1 operand std::vector g1_buf(96*num_pairs); - //g1_buf.reserve(96*num_pairs); for (auto i=0u; i < num_pairs; ++i) { g1 p = random_g1(); - p.toAffineBytesLE(std::span((uint8_t*)g1_buf.data() + i * 96, 96), true); + p.toAffineBytesLE(std::span((uint8_t*)g1_buf.data() + i * 96, 96), false); } eosio::chain::span g1_points(g1_buf.data(), g1_buf.size()); @@ -260,17 +289,16 @@ void benchmark_bls_pairing(std::string test_name, uint32_t num_pairs) { std::vector g2_buf(192*num_pairs); for (auto i=0u; i < num_pairs; ++i) { g2 p2 = random_g2(); - p2.toAffineBytesLE(std::span((uint8_t*)g2_buf.data() + i * 192, (192)), true); + p2.toAffineBytesLE(std::span((uint8_t*)g2_buf.data() + i * 192, (192)), false); } eosio::chain::span g2_points(g2_buf.data(), g2_buf.size()); // prepare result operand - std::vector result_buf(576); - eosio::chain::span result(result_buf.data(), result_buf.size()); + std::array result; // set up bls_pairing to be benchmarked interface_in_benchmark interface; - auto benchmarked_func = [&]() { + auto benchmarked_func = [&]() { interface.interface->bls_pairing(g1_points, g2_points, num_pairs, result); }; @@ -279,27 +307,27 @@ void benchmark_bls_pairing(std::string test_name, uint32_t num_pairs) { // bls_pairing benchmarking with 1 input pair void benchmark_bls_pairing_one_pair() { - benchmark_bls_pairing("bls_pairing 1 pair", 1); + benchmark_bls_pairing_impl("bls_pairing 1 pair", 1); } // bls_pairing benchmarking with 3 input pairs void benchmark_bls_pairing_three_pair() { - benchmark_bls_pairing("bls_pairing 3 pairs", 3); + benchmark_bls_pairing_impl("bls_pairing 3 pairs", 3); } // bls_g1_map benchmarking void benchmark_bls_g1_map() { // prepare e operand. Must be fp LE. - std::vector e_buf = {0xc9, 0x3f,0x81,0x7b, 0x15, 0x9b, 0xdf, 0x84, 0x04, 0xdc, 0x37, 0x85, 0x14, 0xf8, 0x45, 0x19, 0x2b, 0xba, 0xe4, 0xfa, 0xac, 0x7f, 0x4a, 0x56, 0x89, 0x24, 0xf2, 0xd9, 0x72, 0x51, 0x25, 0x00, 0x04, 0x89, 0x40, 0x8f, 0xd7, 0x96, 0x46, 0x1c, 0x28, 0x89, 0x00, 0xad, 0xd0, 0x0d, 0x46, 0x18}; - eosio::chain::span e((char*)e_buf.data(), e_buf.size()); + std::array e; + fp a = random_fe(); + a.toBytesLE(std::span((uint8_t*)e.data(), 48), false); // prepare result operand - std::vector result_buf(96); - eosio::chain::span result(result_buf.data(), result_buf.size()); + std::array result; // set up bls_g1_map to be benchmarked interface_in_benchmark interface; - auto benchmarked_func = [&]() { + auto benchmarked_func = [&]() { interface.interface->bls_g1_map(e, result); }; @@ -308,17 +336,16 @@ void benchmark_bls_g1_map() { // bls_g2_map benchmarking void benchmark_bls_g2_map() { - // prepare e operand. Must be fp2 LE. - std::vector e_buf = {0xd4, 0xf2, 0xcf, 0xec, 0x99, 0x38, 0x78, 0x09, 0x57, 0x4f, 0xcc, 0x2d, 0xba, 0x10, 0x56, 0x03, 0xd9, 0x50, 0xd4, 0x90, 0xe2, 0xbe, 0xbe, 0x0c, 0x21, 0x2c, 0x05, 0xe1, 0x6b, 0x78, 0x47, 0x45, 0xef, 0x4f, 0xe8, 0xe7, 0x0b, 0x55, 0x4d, 0x0a, 0x52, 0xfe, 0x0b, 0xed, 0x5e, 0xa6, 0x69, 0x0a, 0xde, 0x23, 0x48, 0xeb, 0x89, 0x72, 0xa9, 0x67, 0x40, 0xa4, 0x30, 0xdf, 0x16, 0x2d, 0x92, 0x0e, 0x17, 0x5f, 0x59, 0x23, 0xa7, 0x6d, 0x18, 0x65, 0x0e, 0xa2, 0x4a, 0x8e, 0xc0, 0x6d, 0x41, 0x4c, 0x6d, 0x1d, 0x21, 0x8d, 0x67, 0x3d, 0xac, 0x36, 0x19, 0xa1, 0xa5, 0xc1, 0x42, 0x78, 0x57, 0x08}; - eosio::chain::span e((char*)e_buf.data(), e_buf.size()); + std::array e; + fp2 a = random_fe2(); + a.toBytesLE(std::span((uint8_t*)e.data(), 96), false); // prepare result operand - std::vector result_buf(192); - eosio::chain::span result(result_buf.data(), result_buf.size()); + std::array result; // set up bls_g2_map to be benchmarked interface_in_benchmark interface; - auto benchmarked_func = [&]() { + auto benchmarked_func = [&]() { interface.interface->bls_g2_map(e, result); }; @@ -328,27 +355,74 @@ void benchmark_bls_g2_map() { // bls_fp_mod benchmarking void benchmark_bls_fp_mod() { // prepare scalar operand - std::vector scalar_buf(64); + std::array scalar; // random_scalar returns 32 bytes. need to call it twice for (auto i=0u; i < 2; ++i) { std::array s = random_scalar(); - scalar::toBytesLE(s, std::span((uint8_t*)scalar_buf.data() + i*32, 32)); + scalar::toBytesLE(s, std::span((uint8_t*)scalar.data() + i*32, 32)); } - chain::span scalar(scalar_buf.data(), scalar_buf.size()); // prepare result operand - std::vector result_buf(48); - eosio::chain::span result(result_buf.data(), result_buf.size()); + std::array result; // set up bls_fp_mod to be benchmarked interface_in_benchmark interface; - auto benchmarked_func = [&]() { + auto benchmarked_func = [&]() { interface.interface->bls_fp_mod(scalar, result); }; benchmarking("bls_fp_mod", benchmarked_func); } +void benchmark_bls_fp_mul() { + // prepare op1 + std::array op1; + fp a = random_fe(); + a.toBytesLE(std::span((uint8_t*)op1.data(), 48), false); + + // prepare op2 + std::array op2; + fp b = random_fe(); + b.toBytesLE(std::span((uint8_t*)op2.data(), 48), false); + + // prepare result operand + std::array result; + + // set up bls_fp_mul to be benchmarked + interface_in_benchmark interface; + auto benchmarked_func = [&]() { + interface.interface->bls_fp_mul(op1, op2, result); + }; + + benchmarking("bls_fp_mul", benchmarked_func); +} + +void benchmark_bls_fp_exp() { + // prepare base + std::array base; + fp a = random_fe(); + a.toBytesLE(std::span((uint8_t*)base.data(), 48), false); + + // prepare exp operand + std::array exp; + // random_scalar returns 32 bytes. need to call it twice + for (auto i=0u; i < 2; ++i) { + std::array s = random_scalar(); + scalar::toBytesLE(s, std::span((uint8_t*)exp.data() + i*32, 32)); + } + + // prepare result operand + std::array result; + + // set up bls_fp_exp to be benchmarked + interface_in_benchmark interface; + auto benchmarked_func = [&]() { + interface.interface->bls_fp_exp(base, exp, result); + }; + + benchmarking("bls_fp_exp", benchmarked_func); +} + // register benchmarking functions void bls_benchmarking() { benchmark_bls_g1_add(); @@ -357,10 +431,14 @@ void bls_benchmarking() { benchmark_bls_pairing_three_pair(); benchmark_bls_g1_weighted_sum_one_point(); benchmark_bls_g1_weighted_sum_three_point(); + benchmark_bls_g1_weighted_sum_five_point(); benchmark_bls_g2_weighted_sum_one_point(); benchmark_bls_g2_weighted_sum_three_point(); + benchmark_bls_g2_weighted_sum_five_point(); benchmark_bls_g1_map(); benchmark_bls_g2_map(); benchmark_bls_fp_mod(); + benchmark_bls_fp_mul(); + benchmark_bls_fp_exp(); } } // namespace benchmark