|
4 | 4 |
|
5 | 5 | #include <evo/simplifiedmns.h> |
6 | 6 |
|
7 | | -#include <core_io.h> |
8 | | -#include <deploymentstatus.h> |
9 | | -#include <evo/cbtx.h> |
| 7 | +#include <consensus/merkle.h> |
10 | 8 | #include <evo/deterministicmns.h> |
11 | 9 | #include <evo/netinfo.h> |
12 | | -#include <evo/specialtx.h> |
13 | | -#include <llmq/blockprocessor.h> |
14 | | -#include <llmq/commitment.h> |
15 | | -#include <llmq/quorums.h> |
16 | | -#include <node/blockstorage.h> |
17 | | - |
| 10 | +#include <key_io.h> |
| 11 | +#include <logging.h> |
18 | 12 | #include <pubkey.h> |
19 | 13 | #include <serialize.h> |
20 | | - |
21 | | -#include <base58.h> |
22 | | -#include <chainparams.h> |
23 | | -#include <consensus/merkle.h> |
24 | 14 | #include <univalue.h> |
25 | | -#include <validation.h> |
26 | | -#include <key_io.h> |
27 | 15 | #include <util/underlying.h> |
28 | | -#include <util/enumerate.h> |
29 | | - |
30 | | -using node::ReadBlockFromDisk; |
| 16 | +#include <version.h> |
31 | 17 |
|
32 | 18 | CSimplifiedMNListEntry::CSimplifiedMNListEntry(const CDeterministicMN& dmn) : |
33 | 19 | proRegTxHash(dmn.proTxHash), |
@@ -118,202 +104,6 @@ bool CSimplifiedMNList::operator==(const CSimplifiedMNList& rhs) const |
118 | 104 | ); |
119 | 105 | } |
120 | 106 |
|
121 | | -CSimplifiedMNListDiff::CSimplifiedMNListDiff() = default; |
122 | | - |
123 | | -CSimplifiedMNListDiff::~CSimplifiedMNListDiff() = default; |
124 | | - |
125 | | -bool CSimplifiedMNListDiff::BuildQuorumsDiff(const CBlockIndex* baseBlockIndex, const CBlockIndex* blockIndex, |
126 | | - const llmq::CQuorumBlockProcessor& quorum_block_processor) |
127 | | -{ |
128 | | - auto baseQuorums = quorum_block_processor.GetMinedAndActiveCommitmentsUntilBlock(baseBlockIndex); |
129 | | - auto quorums = quorum_block_processor.GetMinedAndActiveCommitmentsUntilBlock(blockIndex); |
130 | | - |
131 | | - std::set<std::pair<Consensus::LLMQType, uint256>> baseQuorumHashes; |
132 | | - std::set<std::pair<Consensus::LLMQType, uint256>> quorumHashes; |
133 | | - for (const auto& [llmqType, vecBlockIndex] : baseQuorums) { |
134 | | - for (const auto& blockindex : vecBlockIndex) { |
135 | | - baseQuorumHashes.emplace(llmqType, blockindex->GetBlockHash()); |
136 | | - } |
137 | | - } |
138 | | - for (const auto& [llmqType, vecBlockIndex] : quorums) { |
139 | | - for (const auto& blockindex : vecBlockIndex) { |
140 | | - quorumHashes.emplace(llmqType, blockindex->GetBlockHash()); |
141 | | - } |
142 | | - } |
143 | | - |
144 | | - for (const auto& p : baseQuorumHashes) { |
145 | | - if (!quorumHashes.count(p)) { |
146 | | - deletedQuorums.emplace_back((uint8_t)p.first, p.second); |
147 | | - } |
148 | | - } |
149 | | - for (const auto& p : quorumHashes) { |
150 | | - const auto& [llmqType, hash] = p; |
151 | | - if (!baseQuorumHashes.count(p)) { |
152 | | - uint256 minedBlockHash; |
153 | | - llmq::CFinalCommitmentPtr qc = quorum_block_processor.GetMinedCommitment(llmqType, hash, minedBlockHash); |
154 | | - if (qc == nullptr) { |
155 | | - return false; |
156 | | - } |
157 | | - newQuorums.emplace_back(*qc); |
158 | | - } |
159 | | - } |
160 | | - |
161 | | - return true; |
162 | | -} |
163 | | - |
164 | | -bool CSimplifiedMNListDiff::BuildQuorumChainlockInfo(const llmq::CQuorumManager& qman, const CBlockIndex* blockIndex) |
165 | | -{ |
166 | | - // Group quorums (indexes corresponding to entries of newQuorums) per CBlockIndex containing the expected CL signature in CbTx. |
167 | | - // We want to avoid to load CbTx now, as more than one quorum will target the same block: hence we want to load CbTxs once per block (heavy operation). |
168 | | - std::multimap<const CBlockIndex*, uint16_t> workBaseBlockIndexMap; |
169 | | - |
170 | | - for (const auto [idx, e] : enumerate(newQuorums)) { |
171 | | - // We assume that we have on hand, quorums that correspond to the hashes queried. |
172 | | - // If we cannot find them, something must have gone wrong and we should cease trying |
173 | | - // to build any further. |
174 | | - auto quorum = qman.GetQuorum(e.llmqType, e.quorumHash); |
175 | | - if (!quorum) { |
176 | | - LogPrintf("%s: ERROR! Unexpected missing quorum with llmqType=%d, quorumHash=%s\n", __func__, |
177 | | - ToUnderlying(e.llmqType), e.quorumHash.ToString()); |
178 | | - return false; |
179 | | - } |
180 | | - |
181 | | - // In case of rotation, all rotated quorums rely on the CL sig expected in the cycleBlock (the block of the first DKG) - 8 |
182 | | - // In case of non-rotation, quorums rely on the CL sig expected in the block of the DKG - 8 |
183 | | - const CBlockIndex* pWorkBaseBlockIndex = |
184 | | - blockIndex->GetAncestor(quorum->m_quorum_base_block_index->nHeight - quorum->qc->quorumIndex - 8); |
185 | | - |
186 | | - workBaseBlockIndexMap.insert(std::make_pair(pWorkBaseBlockIndex, idx)); |
187 | | - } |
188 | | - |
189 | | - for (auto it = workBaseBlockIndexMap.begin(); it != workBaseBlockIndexMap.end();) { |
190 | | - // Process each key (CBlockIndex containing the expected CL signature in CbTx) of the std::multimap once |
191 | | - const CBlockIndex* pWorkBaseBlockIndex = it->first; |
192 | | - const auto cbcl = GetNonNullCoinbaseChainlock(pWorkBaseBlockIndex); |
193 | | - CBLSSignature sig; |
194 | | - if (cbcl.has_value()) { |
195 | | - sig = cbcl.value().first; |
196 | | - } |
197 | | - // Get the range of indexes (values) for the current key and merge them into a single std::set |
198 | | - const auto [it_begin, it_end] = workBaseBlockIndexMap.equal_range(it->first); |
199 | | - std::set<uint16_t> idx_set; |
200 | | - std::transform(it_begin, it_end, std::inserter(idx_set, idx_set.end()), [](const auto& pair) { return pair.second; }); |
201 | | - // Advance the iterator to the next key |
202 | | - it = it_end; |
203 | | - |
204 | | - // Different CBlockIndex can contain the same CL sig in CbTx (both non-null or null during the first blocks after v20 activation) |
205 | | - // Hence, we need to merge the std::set if another std::set already exists for the same sig. |
206 | | - if (auto [it_sig, inserted] = quorumsCLSigs.insert({sig, idx_set}); !inserted) { |
207 | | - it_sig->second.insert(idx_set.begin(), idx_set.end()); |
208 | | - } |
209 | | - } |
210 | | - |
211 | | - return true; |
212 | | -} |
213 | | - |
214 | | -CSimplifiedMNListDiff BuildSimplifiedDiff(const CDeterministicMNList& from, const CDeterministicMNList& to, bool extended) |
215 | | -{ |
216 | | - CSimplifiedMNListDiff diffRet; |
217 | | - diffRet.baseBlockHash = from.GetBlockHash(); |
218 | | - diffRet.blockHash = to.GetBlockHash(); |
219 | | - |
220 | | - to.ForEachMN(false, [&](const auto& toPtr) { |
221 | | - auto fromPtr = from.GetMN(toPtr.proTxHash); |
222 | | - if (fromPtr == nullptr) { |
223 | | - CSimplifiedMNListEntry sme(toPtr); |
224 | | - diffRet.mnList.push_back(std::move(sme)); |
225 | | - } else { |
226 | | - CSimplifiedMNListEntry sme1(toPtr); |
227 | | - CSimplifiedMNListEntry sme2(*fromPtr); |
228 | | - if ((sme1 != sme2) || |
229 | | - (extended && (sme1.scriptPayout != sme2.scriptPayout || sme1.scriptOperatorPayout != sme2.scriptOperatorPayout))) { |
230 | | - diffRet.mnList.push_back(std::move(sme1)); |
231 | | - } |
232 | | - } |
233 | | - }); |
234 | | - |
235 | | - from.ForEachMN(false, [&](auto& fromPtr) { |
236 | | - auto toPtr = to.GetMN(fromPtr.proTxHash); |
237 | | - if (toPtr == nullptr) { |
238 | | - diffRet.deletedMNs.emplace_back(fromPtr.proTxHash); |
239 | | - } |
240 | | - }); |
241 | | - |
242 | | - return diffRet; |
243 | | -} |
244 | | - |
245 | | -bool BuildSimplifiedMNListDiff(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const llmq::CQuorumBlockProcessor& qblockman, |
246 | | - const llmq::CQuorumManager& qman, const uint256& baseBlockHash, const uint256& blockHash, |
247 | | - CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet, bool extended) |
248 | | -{ |
249 | | - AssertLockHeld(::cs_main); |
250 | | - mnListDiffRet = CSimplifiedMNListDiff(); |
251 | | - |
252 | | - const CBlockIndex* baseBlockIndex = chainman.ActiveChain().Genesis(); |
253 | | - if (!baseBlockHash.IsNull()) { |
254 | | - baseBlockIndex = chainman.m_blockman.LookupBlockIndex(baseBlockHash); |
255 | | - if (!baseBlockIndex) { |
256 | | - errorRet = strprintf("block %s not found", baseBlockHash.ToString()); |
257 | | - return false; |
258 | | - } |
259 | | - } |
260 | | - |
261 | | - const CBlockIndex* blockIndex = chainman.m_blockman.LookupBlockIndex(blockHash); |
262 | | - if (!blockIndex) { |
263 | | - errorRet = strprintf("block %s not found", blockHash.ToString()); |
264 | | - return false; |
265 | | - } |
266 | | - |
267 | | - if (!chainman.ActiveChain().Contains(baseBlockIndex) || !chainman.ActiveChain().Contains(blockIndex)) { |
268 | | - errorRet = strprintf("block %s and %s are not in the same chain", baseBlockHash.ToString(), blockHash.ToString()); |
269 | | - return false; |
270 | | - } |
271 | | - if (baseBlockIndex->nHeight > blockIndex->nHeight) { |
272 | | - errorRet = strprintf("base block %s is higher then block %s", baseBlockHash.ToString(), blockHash.ToString()); |
273 | | - return false; |
274 | | - } |
275 | | - |
276 | | - auto baseDmnList = dmnman.GetListForBlock(baseBlockIndex); |
277 | | - auto dmnList = dmnman.GetListForBlock(blockIndex); |
278 | | - mnListDiffRet = BuildSimplifiedDiff(baseDmnList, dmnList, extended); |
279 | | - |
280 | | - // We need to return the value that was provided by the other peer as it otherwise won't be able to recognize the |
281 | | - // response. This will usually be identical to the block found in baseBlockIndex. The only difference is when a |
282 | | - // null block hash was provided to get the diff from the genesis block. |
283 | | - mnListDiffRet.baseBlockHash = baseBlockHash; |
284 | | - |
285 | | - if (!mnListDiffRet.BuildQuorumsDiff(baseBlockIndex, blockIndex, qblockman)) { |
286 | | - errorRet = strprintf("failed to build quorums diff"); |
287 | | - return false; |
288 | | - } |
289 | | - |
290 | | - if (DeploymentActiveAfter(blockIndex, Params().GetConsensus(), Consensus::DEPLOYMENT_V20)) { |
291 | | - if (!mnListDiffRet.BuildQuorumChainlockInfo(qman, blockIndex)) { |
292 | | - errorRet = strprintf("failed to build quorum chainlock info"); |
293 | | - return false; |
294 | | - } |
295 | | - } |
296 | | - |
297 | | - // TODO store coinbase TX in CBlockIndex |
298 | | - CBlock block; |
299 | | - if (!ReadBlockFromDisk(block, blockIndex, Params().GetConsensus())) { |
300 | | - errorRet = strprintf("failed to read block %s from disk", blockHash.ToString()); |
301 | | - return false; |
302 | | - } |
303 | | - |
304 | | - mnListDiffRet.cbTx = block.vtx[0]; |
305 | | - |
306 | | - std::vector<uint256> vHashes; |
307 | | - std::vector<bool> vMatch(block.vtx.size(), false); |
308 | | - for (const auto& tx : block.vtx) { |
309 | | - vHashes.emplace_back(tx->GetHash()); |
310 | | - } |
311 | | - vMatch[0] = true; // only coinbase matches |
312 | | - mnListDiffRet.cbTxMerkleTree = CPartialMerkleTree(vHashes, vMatch); |
313 | | - |
314 | | - return true; |
315 | | -} |
316 | | - |
317 | 107 | bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, CSimplifiedMNList&& sml, BlockValidationState& state) |
318 | 108 | { |
319 | 109 | try { |
|
0 commit comments