Line data Source code
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 :
6 : #include "llmq/quorums_dkgsessionmgr.h"
7 :
8 : #include "chainparams.h"
9 : #include "llmq/quorums_blockprocessor.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 :
22 475 : CDKGSessionManager::CDKGSessionManager(CDBWrapper& _llmqDb, CBLSWorker& _blsWorker) : llmqDb(_llmqDb),
23 475 : blsWorker(_blsWorker)
24 : {
25 1107 : for (const auto& qt : Params().GetConsensus().llmqs) {
26 632 : dkgSessionHandlers.emplace(std::piecewise_construct,
27 632 : std::forward_as_tuple(qt.first),
28 632 : std::forward_as_tuple(qt.second, blsWorker, *this));
29 : }
30 475 : }
31 :
32 347 : void CDKGSessionManager::StartThreads()
33 : {
34 694 : for (auto& it : dkgSessionHandlers) {
35 347 : it.second.StartThread();
36 : }
37 347 : }
38 :
39 357 : void CDKGSessionManager::StopThreads()
40 : {
41 714 : for (auto& it : dkgSessionHandlers) {
42 357 : it.second.StopThread();
43 : }
44 357 : }
45 :
46 41720 : void CDKGSessionManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitialDownload)
47 : {
48 41720 : CleanupCache();
49 :
50 41720 : if (fInitialDownload)
51 32940 : return;
52 40938 : if (!deterministicMNManager->IsDIP3Enforced(pindexNew->nHeight))
53 : return;
54 :
55 17560 : LOCK(cs_main);
56 :
57 17560 : for (auto& qt : dkgSessionHandlers) {
58 8780 : qt.second.UpdatedBlockTip(pindexNew);
59 : }
60 : }
61 :
62 264 : bool CDKGSessionManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv)
63 : {
64 264 : 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 264 : Consensus::LLMQType llmqType = (Consensus::LLMQType)*vRecv.begin();
70 264 : if (!dkgSessionHandlers.count(llmqType)) {
71 0 : return false;
72 : }
73 :
74 264 : dkgSessionHandlers.at(llmqType).ProcessMessage(pfrom, strCommand, vRecv);
75 : return true;
76 : }
77 :
78 1036 : bool CDKGSessionManager::AlreadyHave(const CInv& inv) const
79 : {
80 1586 : for (const auto& p : dkgSessionHandlers) {
81 1036 : auto& dkgType = p.second;
82 1036 : if (dkgType.pendingContributions.HasSeen(inv.hash)
83 804 : || dkgType.pendingComplaints.HasSeen(inv.hash)
84 760 : || dkgType.pendingJustifications.HasSeen(inv.hash)
85 1780 : || dkgType.pendingPrematureCommitments.HasSeen(inv.hash)) {
86 486 : return true;
87 : }
88 : }
89 550 : return false;
90 : }
91 :
92 124 : bool CDKGSessionManager::GetContribution(const uint256& hash, CDKGContribution& ret) const
93 : {
94 124 : for (const auto& p : dkgSessionHandlers) {
95 124 : auto& dkgType = p.second;
96 124 : LOCK2(dkgType.cs, dkgType.curSession->invCs);
97 124 : if (dkgType.phase < QuorumPhase_Initialized || dkgType.phase > QuorumPhase_Contribute) {
98 0 : continue;
99 : }
100 124 : auto it = dkgType.curSession->contributions.find(hash);
101 124 : if (it != dkgType.curSession->contributions.end()) {
102 124 : ret = it->second;
103 248 : return true;
104 : }
105 : }
106 0 : return false;
107 : }
108 :
109 26 : bool CDKGSessionManager::GetComplaint(const uint256& hash, CDKGComplaint& ret) const
110 : {
111 26 : for (const auto& p : dkgSessionHandlers) {
112 26 : auto& dkgType = p.second;
113 26 : LOCK2(dkgType.cs, dkgType.curSession->invCs);
114 26 : if (dkgType.phase < QuorumPhase_Contribute || dkgType.phase > QuorumPhase_Complain) {
115 0 : continue;
116 : }
117 26 : auto it = dkgType.curSession->complaints.find(hash);
118 26 : if (it != dkgType.curSession->complaints.end()) {
119 26 : ret = it->second;
120 52 : return true;
121 : }
122 : }
123 0 : return false;
124 : }
125 :
126 8 : bool CDKGSessionManager::GetJustification(const uint256& hash, CDKGJustification& ret) const
127 : {
128 8 : for (const auto& p : dkgSessionHandlers) {
129 8 : auto& dkgType = p.second;
130 8 : LOCK2(dkgType.cs, dkgType.curSession->invCs);
131 8 : if (dkgType.phase < QuorumPhase_Complain || dkgType.phase > QuorumPhase_Justify) {
132 0 : continue;
133 : }
134 8 : auto it = dkgType.curSession->justifications.find(hash);
135 8 : if (it != dkgType.curSession->justifications.end()) {
136 8 : ret = it->second;
137 16 : return true;
138 : }
139 : }
140 0 : return false;
141 : }
142 :
143 106 : bool CDKGSessionManager::GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const
144 : {
145 106 : for (const auto& p : dkgSessionHandlers) {
146 106 : auto& dkgType = p.second;
147 106 : LOCK2(dkgType.cs, dkgType.curSession->invCs);
148 106 : if (dkgType.phase < QuorumPhase_Justify || dkgType.phase > QuorumPhase_Commit) {
149 0 : continue;
150 : }
151 106 : auto it = dkgType.curSession->prematureCommitments.find(hash);
152 106 : if (it != dkgType.curSession->prematureCommitments.end() && dkgType.curSession->validCommitments.count(hash)) {
153 106 : ret = it->second;
154 212 : return true;
155 : }
156 : }
157 0 : return false;
158 : }
159 :
160 189 : void CDKGSessionManager::WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const BLSVerificationVectorPtr& vvec)
161 : {
162 378 : llmqDb.Write(std::make_tuple(DB_VVEC, (uint8_t)llmqType, pindexQuorum->GetBlockHash(), proTxHash), *vvec);
163 189 : }
164 :
165 176 : void CDKGSessionManager::WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const CBLSSecretKey& skContribution)
166 : {
167 352 : llmqDb.Write(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, pindexQuorum->GetBlockHash(), proTxHash), skContribution);
168 176 : }
169 :
170 372 : 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 744 : auto members = deterministicMNManager->GetAllQuorumMembers(llmqType, pindexQuorum);
173 :
174 372 : memberIndexesRet.clear();
175 372 : vvecsRet.clear();
176 372 : skContributionsRet.clear();
177 372 : memberIndexesRet.reserve(members.size());
178 372 : vvecsRet.reserve(members.size());
179 372 : skContributionsRet.reserve(members.size());
180 1488 : for (size_t i = 0; i < members.size(); i++) {
181 1116 : if (validMembers[i]) {
182 1018 : BLSVerificationVectorPtr vvec;
183 2036 : CBLSSecretKey skContribution;
184 1018 : if (!GetVerifiedContribution(llmqType, pindexQuorum, members[i]->proTxHash, vvec, skContribution)) {
185 0 : return false;
186 : }
187 :
188 1018 : memberIndexesRet.emplace_back(i);
189 1018 : vvecsRet.emplace_back(vvec);
190 1018 : skContributionsRet.emplace_back(skContribution);
191 : }
192 : }
193 372 : return true;
194 : }
195 :
196 1018 : bool CDKGSessionManager::GetVerifiedContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, BLSVerificationVectorPtr& vvecRet, CBLSSecretKey& skContributionRet)
197 : {
198 1018 : const uint256& quorumHash = pindexQuorum->GetBlockHash();
199 2036 : LOCK(contributionsCacheCs);
200 1018 : ContributionsCacheKey cacheKey = {llmqType, quorumHash, proTxHash};
201 1018 : auto it = contributionsCache.find(cacheKey);
202 1018 : if (it != contributionsCache.end()) {
203 623 : vvecRet = it->second.vvec;
204 623 : skContributionRet = it->second.skContribution;
205 623 : return true;
206 : }
207 :
208 1413 : BLSVerificationVector vvec;
209 395 : BLSVerificationVectorPtr vvecPtr;
210 790 : CBLSSecretKey skContribution;
211 790 : if (llmqDb.Read(std::make_tuple(DB_VVEC, (uint8_t)llmqType, quorumHash, proTxHash), vvec)) {
212 330 : vvecPtr = std::make_shared<BLSVerificationVector>(std::move(vvec));
213 : }
214 790 : llmqDb.Read(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, quorumHash, proTxHash), skContribution);
215 :
216 395 : it = contributionsCache.emplace(cacheKey, ContributionsCacheEntry{GetTimeMillis(), vvecPtr, skContribution}).first;
217 :
218 395 : vvecRet = it->second.vvec;
219 395 : skContributionRet = it->second.skContribution;
220 :
221 395 : return true;
222 : }
223 :
224 41720 : void CDKGSessionManager::CleanupCache()
225 : {
226 41720 : LOCK(contributionsCacheCs);
227 41720 : auto curTime = GetTimeMillis();
228 41720 : for (auto it = contributionsCache.begin(); it != contributionsCache.end(); ) {
229 28830 : if (curTime - it->second.entryTime > MAX_CONTRIBUTION_CACHE_TIME) {
230 113 : it = contributionsCache.erase(it);
231 : } else {
232 99267 : ++it;
233 : }
234 : }
235 41720 : }
236 :
237 : }
|