Skip to content

Commit

Permalink
Use lazy BLS signatures more often and don't always verify self-recov…
Browse files Browse the repository at this point in the history
…ered sigs (dashpay#2860)

* Make CBLSLazySignature thread safe

* Perform malleability check in CBLSLazySignature

* Use CBLSLazySignature in CRecoveredSig and CInstantSendLock

* Only sporadically verify self-recovered signatures

* test
  • Loading branch information
codablock authored and panleone committed Nov 14, 2024
1 parent f4a5a04 commit 965a4a7
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/llmq/quorums_chainlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ void CChainLocksHandler::HandleNewRecoveredSig(const llmq::CRecoveredSig& recove

clsig.nHeight = lastSignedHeight;
clsig.blockHash = lastSignedMsgHash;
clsig.sig = recoveredSig.sig;
clsig.sig = recoveredSig.sig.Get();
}
ProcessNewChainLock(-1, clsig, ::SerializeHash(clsig));
}
Expand Down
15 changes: 8 additions & 7 deletions src/llmq/quorums_signing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ bool CRecoveredSigsDb::ReadRecoveredSig(Consensus::LLMQType llmqType, const uint
}

try {
ret.Unserialize(ds, false);
ret.Unserialize(ds);
return true;
} catch (std::exception&) {
return false;
Expand Down Expand Up @@ -326,11 +326,6 @@ bool CSigningManager::PreVerifyRecoveredSig(NodeId nodeId, const CRecoveredSig&
return false;
}

if (!recoveredSig.sig.IsValid()) {
retBan = true;
return false;
}

return true;
}

Expand Down Expand Up @@ -417,8 +412,14 @@ bool CSigningManager::ProcessPendingRecoveredSigs(CConnman& connman)
auto& v = p.second;

for (auto& recSig : v) {
// we didn't verify the lazy signature until now
if (!recSig.sig.Get().IsValid()) {
batchVerifier.badSources.emplace(nodeId);
break;
}

const auto& quorum = quorums.at(std::make_pair((Consensus::LLMQType)recSig.llmqType, recSig.quorumHash));
batchVerifier.PushMessage(nodeId, recSig.GetHash(), llmq::utils::BuildSignHash(recSig), recSig.sig, quorum->quorumPublicKey);
batchVerifier.PushMessage(nodeId, recSig.GetHash(), llmq::utils::BuildSignHash(recSig), recSig.sig.Get(), quorum->quorumPublicKey);
verifyCount++;
}
}
Expand Down
30 changes: 8 additions & 22 deletions src/llmq/quorums_signing.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,20 @@ class CRecoveredSig
uint256 quorumHash;
uint256 id;
uint256 msgHash;
CBLSSignature sig;
CBLSLazySignature sig;

// only in-memory
uint256 hash;

public:
template <typename Stream>
inline void Serialize(Stream& s) const
SERIALIZE_METHODS(CRecoveredSig, obj)
{
s << llmqType;
s << quorumHash;
s << id;
s << msgHash;
s << sig;
}
template <typename Stream>
inline void Unserialize(Stream& s, bool checkMalleable = true, bool updateHash = true, bool skipSig = false)
{
s >> llmqType;
s >> quorumHash;
s >> id;
s >> msgHash;
if (!skipSig) {
sig.Unserialize(s, checkMalleable);
if (updateHash) {
UpdateHash();
}
}
READWRITE(obj.llmqType);
READWRITE(obj.quorumHash);
READWRITE(obj.id);
READWRITE(obj.msgHash);
READWRITE(obj.sig);
SER_READ(obj, obj.UpdateHash());
}

void UpdateHash()
Expand Down
21 changes: 13 additions & 8 deletions src/llmq/quorums_signing_shares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,16 +753,21 @@ void CSigSharesManager::TryRecoverSig(const CQuorumCPtr& quorum, const uint256&
rs.quorumHash = quorum->pindexQuorum->GetBlockHash();
rs.id = id;
rs.msgHash = msgHash;
rs.sig = recoveredSig;
rs.sig.Set(recoveredSig);
rs.UpdateHash();

auto signHash = llmq::utils::BuildSignHash(rs);
bool valid = rs.sig.VerifyInsecure(quorum->quorumPublicKey, signHash);
if (!valid) {
// this should really not happen as we have verified all signature shares before
LogPrintf("CSigSharesManager::%s -- own recovered signature is invalid. id=%s, msgHash=%s\n", __func__,
id.ToString(), msgHash.ToString());
return;
// There should actually be no need to verify the self-recovered signatures as it should always succeed. Let's
// however still verify it from time to time, so that we have a chance to catch bugs. We do only this sporadic
// verification because this is unbatched and thus slow verification that happens here.
if (((recoveredSigsCounter++) % 100) == 0) {
auto signHash = llmq::utils::BuildSignHash(rs);
bool valid = recoveredSig.VerifyInsecure(quorum->quorumPublicKey, signHash);
if (!valid) {
// this should really not happen as we have verified all signature shares before
LogPrintf("CSigSharesManager::%s -- own recovered signature is invalid. id=%s, msgHash=%s\n", __func__,
id.ToString(), msgHash.ToString());
return;
}
}

quorumSigningManager->ProcessRecoveredSig(-1, rs, quorum, connman);
Expand Down
1 change: 1 addition & 0 deletions src/llmq/quorums_signing_shares.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ class CSigSharesManager : public CRecoveredSigsListener
FastRandomContext rnd;

int64_t lastCleanupTime{0};
std::atomic<uint32_t> recoveredSigsCounter{0};

public:
CSigSharesManager();
Expand Down

0 comments on commit 965a4a7

Please sign in to comment.