PIVX Core  5.6.99
P2P Digital Currency
quorums_dkgsessionmgr.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2021 The Dash Core developers
2 // Copyright (c) 2022 The PIVX Core developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
7 
8 #include "chainparams.h"
10 #include "llmq/quorums_utils.h"
11 #include "spork.h"
12 #include "validation.h"
13 
14 namespace llmq
15 {
16 
17 std::unique_ptr<CDKGSessionManager> quorumDKGSessionManager{nullptr};
18 
19 static const std::string DB_VVEC = "qdkg_V";
20 static const std::string DB_SKCONTRIB = "qdkg_S";
21 
23  blsWorker(_blsWorker)
24 {
25  for (const auto& qt : Params().GetConsensus().llmqs) {
26  dkgSessionHandlers.emplace(std::piecewise_construct,
27  std::forward_as_tuple(qt.first),
28  std::forward_as_tuple(qt.second, blsWorker, *this));
29  }
30 }
31 
33 {
34  for (auto& it : dkgSessionHandlers) {
35  it.second.StartThread();
36  }
37 }
38 
40 {
41  for (auto& it : dkgSessionHandlers) {
42  it.second.StopThread();
43  }
44 }
45 
46 void CDKGSessionManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitialDownload)
47 {
48  CleanupCache();
49 
50  if (fInitialDownload)
51  return;
52  if (!deterministicMNManager->IsDIP3Enforced(pindexNew->nHeight))
53  return;
54 
55  LOCK(cs_main);
56 
57  for (auto& qt : dkgSessionHandlers) {
58  qt.second.UpdatedBlockTip(pindexNew);
59  }
60 }
61 
62 bool CDKGSessionManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv)
63 {
64  if (vRecv.empty()) {
65  return false;
66  }
67 
68  // peek into the message and see which LLMQType it is. First byte of all messages is always the LLMQType
69  Consensus::LLMQType llmqType = (Consensus::LLMQType)*vRecv.begin();
70  if (!dkgSessionHandlers.count(llmqType)) {
71  return false;
72  }
73 
74  dkgSessionHandlers.at(llmqType).ProcessMessage(pfrom, strCommand, vRecv);
75  return true;
76 }
77 
78 bool CDKGSessionManager::AlreadyHave(const CInv& inv) const
79 {
80  for (const auto& p : dkgSessionHandlers) {
81  auto& dkgType = p.second;
82  if (dkgType.pendingContributions.HasSeen(inv.hash)
83  || dkgType.pendingComplaints.HasSeen(inv.hash)
84  || dkgType.pendingJustifications.HasSeen(inv.hash)
85  || dkgType.pendingPrematureCommitments.HasSeen(inv.hash)) {
86  return true;
87  }
88  }
89  return false;
90 }
91 
93 {
94  for (const auto& p : dkgSessionHandlers) {
95  auto& dkgType = p.second;
96  LOCK2(dkgType.cs, dkgType.curSession->invCs);
97  if (dkgType.phase < QuorumPhase_Initialized || dkgType.phase > QuorumPhase_Contribute) {
98  continue;
99  }
100  auto it = dkgType.curSession->contributions.find(hash);
101  if (it != dkgType.curSession->contributions.end()) {
102  ret = it->second;
103  return true;
104  }
105  }
106  return false;
107 }
108 
110 {
111  for (const auto& p : dkgSessionHandlers) {
112  auto& dkgType = p.second;
113  LOCK2(dkgType.cs, dkgType.curSession->invCs);
114  if (dkgType.phase < QuorumPhase_Contribute || dkgType.phase > QuorumPhase_Complain) {
115  continue;
116  }
117  auto it = dkgType.curSession->complaints.find(hash);
118  if (it != dkgType.curSession->complaints.end()) {
119  ret = it->second;
120  return true;
121  }
122  }
123  return false;
124 }
125 
127 {
128  for (const auto& p : dkgSessionHandlers) {
129  auto& dkgType = p.second;
130  LOCK2(dkgType.cs, dkgType.curSession->invCs);
131  if (dkgType.phase < QuorumPhase_Complain || dkgType.phase > QuorumPhase_Justify) {
132  continue;
133  }
134  auto it = dkgType.curSession->justifications.find(hash);
135  if (it != dkgType.curSession->justifications.end()) {
136  ret = it->second;
137  return true;
138  }
139  }
140  return false;
141 }
142 
144 {
145  for (const auto& p : dkgSessionHandlers) {
146  auto& dkgType = p.second;
147  LOCK2(dkgType.cs, dkgType.curSession->invCs);
148  if (dkgType.phase < QuorumPhase_Justify || dkgType.phase > QuorumPhase_Commit) {
149  continue;
150  }
151  auto it = dkgType.curSession->prematureCommitments.find(hash);
152  if (it != dkgType.curSession->prematureCommitments.end() && dkgType.curSession->validCommitments.count(hash)) {
153  ret = it->second;
154  return true;
155  }
156  }
157  return false;
158 }
159 
161 {
162  llmqDb.Write(std::make_tuple(DB_VVEC, (uint8_t)llmqType, pindexQuorum->GetBlockHash(), proTxHash), *vvec);
163 }
164 
165 void CDKGSessionManager::WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const CBLSSecretKey& skContribution)
166 {
167  llmqDb.Write(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, pindexQuorum->GetBlockHash(), proTxHash), skContribution);
168 }
169 
170 bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const std::vector<bool>& validMembers, std::vector<uint16_t>& memberIndexesRet, std::vector<BLSVerificationVectorPtr>& vvecsRet, BLSSecretKeyVector& skContributionsRet)
171 {
172  auto members = deterministicMNManager->GetAllQuorumMembers(llmqType, pindexQuorum);
173 
174  memberIndexesRet.clear();
175  vvecsRet.clear();
176  skContributionsRet.clear();
177  memberIndexesRet.reserve(members.size());
178  vvecsRet.reserve(members.size());
179  skContributionsRet.reserve(members.size());
180  for (size_t i = 0; i < members.size(); i++) {
181  if (validMembers[i]) {
183  CBLSSecretKey skContribution;
184  if (!GetVerifiedContribution(llmqType, pindexQuorum, members[i]->proTxHash, vvec, skContribution)) {
185  return false;
186  }
187 
188  memberIndexesRet.emplace_back(i);
189  vvecsRet.emplace_back(vvec);
190  skContributionsRet.emplace_back(skContribution);
191  }
192  }
193  return true;
194 }
195 
197 {
198  const uint256& quorumHash = pindexQuorum->GetBlockHash();
200  ContributionsCacheKey cacheKey = {llmqType, quorumHash, proTxHash};
201  auto it = contributionsCache.find(cacheKey);
202  if (it != contributionsCache.end()) {
203  vvecRet = it->second.vvec;
204  skContributionRet = it->second.skContribution;
205  return true;
206  }
207 
209  BLSVerificationVectorPtr vvecPtr;
210  CBLSSecretKey skContribution;
211  if (llmqDb.Read(std::make_tuple(DB_VVEC, (uint8_t)llmqType, quorumHash, proTxHash), vvec)) {
212  vvecPtr = std::make_shared<BLSVerificationVector>(std::move(vvec));
213  }
214  llmqDb.Read(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, quorumHash, proTxHash), skContribution);
215 
216  it = contributionsCache.emplace(cacheKey, ContributionsCacheEntry{GetTimeMillis(), vvecPtr, skContribution}).first;
217 
218  vvecRet = it->second.vvec;
219  skContributionRet = it->second.skContribution;
220 
221  return true;
222 }
223 
225 {
227  auto curTime = GetTimeMillis();
228  for (auto it = contributionsCache.begin(); it != contributionsCache.end(); ) {
229  if (curTime - it->second.entryTime > MAX_CONTRIBUTION_CACHE_TIME) {
230  it = contributionsCache.erase(it);
231  } else {
232  ++it;
233  }
234  }
235 }
236 
237 }
std::vector< CBLSPublicKey > BLSVerificationVector
Definition: bls_wrapper.h:409
std::shared_ptr< BLSVerificationVector > BLSVerificationVectorPtr
Definition: bls_wrapper.h:415
std::vector< CBLSSecretKey > BLSSecretKeyVector
Definition: bls_wrapper.h:411
const CChainParams & Params()
Return the currently selected parameters.
const_iterator begin() const
Definition: streams.h:161
bool empty() const
Definition: streams.h:166
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
uint256 GetBlockHash() const
Definition: chain.h:215
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:151
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:260
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:284
inv message data
Definition: protocol.h:466
uint256 hash
Definition: protocol.h:480
Information about a peer.
Definition: net.h:669
bool AlreadyHave(const CInv &inv) const
bool GetVerifiedContribution(Consensus::LLMQType llmqType, const CBlockIndex *pindexQuorum, const uint256 &proTxHash, BLSVerificationVectorPtr &vvecRet, CBLSSecretKey &skContributionRet)
std::map< ContributionsCacheKey, ContributionsCacheEntry > contributionsCache
std::map< Consensus::LLMQType, CDKGSessionHandler > dkgSessionHandlers
static const int64_t MAX_CONTRIBUTION_CACHE_TIME
bool GetJustification(const uint256 &hash, CDKGJustification &ret) const
bool GetPrematureCommitment(const uint256 &hash, CDKGPrematureCommitment &ret) const
CDKGSessionManager(CDBWrapper &_evoDb, CBLSWorker &_blsWorker)
bool GetContribution(const uint256 &hash, CDKGContribution &ret) const
void WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const CBlockIndex *pindexQuorum, const uint256 &proTxHash, const CBLSSecretKey &skContribution)
void WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const CBlockIndex *pindexQuorum, const uint256 &proTxHash, const BLSVerificationVectorPtr &vvec)
void UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitialDownload)
bool ProcessMessage(CNode *pfrom, const std::string &strCommand, CDataStream &vRecv)
bool GetVerifiedContributions(Consensus::LLMQType llmqType, const CBlockIndex *pindexQuorum, const std::vector< bool > &validMembers, std::vector< uint16_t > &memberIndexesRet, std::vector< BLSVerificationVectorPtr > &vvecsRet, BLSSecretKeyVector &skContributionsRet)
bool GetComplaint(const uint256 &hash, CDKGComplaint &ret) const
256-bit opaque blob.
Definition: uint256.h:138
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
@ LOCK
Definition: lockunlock.h:16
LLMQType
Definition: params.h:90
Definition: quorums.cpp:26
std::unique_ptr< CDKGSessionManager > quorumDKGSessionManager
CBLSWorker * blsWorker
CDBWrapper * llmqDb
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
@ proTxHash
Definition: rpcevo.cpp:50
#define LOCK2(cs1, cs2)
Definition: sync.h:221
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: utiltime.cpp:61