Skip to content

Commit c2e053f

Browse files
committed
refactor: move diff related code from evo/simplifiedmns to new module evo/smldiff
This commit is to prevent multiple circular dependencies over llmq/ module because evo/simplifiedmns depends on llmq/blockprocessor, llmq/commitment, llmq/quorums, but they includes evo/deterministicmns. Once evo/deterministicmns knows about simplifiedmns it causes 10 more loops over llmq/* and evo/deterministicmns
1 parent e8949c8 commit c2e053f

File tree

11 files changed

+331
-290
lines changed

11 files changed

+331
-290
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ BITCOIN_CORE_H = \
195195
evo/netinfo.h \
196196
evo/providertx.h \
197197
evo/simplifiedmns.h \
198+
evo/smldiff.h \
198199
evo/specialtx.h \
199200
evo/specialtxman.h \
200201
dsnotificationinterface.h \
@@ -472,6 +473,7 @@ libbitcoin_node_a_SOURCES = \
472473
evo/mnhftx.cpp \
473474
evo/providertx.cpp \
474475
evo/simplifiedmns.cpp \
476+
evo/smldiff.cpp \
475477
evo/specialtx.cpp \
476478
evo/specialtxman.cpp \
477479
flatfile.cpp \

src/evo/core_write.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <evo/netinfo.h>
1010
#include <evo/providertx.h>
1111
#include <evo/simplifiedmns.h>
12+
#include <evo/smldiff.h>
1213
#include <llmq/commitment.h>
1314

1415
#include <univalue.h>

src/evo/simplifiedmns.cpp

Lines changed: 4 additions & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,16 @@
44

55
#include <evo/simplifiedmns.h>
66

7-
#include <core_io.h>
8-
#include <deploymentstatus.h>
9-
#include <evo/cbtx.h>
7+
#include <consensus/merkle.h>
108
#include <evo/deterministicmns.h>
119
#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>
1812
#include <pubkey.h>
1913
#include <serialize.h>
20-
21-
#include <base58.h>
22-
#include <chainparams.h>
23-
#include <consensus/merkle.h>
2414
#include <univalue.h>
25-
#include <validation.h>
26-
#include <key_io.h>
2715
#include <util/underlying.h>
28-
#include <util/enumerate.h>
29-
30-
using node::ReadBlockFromDisk;
16+
#include <version.h>
3117

3218
CSimplifiedMNListEntry::CSimplifiedMNListEntry(const CDeterministicMN& dmn) :
3319
proRegTxHash(dmn.proTxHash),
@@ -118,202 +104,6 @@ bool CSimplifiedMNList::operator==(const CSimplifiedMNList& rhs) const
118104
);
119105
}
120106

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-
317107
bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, CSimplifiedMNList&& sml, BlockValidationState& state)
318108
{
319109
try {

src/evo/simplifiedmns.h

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,13 @@
1212
#include <merkleblock.h>
1313
#include <netaddress.h>
1414
#include <pubkey.h>
15-
#include <sync.h>
16-
#include <threadsafety.h>
1715
#include <util/pointer.h>
1816

1917
class UniValue;
20-
class CBlockIndex;
2118
class CDeterministicMN;
2219
class CDeterministicMNList;
23-
class CDeterministicMNManager;
2420
class ChainstateManager;
2521

26-
extern RecursiveMutex cs_main;
27-
2822
namespace llmq {
2923
class CFinalCommitment;
3024
class CQuorumBlockProcessor;
@@ -116,71 +110,6 @@ class CSimplifiedMNList
116110
bool operator==(const CSimplifiedMNList& rhs) const;
117111
};
118112

119-
/// P2P messages
120-
121-
class CGetSimplifiedMNListDiff
122-
{
123-
public:
124-
uint256 baseBlockHash;
125-
uint256 blockHash;
126-
127-
SERIALIZE_METHODS(CGetSimplifiedMNListDiff, obj)
128-
{
129-
READWRITE(obj.baseBlockHash, obj.blockHash);
130-
}
131-
};
132-
133-
class CSimplifiedMNListDiff
134-
{
135-
public:
136-
static constexpr uint16_t CURRENT_VERSION = 1;
137-
138-
uint256 baseBlockHash;
139-
uint256 blockHash;
140-
CPartialMerkleTree cbTxMerkleTree;
141-
CTransactionRef cbTx;
142-
std::vector<uint256> deletedMNs;
143-
std::vector<CSimplifiedMNListEntry> mnList;
144-
uint16_t nVersion{CURRENT_VERSION};
145-
146-
std::vector<std::pair<uint8_t, uint256>> deletedQuorums; // p<LLMQType, quorumHash>
147-
std::vector<llmq::CFinalCommitment> newQuorums;
148-
149-
// Map of Chainlock Signature used for shuffling per set of quorums
150-
// The set of quorums is the set of indexes corresponding to entries in newQuorums
151-
std::map<CBLSSignature, std::set<uint16_t>> quorumsCLSigs;
152-
153-
SERIALIZE_METHODS(CSimplifiedMNListDiff, obj)
154-
{
155-
if ((s.GetType() & SER_NETWORK) && s.GetVersion() >= MNLISTDIFF_VERSION_ORDER) {
156-
READWRITE(obj.nVersion);
157-
}
158-
READWRITE(obj.baseBlockHash, obj.blockHash, obj.cbTxMerkleTree, obj.cbTx);
159-
if ((s.GetType() & SER_NETWORK) && s.GetVersion() >= BLS_SCHEME_PROTO_VERSION && s.GetVersion() < MNLISTDIFF_VERSION_ORDER) {
160-
READWRITE(obj.nVersion);
161-
}
162-
READWRITE(obj.deletedMNs, obj.mnList);
163-
READWRITE(obj.deletedQuorums, obj.newQuorums);
164-
if ((s.GetType() & SER_NETWORK) && s.GetVersion() >= MNLISTDIFF_CHAINLOCKS_PROTO_VERSION) {
165-
READWRITE(obj.quorumsCLSigs);
166-
}
167-
}
168-
169-
CSimplifiedMNListDiff();
170-
~CSimplifiedMNListDiff();
171-
172-
bool BuildQuorumsDiff(const CBlockIndex* baseBlockIndex, const CBlockIndex* blockIndex,
173-
const llmq::CQuorumBlockProcessor& quorum_block_processor);
174-
bool BuildQuorumChainlockInfo(const llmq::CQuorumManager& qman, const CBlockIndex* blockIndex);
175-
176-
[[nodiscard]] UniValue ToJson(bool extended = false) const;
177-
};
178-
179-
bool BuildSimplifiedMNListDiff(CDeterministicMNManager& dmnman, const ChainstateManager& chainman,
180-
const llmq::CQuorumBlockProcessor& qblockman, const llmq::CQuorumManager& qman,
181-
const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet,
182-
std::string& errorRet, bool extended = false) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
183-
184113
bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, CSimplifiedMNList&& sml, BlockValidationState& state);
185114

186115
#endif // BITCOIN_EVO_SIMPLIFIEDMNS_H

0 commit comments

Comments
 (0)