Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bech32 export/import encoding format for BLS keys #2733

Merged
merged 7 commits into from
Feb 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ set(COMMON_SOURCES
./src/bls/bls_ies.cpp
./src/bls/bls_worker.cpp
./src/bls/bls_wrapper.cpp
./src/bls/key_io.cpp
./src/budget/budgetdb.cpp
./src/budget/budgetmanager.cpp
./src/budget/budgetproposal.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ BITCOIN_CORE_H = \
bls/bls_ies.h \
bls/bls_worker.h \
bls/bls_wrapper.h \
bls/key_io.h \
chain.h \
chainparams.h \
chainparamsbase.h \
Expand Down Expand Up @@ -345,6 +346,7 @@ libbitcoin_server_a_SOURCES = \
bls/bls_ies.cpp \
bls/bls_worker.cpp \
bls/bls_wrapper.cpp \
bls/key_io.cpp \
chain.cpp \
checkpoints.cpp \
consensus/params.cpp \
Expand Down
6 changes: 5 additions & 1 deletion src/activemasternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "activemasternode.h"

#include "addrman.h"
#include "bls/key_io.h"
#include "bls/bls_wrapper.h"
#include "masternode.h"
#include "masternodeconfig.h"
Expand Down Expand Up @@ -61,9 +62,12 @@ OperationResult CActiveDeterministicMasternodeManager::SetOperatorKey(const std:
if (strMNOperatorPrivKey.empty()) {
return errorOut("ERROR: Masternode operator priv key cannot be empty.");
}
if (!info.keyOperator.SetHexStr(strMNOperatorPrivKey)) {

auto opSk = bls::DecodeSecret(Params(), strMNOperatorPrivKey);
if (!opSk) {
return errorOut(_("Invalid mnoperatorprivatekey. Please see the documentation."));
}
info.keyOperator = *opSk;
info.pubKeyOperator = info.keyOperator.GetPublicKey();
return OperationResult(true);
}
Expand Down
17 changes: 2 additions & 15 deletions src/bls/bls_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,21 +129,6 @@ class CBLSWrapper
return cachedHash;
}

bool SetHexStr(const std::string& str)
{
if (!IsHex(str)) {
Reset();
return false;
}
auto b = ParseHex(str);
if (b.size() != SerSize) {
Reset();
return false;
}
SetByteVector(b);
return IsValid();
}

public:
template <typename Stream>
inline void Serialize(Stream& s) const
Expand Down Expand Up @@ -174,6 +159,8 @@ class CBLSWrapper
return true;
}

// hex-encoding. Used only for signatures.
// For secret/public keys use bls::EncodeSecret/EncodePublic
inline std::string ToString() const
{
std::vector<uint8_t> buf = ToByteVector();
Expand Down
73 changes: 73 additions & 0 deletions src/bls/key_io.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) 2022 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include "bls/key_io.h"

#include "chainparams.h"
#include "bech32.h"
#include "bls/bls_wrapper.h"

namespace bls {

template<typename BLSKey>
static std::string EncodeBLS(const CChainParams& params,
const BLSKey& key,
CChainParams::Bech32Type type)
{
if (!key.IsValid()) return "";
std::vector<unsigned char> vec{key.ToByteVector()};
std::vector<unsigned char> data;
data.reserve((vec.size() * 8 + 4) / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, vec.begin(), vec.end());
auto res = bech32::Encode(params.Bech32HRP(type), data);
memory_cleanse(vec.data(), vec.size());
memory_cleanse(data.data(), data.size());
return res;
}

template<typename BLSKey>
static Optional<BLSKey> DecodeBLS(const CChainParams& params,
const std::string& keyStr,
CChainParams::Bech32Type type,
unsigned int keySize)
{
if (keyStr.empty()) return nullopt;
auto bech = bech32::Decode(keyStr);
if (bech.first == params.Bech32HRP(type) && bech.second.size() == keySize) {
std::vector<unsigned char> data;
data.reserve((bech.second.size() * 5) / 8);
if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
BLSKey key;
ss >> key;
if (key.IsValid()) return {key};
}
}
return nullopt;
}

std::string EncodeSecret(const CChainParams& params, const CBLSSecretKey& key)
{
return EncodeBLS<CBLSSecretKey>(params, key, CChainParams::BLS_SECRET_KEY);
}

std::string EncodePublic(const CChainParams& params, const CBLSPublicKey& pk)
{
return EncodeBLS<CBLSPublicKey>(params, pk, CChainParams::BLS_PUBLIC_KEY);
}

const size_t ConvertedBlsSkSize = (BLS_CURVE_SECKEY_SIZE * 8 + 4) / 5;
const size_t ConvertedBlsPkSize = (BLS_CURVE_PUBKEY_SIZE * 8 + 4) / 5;

Optional<CBLSSecretKey> DecodeSecret(const CChainParams& params, const std::string& keyStr)
{
return DecodeBLS<CBLSSecretKey>(params, keyStr, CChainParams::BLS_SECRET_KEY, ConvertedBlsSkSize);
}

