Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/hotstuff_integration' into GH-1523
Browse files Browse the repository at this point in the history
…-finalizer-set-transition-2
  • Loading branch information
heifner committed Sep 7, 2023
2 parents b695b40 + e0a9901 commit d24c1a5
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 31 deletions.
11 changes: 7 additions & 4 deletions libraries/libfc/src/crypto/bls_public_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ namespace fc::crypto::blslib {

auto data_str = base64str.substr(config::bls_public_key_prefix.size());

std::array<uint8_t, 48> bytes = fc::crypto::blslib::deserialize_base64<std::array<uint8_t, 48>>(data_str);
std::array<uint8_t, 96> bytes = fc::crypto::blslib::deserialize_base64<std::array<uint8_t, 96>>(data_str);

std::optional<bls12_381::g1> g1 = bls12_381::g1::fromCompressedBytesBE(bytes);
constexpr bool check = false; // default
constexpr bool raw = true;
std::optional<bls12_381::g1> g1 = bls12_381::g1::fromAffineBytesLE(bytes, check, raw);
FC_ASSERT(g1);
return *g1;
}
Expand All @@ -26,9 +28,10 @@ namespace fc::crypto::blslib {

std::string bls_public_key::to_string(const yield_function_t& yield)const {

std::array<uint8_t, 48> bytes = _pkey.toCompressedBytesBE();
constexpr bool raw = true;
std::array<uint8_t, 96> bytes = _pkey.toAffineBytesLE(raw);

std::string data_str = fc::crypto::blslib::serialize_base64<std::array<uint8_t, 48>>(bytes);
std::string data_str = fc::crypto::blslib::serialize_base64<std::array<uint8_t, 96>>(bytes);

return config::bls_public_key_prefix + data_str;

Expand Down
13 changes: 8 additions & 5 deletions libraries/libfc/src/crypto/bls_signature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ namespace fc::crypto::blslib {

auto data_str = base64str.substr(config::bls_signature_prefix.size());

std::array<uint8_t, 96> bytes = fc::crypto::blslib::deserialize_base64<std::array<uint8_t, 96>>(data_str);
std::array<uint8_t, 192> bytes = fc::crypto::blslib::deserialize_base64<std::array<uint8_t, 192>>(data_str);

std::optional<bls12_381::g2> g2 = bls12_381::g2::fromCompressedBytesBE(bytes);
constexpr bool check = false; // default
constexpr bool raw = true;
std::optional<bls12_381::g2> g2 = bls12_381::g2::fromAffineBytesLE(bytes, check, raw);
FC_ASSERT(g2);
return *g2;

Expand All @@ -31,9 +33,10 @@ namespace fc::crypto::blslib {
std::string bls_signature::to_string(const yield_function_t& yield) const
{

std::array<uint8_t, 96> bytes = _sig.toCompressedBytesBE();
constexpr bool raw = true;
std::array<uint8_t, 192> bytes = _sig.toAffineBytesLE(raw);

std::string data_str = fc::crypto::blslib::serialize_base64<std::array<uint8_t, 96>>(bytes);
std::string data_str = fc::crypto::blslib::serialize_base64<std::array<uint8_t, 192>>(bytes);

return config::bls_signature_prefix + data_str;

Expand All @@ -56,4 +59,4 @@ namespace fc
{
vo = crypto::blslib::bls_signature(var.as_string());
}
} // fc
} // fc
41 changes: 20 additions & 21 deletions libraries/libfc/test/test_bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,48 +282,47 @@ BOOST_AUTO_TEST_CASE(bls_prefix_encoding_check) try {

//test no_throw for correctly encoded keys
BOOST_CHECK_NO_THROW(bls_private_key("PVT_BLS_LaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+x"));
BOOST_CHECK_NO_THROW(bls_public_key("PUB_BLS_hiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="));
BOOST_CHECK_NO_THROW(bls_signature("SIG_BLS_qn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="));
BOOST_CHECK_NO_THROW(bls_public_key("PUB_BLS_tCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSRg=="));
BOOST_CHECK_NO_THROW(bls_signature("SIG_BLS_Syq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="));

//test no pivot delimiter
BOOST_CHECK_THROW(bls_private_key("PVTBLSLaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+x"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUBBLShiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIGBLSqn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUBBLStCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSRg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIGBLSSyq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="), fc::assert_exception);

//test first prefix validation
BOOST_CHECK_THROW(bls_private_key("XYZ_BLS_LaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+x"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("XYZ_BLS_hiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("XYZ_BLS_qn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("XYZ_BLS_tCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSRg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("XYZ_BLS_Syq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="), fc::assert_exception);

//test second prefix validation
BOOST_CHECK_THROW(bls_private_key("PVT_XYZ_LaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+x"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_XYZ_hiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_XYZ_qn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_XYZ_tCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSRg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_XYZ_Syq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="), fc::assert_exception);

//test missing prefix
BOOST_CHECK_THROW(bls_private_key("LaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+x"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("hiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("qn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("tCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSRg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("Syq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="), fc::assert_exception);

//test incomplete prefix
BOOST_CHECK_THROW(bls_private_key("PVT_LaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+x"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_hiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_qn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_tCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSRg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_Syq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_private_key("BLS_LaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+x"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("BLS_hiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("BLS_qn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("BLS_tCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSRg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("BLS_Syq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="), fc::assert_exception);

//test invalid data / invalid checksum
BOOST_CHECK_THROW(bls_private_key("PVT_BLS_LaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+y"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_BLS_hiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFBA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_BLS_qn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS8g=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_BLS_tCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSSg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_BLS_Syq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQxQ=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_private_key("PVT_BLS_LaNRcYuQxSm/tRrMofQduPb5U2xUfdrCO0Yo5/CRcDeeHO+x"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_BLS_hiQykLvL/ZrnW97OeYGWU1AgjrXpnwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_BLS_qn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqQ8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_BLS_tCPHD1uL85ZWAX8yY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSRg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_BLS_Syq5e23eMxcXnSGud+ACcKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_private_key("PVT_BLS_MaNRcYuQxSm/tRrMofQduPa5U2xUfdrCO0Yo5/CRcDeeHO+x"), fc::assert_exception);
BOOST_CHECK_THROW(bls_public_key("PUB_BLS_iiQykLvL/ZrnW97OeYGWU1AgjrXpmwTVzSTpVa2pYfjAoWLe50C+e9xsPAYTui6xbEYFCA=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_BLS_rn0BzfxSR4D6TK5c0MCYkX/hG4hp7NPwkEHvws4zoToZgPatfhqP8A62sEZd9gQ4FB95uVAQX04ZDj7nx85fsUdv4RtW6fxzUV2ZudfNUWRdjPX8ytXXnMEBAs6RRoF1TfiS9g=="), fc::assert_exception);

BOOST_CHECK_THROW(bls_public_key("PUB_BLS_uCPHD1uL85ZWAX8xY06U00e72GZR0ux/RcB3DOFF5KV22F9eAVNAFU/enVJwLtQCG8N0v4KkwSSdoJo9ZRR042/xbiR3JgIsQmUqXoR0YyMuPcUGQbbon65ZgfsD3BkBUOPSSg=="), fc::assert_exception);
BOOST_CHECK_THROW(bls_signature("SIG_BLS_Tyq5e23eMxcXnSGud+ACbKp5on4Rn2kOXdrA5sH/VNS/0i8V9RG/Oq1AliFBuJsNm7Y+LT1bqh/23+mVzYs/YVJAmDUHLFjimqyyMI+5wDLUhqFxVplSlezTOc3kj7cSFJRCfpcZUhD0gPffjBkxXctiNubjdtqLUjkLr6jWGNFrxKeSOXS9elB9tn5nZT4SGzygqNLjcWCu4Bza7tC5B7djLtzr/9SEpDb3XPPCUTmm6kMmi2tWwxGRmu06MMMI2sjQwQ=="), fc::assert_exception);
} FC_LOG_AND_RETHROW();

BOOST_AUTO_TEST_CASE(bls_variant) try {
Expand Down
2 changes: 1 addition & 1 deletion programs/leap-util/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
add_executable( ${LEAP_UTIL_EXECUTABLE_NAME} main.cpp actions/subcommand.cpp actions/generic.cpp actions/blocklog.cpp actions/snapshot.cpp actions/chain.cpp)
add_executable( ${LEAP_UTIL_EXECUTABLE_NAME} main.cpp actions/subcommand.cpp actions/generic.cpp actions/blocklog.cpp actions/bls.cpp actions/snapshot.cpp actions/chain.cpp)

if( UNIX AND NOT APPLE )
set(rt_library rt )
Expand Down
125 changes: 125 additions & 0 deletions programs/leap-util/actions/bls.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include "bls.hpp"

#include <fc/crypto/bls_private_key.hpp>
#include <fc/crypto/bls_public_key.hpp>
#include <fc/crypto/bls_signature.hpp>

#include <boost/program_options.hpp>

using namespace fc::crypto::blslib;
namespace bpo = boost::program_options;
using bpo::options_description;

void bls_actions::setup(CLI::App& app) {
// callback helper with error code handling
auto err_guard = [this](int (bls_actions::*fun)()) {
try {
int rc = (this->*fun)();
if(rc) throw(CLI::RuntimeError(rc));
} catch(...) {
print_exception();
throw(CLI::RuntimeError(-1));
}
};

// main command
auto* sub = app.add_subcommand("bls", "BLS utility");
sub->require_subcommand();

// Create subcommand
auto create = sub->add_subcommand("create", "Create BLS items");
create->require_subcommand();

// sub-subcommand - key
auto* create_key = create->add_subcommand("key", "Create a new BLS keypair and print the public and private keys")->callback([err_guard]() { err_guard(&bls_actions::create_key); });
create_key->add_option("-f,--file", opt->key_file, "Name of file to write private/public key output to. (Must be set, unless \"--to-console\" is passed");
create_key->add_flag( "--to-console", opt->print_console, "Print private/public keys to console.");

// sub-subcommand - pop (proof of possession)
auto* create_pop = create->add_subcommand("pop", "Create proof of possession of the corresponding private key for a given public key")->callback([err_guard]() { err_guard(&bls_actions::create_pop); });
create_pop->add_option("-f,--file", opt->key_file, "Name of file storing the private key. (one and only one of \"-f,--file\" and \"--private-key\" must be set)");
create_pop->add_option("--private-key", opt->private_key_str, "The private key. (one and only one of \"-f,--file\" and \"--private-key\" must be set)");
}

int bls_actions::create_key() {
if (opt->key_file.empty() && !opt->print_console) {
std::cerr << "ERROR: Either indicate a file using \"-f, --file\" or pass \"--to-console\"" << "\n";
return -1;
} else if (!opt->key_file.empty() && opt->print_console) {
std::cerr << "ERROR: Only one of \"-f, --file\" or pass \"--to-console\" can be provided" << "\n";
return -1;
}

// create a private key and get its corresponding public key
const bls_private_key private_key = bls_private_key::generate();
const bls_public_key public_key = private_key.get_public_key();

// generate pop
const std::string pop_str = generate_pop_str(private_key);

// prepare output
std::string out_str = "Private key: " + private_key.to_string({}) + "\n";
out_str += "Public key: " + public_key.to_string({}) + "\n";
out_str += "Proof of Possession: " + pop_str + "\n";
if (opt->print_console) {
std::cout << out_str;
} else {
std::cout << "saving keys to " << opt->key_file << "\n";
std::ofstream out( opt->key_file.c_str() );
out << out_str;
}

return 0;
}

int bls_actions::create_pop() {
if (opt->key_file.empty() && opt->private_key_str.empty()) {
std::cerr << "ERROR: Either indicate a file using \"-f, --file\" or pass \"--private-key\"" << "\n";
return -1;
} else if (!opt->key_file.empty() && !opt->private_key_str.empty()) {
std::cerr << "ERROR: Only one of \"-f, --file\" and \"--private-key\" can be provided" << "\n";
return -1;
}

std::string private_key_str;
if (!opt->private_key_str.empty()) {
private_key_str = opt->private_key_str;
} else {
std::ifstream key_file(opt->key_file);

if (!key_file.is_open()) {
std::cerr << "ERROR: failed to open file " << opt->key_file << "\n";
return -1;
}

if (std::getline(key_file, private_key_str)) {
if (!key_file.eof()) {
std::cerr << "ERROR: file " << opt->key_file << " contains more than one line" << "\n";
return -1;
}
} else {
std::cerr << "ERROR: file " << opt->key_file << " is empty" << "\n";
return -1;
}
}

// create private key object using input private key string
const bls_private_key private_key = bls_private_key(private_key_str);
const bls_public_key public_key = private_key.get_public_key();
std::string pop_str = generate_pop_str(private_key);

std::cout << "Proof of Possession: " << pop_str << "\n";
std::cout << "Public key: " << public_key.to_string({}) << "\n";

return 0;
}

std::string bls_actions::generate_pop_str(const bls_private_key& private_key) {
const bls_public_key public_key = private_key.get_public_key();

const std::array<uint8_t, 96> msg = public_key._pkey.toAffineBytesLE(true); // true means raw
const std::vector<uint8_t> msg_vector = std::vector<uint8_t>(msg.begin(), msg.end());
const bls_signature pop = private_key.sign(msg_vector);

return pop.to_string({});
}
26 changes: 26 additions & 0 deletions programs/leap-util/actions/bls.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "subcommand.hpp"
#include <eosio/chain/config.hpp>

#include <fc/crypto/bls_private_key.hpp>

using namespace eosio::chain;

struct bls_options {
std::string key_file;
std::string private_key_str;

// flags
bool print_console{false};
};

class bls_actions : public sub_command<bls_options> {
public:
void setup(CLI::App& app);

protected:
int create_key();
int create_pop();

private:
std::string generate_pop_str(const fc::crypto::blslib::bls_private_key& private_key);
};
5 changes: 5 additions & 0 deletions programs/leap-util/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <CLI/CLI.hpp>

#include "actions/blocklog.hpp"
#include "actions/bls.hpp"
#include "actions/chain.hpp"
#include "actions/generic.hpp"
#include "actions/snapshot.hpp"
Expand Down Expand Up @@ -33,6 +34,10 @@ int main(int argc, char** argv) {
auto blocklog_subcommand = std::make_shared<blocklog_actions>();
blocklog_subcommand->setup(app);

// bls sc tree
auto bls_subcommand = std::make_shared<bls_actions>();
bls_subcommand->setup(app);

// snapshot sc tree
auto snapshot_subcommand = std::make_shared<snapshot_actions>();
snapshot_subcommand->setup(app);
Expand Down
Loading

0 comments on commit d24c1a5

Please sign in to comment.