Skip to content

Commit

Permalink
Use CBLSLazySignature in CBatchedSigShares
Browse files Browse the repository at this point in the history
This removes the burden on the message handler thread when many sig batches
arrive. The expensive part of deserialization is now performed in the sig
shares worker thread.

This also removes the need for the specialized deserialization of the sig
shares which tried to avoid the malleability check, as CBLSLazySignature does
not perform malleability checks at all.
  • Loading branch information
codablock committed Feb 15, 2019
1 parent 02b6888 commit 500b9c8
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 37 deletions.
21 changes: 12 additions & 9 deletions src/llmq/quorums_signing_shares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,11 +373,6 @@ bool CSigSharesManager::PreVerifyBatchedSigShares(NodeId nodeId, const CBatchedS

for (size_t i = 0; i < batchedSigShares.sigShares.size(); i++) {
auto quorumMember = batchedSigShares.sigShares[i].first;
auto& sigShare = batchedSigShares.sigShares[i].second;
if (!sigShare.IsValid()) {
retBan = true;
return false;
}
if (!dupMembers.emplace(quorumMember).second) {
retBan = true;
return false;
Expand Down Expand Up @@ -483,6 +478,14 @@ void CSigSharesManager::ProcessPendingSigShares(CConnman& connman)
continue;
}

// we didn't check this earlier because we use a lazy BLS signature and tried to avoid doing the expensive
// deserialization in the message thread
if (!sigShare.sigShare.GetSig().IsValid()) {
BanNode(nodeId);
// don't process any additional shares from this node
break;
}

auto quorum = quorums.at(std::make_pair((Consensus::LLMQType)sigShare.llmqType, sigShare.quorumHash));
auto pubKeyShare = quorum->GetPubKeyShare(sigShare.quorumMember);

Expand All @@ -493,7 +496,7 @@ void CSigSharesManager::ProcessPendingSigShares(CConnman& connman)
assert(false);
}

batchVerifier.PushMessage(nodeId, sigShare.GetKey(), sigShare.GetSignHash(), sigShare.sigShare, pubKeyShare);
batchVerifier.PushMessage(nodeId, sigShare.GetKey(), sigShare.GetSignHash(), sigShare.sigShare.GetSig(), pubKeyShare);
verifyCount++;
}
}
Expand Down Expand Up @@ -617,7 +620,7 @@ void CSigSharesManager::TryRecoverSig(const CQuorumCPtr& quorum, const uint256&
idsForRecovery.reserve((size_t) quorum->params.threshold);
for (auto it = itPair.first; it != itPair.second && sigSharesForRecovery.size() < quorum->params.threshold; ++it) {
auto& sigShare = it->second;
sigSharesForRecovery.emplace_back(sigShare.sigShare);
sigSharesForRecovery.emplace_back(sigShare.sigShare.GetSig());
idsForRecovery.emplace_back(CBLSId::FromHash(quorum->members[sigShare.quorumMember]->proTxHash));
}

Expand Down Expand Up @@ -1168,8 +1171,8 @@ void CSigSharesManager::Sign(const CQuorumCPtr& quorum, const uint256& id, const
sigShare.quorumMember = (uint16_t)memberIdx;
uint256 signHash = CLLMQUtils::BuildSignHash(sigShare);

sigShare.sigShare = skShare.Sign(signHash);
if (!sigShare.sigShare.IsValid()) {
sigShare.sigShare.SetSig(skShare.Sign(signHash));
if (!sigShare.sigShare.GetSig().IsValid()) {
LogPrintf("CSigSharesManager::%s -- failed to sign sigShare. id=%s, msgHash=%s, time=%s\n", __func__,
sigShare.id.ToString(), sigShare.msgHash.ToString(), t.count());
return;
Expand Down
34 changes: 6 additions & 28 deletions src/llmq/quorums_signing_shares.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class CSigShare
uint16_t quorumMember;
uint256 id;
uint256 msgHash;
CBLSSignature sigShare;
CBLSLazySignature sigShare;

SigShareKey key;

Expand Down Expand Up @@ -97,43 +97,21 @@ class CBatchedSigShares
uint256 quorumHash;
uint256 id;
uint256 msgHash;
std::vector<std::pair<uint16_t, CBLSSignature>> sigShares;
std::vector<std::pair<uint16_t, CBLSLazySignature>> sigShares;

public:
ADD_SERIALIZE_METHODS;

template<typename Stream, typename Operation>
inline void SerializationOpBase(Stream& s, Operation ser_action)
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(llmqType);
READWRITE(quorumHash);
READWRITE(id);
READWRITE(msgHash);
READWRITE(sigShares);
}

template<typename Stream>
inline void Serialize(Stream& s) const
{
NCONST_PTR(this)->SerializationOpBase(s, CSerActionSerialize());
s << sigShares;
}
template<typename Stream>
inline void Unserialize(Stream& s)
{
NCONST_PTR(this)->SerializationOpBase(s, CSerActionUnserialize());

// we do custom deserialization here with the malleability check skipped for signatures
// we can do this here because we never use the hash of a sig share for identification and are only interested
// in validity
uint64_t nSize = ReadCompactSize(s);
if (nSize > 400) { // we don't support larger quorums, so this is the limit
throw std::ios_base::failure(strprintf("too many elements (%d) in CBatchedSigShares", nSize));
}
sigShares.resize(nSize);
for (size_t i = 0; i < nSize; i++) {
s >> sigShares[i].first;
sigShares[i].second.Unserialize(s, false);
}
};

CSigShare RebuildSigShare(size_t idx) const
{
assert(idx < sigShares.size());
Expand Down

0 comments on commit 500b9c8

Please sign in to comment.