Optional<CBLSPublicKey> DecodePublic(const CChainParams& params, const std::string& keyStr)
{
return DecodeBLS<CBLSPublicKey>(params, keyStr, CChainParams::BLS_PUBLIC_KEY, ConvertedBlsPkSize);
}

} // end bls namespace
24 changes: 24 additions & 0 deletions src/bls/key_io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2022 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#ifndef PIVX_BLS_KEY_IO_H
#define PIVX_BLS_KEY_IO_H

#include "optional.h"

class CChainParams;
class CBLSPublicKey;
class CBLSSecretKey;

namespace bls {

std::string EncodeSecret(const CChainParams& params, const CBLSSecretKey& key);
Optional<CBLSSecretKey> DecodeSecret(const CChainParams& params, const std::string& keyStr);

std::string EncodePublic(const CChainParams& params, const CBLSPublicKey& pk);
Optional<CBLSPublicKey> DecodePublic(const CChainParams& params, const std::string& keyStr);

} // end bls namespace

#endif //PIVX_BLS_KEY_IO_H
9 changes: 9 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ class CMainParams : public CChainParams
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "p-secret-spending-key-main";
bech32HRPs[SAPLING_EXTENDED_FVK] = "pxviews";

bech32HRPs[BLS_SECRET_KEY] = "bls-sk";
bech32HRPs[BLS_PUBLIC_KEY] = "bls-pk";

// long living quorum params
consensus.llmqs[Consensus::LLMQ_50_60] = llmq50_60;
consensus.llmqs[Consensus::LLMQ_400_60] = llmq400_60;
Expand Down Expand Up @@ -468,6 +471,9 @@ class CTestNetParams : public CChainParams
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "p-secret-spending-key-test";
bech32HRPs[SAPLING_EXTENDED_FVK] = "pxviewtestsapling";

bech32HRPs[BLS_SECRET_KEY] = "bls-sk-test";
bech32HRPs[BLS_PUBLIC_KEY] = "bls-pk-test";

// long living quorum params
consensus.llmqs[Consensus::LLMQ_50_60] = llmq50_60;
consensus.llmqs[Consensus::LLMQ_400_60] = llmq400_60;
Expand Down Expand Up @@ -602,6 +608,9 @@ class CRegTestParams : public CChainParams
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "p-secret-spending-key-test";
bech32HRPs[SAPLING_EXTENDED_FVK] = "pxviewtestsapling";

bech32HRPs[BLS_SECRET_KEY] = "bls-sk-test";
bech32HRPs[BLS_PUBLIC_KEY] = "bls-pk-test";

// long living quorum params
consensus.llmqs[Consensus::LLMQ_TEST] = llmq_test;
nLLMQConnectionRetryTimeout = 5;
Expand Down
3 changes: 3 additions & 0 deletions src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class CChainParams
SAPLING_EXTENDED_SPEND_KEY,
SAPLING_EXTENDED_FVK,

BLS_SECRET_KEY,
BLS_PUBLIC_KEY,

MAX_BECH32_TYPES
};

Expand Down
7 changes: 4 additions & 3 deletions src/evo/deterministicmns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "evo/deterministicmns.h"

#include "bls/key_io.h"
#include "chain.h"
#include "coins.h"
#include "chainparams.h"
Expand Down Expand Up @@ -41,7 +42,7 @@ std::string CDeterministicMNState::ToString() const

return strprintf("CDeterministicMNState(nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, ownerAddress=%s, operatorPubKey=%s, votingAddress=%s, addr=%s, payoutAddress=%s, operatorPayoutAddress=%s)",
nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason,
EncodeDestination(keyIDOwner), pubKeyOperator.Get().ToString(), EncodeDestination(keyIDVoting), addr.ToStringIPPort(), payoutAddress, operatorPayoutAddress);
EncodeDestination(keyIDOwner), bls::EncodePublic(Params(), pubKeyOperator.Get()), EncodeDestination(keyIDVoting), addr.ToStringIPPort(), payoutAddress, operatorPayoutAddress);
}

void CDeterministicMNState::ToJson(UniValue& obj) const
Expand All @@ -56,7 +57,7 @@ void CDeterministicMNState::ToJson(UniValue& obj) const
obj.pushKV("PoSeBanHeight", nPoSeBanHeight);
obj.pushKV("revocationReason", nRevocationReason);
obj.pushKV("ownerAddress", EncodeDestination(keyIDOwner));
obj.pushKV("operatorPubKey", pubKeyOperator.Get().ToString());
obj.pushKV("operatorPubKey", bls::EncodePublic(Params(), pubKeyOperator.Get()));
obj.pushKV("votingAddress", EncodeDestination(keyIDVoting));

