Line data Source code
1 : // Copyright (c) 2017-2025 The Dash Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include <evo/simplifiedmns.h>
6 :
7 : #include <evo/netinfo.h>
8 : #include <util/std23.h>
9 :
10 : #include <clientversion.h>
11 : #include <consensus/merkle.h>
12 : #include <key_io.h>
13 : #include <logging.h>
14 : #include <serialize.h>
15 : #include <sync.h>
16 : #include <util/time.h>
17 : #include <version.h>
18 :
19 : #include <univalue.h>
20 :
21 34318 : CSimplifiedMNListEntry::CSimplifiedMNListEntry(const uint256& proreg_tx_hash, const uint256& confirmed_hash,
22 : const std::shared_ptr<NetInfoInterface>& net_info,
23 : const CBLSLazyPublicKey& pubkey_operator, const CKeyID& keyid_voting,
24 : bool is_valid, uint16_t platform_http_port,
25 : const uint160& platform_node_id, const CScript& script_payout,
26 : const CScript& script_operator_payout, uint16_t version, MnType type) :
27 17159 : proRegTxHash(proreg_tx_hash),
28 17159 : confirmedHash(confirmed_hash),
29 17159 : netInfo(net_info),
30 17159 : pubKeyOperator(pubkey_operator),
31 17159 : keyIDVoting(keyid_voting),
32 17159 : isValid(is_valid),
33 17159 : platformHTTPPort(platform_http_port),
34 17159 : platformNodeID(platform_node_id),
35 17159 : scriptPayout(script_payout),
36 17159 : scriptOperatorPayout(script_operator_payout),
37 17159 : nVersion(version),
38 17159 : nType(type)
39 17159 : {
40 34318 : }
41 :
42 408 : uint256 CSimplifiedMNListEntry::CalcHash() const
43 : {
44 408 : CHashWriter hw(SER_GETHASH, CLIENT_VERSION);
45 408 : hw << *this;
46 408 : return hw.GetHash();
47 : }
48 :
49 0 : std::string CSimplifiedMNListEntry::ToString() const
50 : {
51 0 : CTxDestination dest;
52 0 : std::string payoutAddress = "unknown";
53 0 : std::string operatorPayoutAddress = "none";
54 0 : if (ExtractDestination(scriptPayout, dest)) {
55 0 : payoutAddress = EncodeDestination(dest);
56 0 : }
57 0 : if (ExtractDestination(scriptOperatorPayout, dest)) {
58 0 : operatorPayoutAddress = EncodeDestination(dest);
59 0 : }
60 :
61 0 : return strprintf("CSimplifiedMNListEntry(nVersion=%d, nType=%d, proRegTxHash=%s, confirmedHash=%s, netInfo=%s, "
62 : "pubKeyOperator=%s, votingAddress=%s, isValid=%d, payoutAddress=%s, operatorPayoutAddress=%s, "
63 : "platformNodeID=%s%s)\n",
64 0 : nVersion, std23::to_underlying(nType), proRegTxHash.ToString(), confirmedHash.ToString(),
65 0 : netInfo->ToString(), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), isValid,
66 0 : payoutAddress, operatorPayoutAddress, platformNodeID.ToString(),
67 0 : (nVersion >= ProTxVersion::ExtAddr ? "" : strprintf(", platformHTTPPort=%d", platformHTTPPort)));
68 0 : }
69 :
70 418 : CSimplifiedMNList::CSimplifiedMNList(std::vector<std::unique_ptr<CSimplifiedMNListEntry>>&& smlEntries)
71 209 : {
72 209 : mnList = std::move(smlEntries);
73 :
74 2265 : std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr<CSimplifiedMNListEntry>& a, const std::unique_ptr<CSimplifiedMNListEntry>& b) {
75 2056 : return a->proRegTxHash.Compare(b->proRegTxHash) < 0;
76 : });
77 418 : }
78 :
79 59 : uint256 CSimplifiedMNList::CalcMerkleRoot(bool* pmutated) const
80 : {
81 59 : std::vector<uint256> leaves;
82 59 : leaves.reserve(mnList.size());
83 452 : for (const auto& e : mnList) {
84 393 : leaves.emplace_back(e->CalcHash());
85 : }
86 59 : return ComputeMerkleRoot(leaves, pmutated);
87 59 : }
88 :
89 36470 : bool CSimplifiedMNList::operator==(const CSimplifiedMNList& rhs) const
90 : {
91 72911 : return mnList.size() == rhs.mnList.size() &&
92 36441 : std::equal(mnList.begin(), mnList.end(), rhs.mnList.begin(),
93 14041 : [](const std::unique_ptr<CSimplifiedMNListEntry>& left, const std::unique_ptr<CSimplifiedMNListEntry>& right)
94 : {
95 14041 : return *left == *right;
96 : }
97 : );
98 : }
99 :
100 36470 : bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, gsl::not_null<std::shared_ptr<const CSimplifiedMNList>> sml,
101 : BlockValidationState& state)
102 : {
103 : try {
104 : static std::atomic<int64_t> nTimeMerkle = 0;
105 :
106 36470 : int64_t nTime1 = GetTimeMicros();
107 :
108 36470 : static Mutex cached_mutex;
109 36473 : static gsl::not_null<std::shared_ptr<const CSimplifiedMNList>> cached_sml GUARDED_BY(cached_mutex){
110 3 : std::make_shared<const CSimplifiedMNList>()};
111 : static uint256 merkleRootCached GUARDED_BY(cached_mutex);
112 : static bool mutatedCached GUARDED_BY(cached_mutex){false};
113 :
114 36470 : LOCK(cached_mutex);
115 36470 : if (sml == cached_sml || *sml == *cached_sml) {
116 36412 : merkleRootRet = merkleRootCached;
117 36412 : if (mutatedCached) {
118 0 : return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "mutated-cached-calc-cb-mnmerkleroot");
119 : }
120 36412 : return true;
121 : }
122 :
123 58 : bool mutated = false;
124 58 : merkleRootRet = sml->CalcMerkleRoot(&mutated);
125 :
126 58 : int64_t nTime2 = GetTimeMicros();
127 58 : nTimeMerkle += nTime2 - nTime1;
128 58 : LogPrint(BCLog::BENCHMARK, " - CalcMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1),
129 : nTimeMerkle * 0.000001);
130 :
131 58 : cached_sml = sml;
132 58 : merkleRootCached = merkleRootRet;
133 58 : mutatedCached = mutated;
134 :
135 58 : if (mutated) {
136 0 : return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "mutated-calc-cb-mnmerkleroot");
137 : }
138 :
139 58 : return true;
140 36470 : } catch (const std::exception& e) {
141 0 : LogPrintf("%s -- failed: %s\n", __func__, e.what());
142 0 : return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "failed-calc-cb-mnmerkleroot");
143 0 : }
144 36470 : }
|