Move SelectQuorumForSigning into CSigningManager and make it height based

This commit is contained in:
Alexander Block 2019-01-24 14:11:14 +01:00
parent 4026ea203b
commit cf33efc9e1
4 changed files with 44 additions and 35 deletions

View File

@ -333,35 +333,6 @@ std::vector<CQuorumCPtr> CQuorumManager::ScanQuorums(Consensus::LLMQType llmqTyp
return result;
}
CQuorumCPtr CQuorumManager::SelectQuorum(Consensus::LLMQType llmqType, const uint256& selectionHash)
{
LOCK(cs_main);
return SelectQuorum(llmqType, chainActive.Tip()->GetBlockHash(), selectionHash);
}
CQuorumCPtr CQuorumManager::SelectQuorum(Consensus::LLMQType llmqType, const uint256& startBlock, const uint256& selectionHash)
{
auto& llmqParams = Params().GetConsensus().llmqs.at(llmqType);
size_t poolSize = (size_t)llmqParams.signingActiveQuorumCount;
auto quorums = ScanQuorums(llmqType, startBlock, poolSize);
if (quorums.empty()) {
return nullptr;
}
std::vector<std::pair<uint256, size_t>> scores;
scores.reserve(quorums.size());
for (size_t i = 0; i < quorums.size(); i++) {
CHashWriter h(SER_NETWORK, 0);
h << (uint8_t)llmqType;
h << quorums[i]->quorumHash;
h << selectionHash;
scores.emplace_back(h.GetHash(), i);
}
std::sort(scores.begin(), scores.end());
return quorums[scores.front().second];
}
CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, const uint256& quorumHash)
{
AssertLockHeld(cs_main);

View File

@ -99,8 +99,6 @@ public:
CQuorumCPtr GetNewestQuorum(Consensus::LLMQType llmqType);
std::vector<CQuorumCPtr> ScanQuorums(Consensus::LLMQType llmqType, size_t maxCount);
std::vector<CQuorumCPtr> ScanQuorums(Consensus::LLMQType llmqType, const uint256& startBlock, size_t maxCount);
CQuorumCPtr SelectQuorum(Consensus::LLMQType llmqType, const uint256& selectionHash);
CQuorumCPtr SelectQuorum(Consensus::LLMQType llmqType, const uint256& startBlock, const uint256& selectionHash);
private:
void EnsureQuorumConnections(Consensus::LLMQType llmqType, const CBlockIndex *pindexNew);

View File

@ -496,12 +496,18 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, const uint
db.WriteVoteForId(llmqType, id, msgHash);
}
int tipHeight;
{
LOCK(cs_main);
tipHeight = chainActive.Height();
}
// This might end up giving different results on different members
// This might happen when we are on the brink of confirming a new quorum
// This gives a slight risk of not getting enough shares to recover a signature
// But at least it shouldn't be possible to get conflicting recovered signatures
// TODO fix this by re-signing when the next block arrives, but only when that block results in a change of the quorum list and no recovered signature has been created in the mean time
CQuorumCPtr quorum = quorumManager->SelectQuorum(llmqType, id);
CQuorumCPtr quorum = SelectQuorumForSigning(llmqType, tipHeight, id);
if (!quorum) {
LogPrintf("CSigningManager::%s -- failed to select quorum. id=%s, msgHash=%s\n", __func__, id.ToString(), msgHash.ToString());
return false;
@ -548,11 +554,43 @@ bool CSigningManager::IsConflicting(Consensus::LLMQType llmqType, const uint256&
return false;
}
bool CSigningManager::VerifyRecoveredSig(Consensus::LLMQType llmqType, const uint256& signedAtTip, const uint256& id, const uint256& msgHash, const CBLSSignature& sig)
CQuorumCPtr CSigningManager::SelectQuorumForSigning(Consensus::LLMQType llmqType, int signHeight, const uint256& selectionHash)
{
auto& llmqParams = Params().GetConsensus().llmqs.at(llmqType);
size_t poolSize = (size_t)llmqParams.signingActiveQuorumCount;
uint256 startBlock;
{
LOCK(cs_main);
if (signHeight > chainActive.Height()) {
return nullptr;
}
startBlock = chainActive[signHeight]->GetBlockHash();
}
auto quorums = quorumManager->ScanQuorums(llmqType, startBlock, poolSize);
if (quorums.empty()) {
return nullptr;
}
std::vector<std::pair<uint256, size_t>> scores;
scores.reserve(quorums.size());
for (size_t i = 0; i < quorums.size(); i++) {
CHashWriter h(SER_NETWORK, 0);
h << (uint8_t)llmqType;
h << quorums[i]->quorumHash;
h << selectionHash;
scores.emplace_back(h.GetHash(), i);
}
std::sort(scores.begin(), scores.end());
return quorums[scores.front().second];
}
bool CSigningManager::VerifyRecoveredSig(Consensus::LLMQType llmqType, int signedAtHeight, const uint256& id, const uint256& msgHash, const CBLSSignature& sig)
{
auto& llmqParams = Params().GetConsensus().llmqs.at(Params().GetConsensus().llmqTypeForChainLocks);
auto quorum = quorumManager->SelectQuorum(llmqParams.type, signedAtTip, id);
auto quorum = SelectQuorumForSigning(llmqParams.type, signedAtHeight, id);
if (!quorum) {
return false;
}

View File

@ -147,8 +147,10 @@ public:
bool HasRecoveredSigForSession(const uint256& signHash);
bool IsConflicting(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash);
CQuorumCPtr SelectQuorumForSigning(Consensus::LLMQType llmqType, int signHeight, const uint256& selectionHash);
// Verifies a recovered sig that was signed while the chain tip was at signedAtTip
bool VerifyRecoveredSig(Consensus::LLMQType llmqType, const uint256& signedAtTip, const uint256& id, const uint256& msgHash, const CBLSSignature& sig);
bool VerifyRecoveredSig(Consensus::LLMQType llmqType, int signedAtHeight, const uint256& id, const uint256& msgHash, const CBLSSignature& sig);
};
extern CSigningManager* quorumSigningManager;