CTxDestination dest1;
Expand Down Expand Up @@ -389,7 +390,7 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota
throw(std::runtime_error(strprintf("%s: can't add a masternode with a duplicate address %s", __func__, dmn->pdmnState->addr.ToStringIPPort())));
}
if (HasUniqueProperty(dmn->pdmnState->keyIDOwner) || HasUniqueProperty(dmn->pdmnState->pubKeyOperator)) {
throw(std::runtime_error(strprintf("%s: can't add a masternode with a duplicate key (%s or %s)", __func__, EncodeDestination(dmn->pdmnState->keyIDOwner), dmn->pdmnState->pubKeyOperator.Get().ToString())));
throw(std::runtime_error(strprintf("%s: can't add a masternode with a duplicate key (%s or %s)", __func__, EncodeDestination(dmn->pdmnState->keyIDOwner), bls::EncodePublic(Params(), dmn->pdmnState->pubKeyOperator.Get()))));
}

mnMap = mnMap.set(dmn->proTxHash, dmn);
Expand Down
9 changes: 5 additions & 4 deletions src/evo/providertx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "evo/providertx.h"

#include "bls/key_io.h"
#include "key_io.h"

std::string ProRegPL::MakeSignString() const
Expand All @@ -28,7 +29,7 @@ std::string ProRegPL::ToString() const
std::string payee = ExtractDestination(scriptPayout, dest) ?
EncodeDestination(dest) : "unknown";
return strprintf("ProRegPL(nVersion=%d, collateralOutpoint=%s, addr=%s, nOperatorReward=%f, ownerAddress=%s, operatorPubKey=%s, votingAddress=%s, scriptPayout=%s)",
nVersion, collateralOutpoint.ToStringShort(), addr.ToString(), (double)nOperatorReward / 100, EncodeDestination(keyIDOwner), pubKeyOperator.ToString(), EncodeDestination(keyIDVoting), payee);
nVersion, collateralOutpoint.ToStringShort(), addr.ToString(), (double)nOperatorReward / 100, EncodeDestination(keyIDOwner), bls::EncodePublic(Params(), pubKeyOperator), EncodeDestination(keyIDVoting), payee);
}

void ProRegPL::ToJson(UniValue& obj) const
Expand All @@ -40,7 +41,7 @@ void ProRegPL::ToJson(UniValue& obj) const
obj.pushKV("collateralIndex", (int)collateralOutpoint.n);
obj.pushKV("service", addr.ToString());
obj.pushKV("ownerAddress", EncodeDestination(keyIDOwner));
obj.pushKV("operatorPubKey", pubKeyOperator.ToString());
obj.pushKV("operatorPubKey", bls::EncodePublic(Params(), pubKeyOperator));
obj.pushKV("votingAddress", EncodeDestination(keyIDVoting));

CTxDestination dest1;
Expand Down Expand Up @@ -84,7 +85,7 @@ std::string ProUpRegPL::ToString() const
std::string payee = ExtractDestination(scriptPayout, dest) ?
EncodeDestination(dest) : "unknown";
return strprintf("ProUpRegPL(nVersion=%d, proTxHash=%s, operatorPubKey=%s, votingAddress=%s, payoutAddress=%s)",
nVersion, proTxHash.ToString(), pubKeyOperator.ToString(), EncodeDestination(keyIDVoting), payee);
nVersion, proTxHash.ToString(), bls::EncodePublic(Params(), pubKeyOperator), EncodeDestination(keyIDVoting), payee);
}

void ProUpRegPL::ToJson(UniValue& obj) const
Expand All @@ -98,7 +99,7 @@ void ProUpRegPL::ToJson(UniValue& obj) const
if (ExtractDestination(scriptPayout, dest)) {
obj.pushKV("payoutAddress", EncodeDestination(dest));
}
obj.pushKV("operatorPubKey", pubKeyOperator.ToString());
obj.pushKV("operatorPubKey", bls::EncodePublic(Params(), pubKeyOperator));
obj.pushKV("inputsHash", inputsHash.ToString());
}

Expand Down
3 changes: 2 additions & 1 deletion src/llmq/quorums_blockprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "llmq/quorums_blockprocessor.h"

#include "bls/key_io.h"
#include "chain.h"
#include "chainparams.h"
#include "consensus/validation.h"
Expand Down Expand Up @@ -181,7 +182,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH
}

LogPrintf("%s: processed commitment from block. type=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s\n", __func__,
qc.llmqType, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), ""/*qc.quorumPublicKey.ToString()*/);
qc.llmqType, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), bls::EncodePublic(Params(), qc.quorumPublicKey));

return true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/llmq/quorums_commitment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "llmq/quorums_commitment.h"

#include "bls/key_io.h"
#include "chainparams.h"
#include "llmq/quorums_utils.h"
#include "logging.h"
Expand Down Expand Up @@ -47,7 +48,7 @@ void CFinalCommitment::ToJson(UniValue& obj) const
obj.pushKV("signers", utils::ToHexStr(signers));
obj.pushKV("validMembersCount", CountValidMembers());
obj.pushKV("validMembers", utils::ToHexStr(validMembers));
obj.pushKV("quorumPublicKey", quorumPublicKey.ToString());
obj.pushKV("quorumPublicKey", bls::EncodePublic(Params(), quorumPublicKey));
obj.pushKV("quorumVvecHash", quorumVvecHash.ToString());
obj.pushKV("quorumSig", quorumSig.ToString());
obj.pushKV("membersSig", membersSig.ToString());
Expand Down
Loading