Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

simplifiedmns.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2019 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/cbtx.h>
6 #include <core_io.h>
7 #include <evo/deterministicmns.h>
8 #include <llmq/quorums.h>
11 #include <evo/simplifiedmns.h>
12 #include <evo/specialtx.h>
13 
14 #include <base58.h>
15 #include <chainparams.h>
16 #include <consensus/merkle.h>
17 #include <univalue.h>
18 #include <validation.h>
19 
21  proRegTxHash(dmn.proTxHash),
22  confirmedHash(dmn.pdmnState->confirmedHash),
23  service(dmn.pdmnState->addr),
24  pubKeyOperator(dmn.pdmnState->pubKeyOperator),
25  keyIDVoting(dmn.pdmnState->keyIDVoting),
26  isValid(dmn.pdmnState->nPoSeBanHeight == -1)
27 {
28 }
29 
31 {
33  hw << *this;
34  return hw.GetHash();
35 }
36 
38 {
39  return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValid=%d)",
41 }
42 
44 {
45  obj.clear();
46  obj.setObject();
47  obj.push_back(Pair("proRegTxHash", proRegTxHash.ToString()));
48  obj.push_back(Pair("confirmedHash", confirmedHash.ToString()));
49  obj.push_back(Pair("service", service.ToString(false)));
50  obj.push_back(Pair("pubKeyOperator", pubKeyOperator.Get().ToString()));
51  obj.push_back(Pair("votingAddress", EncodeDestination(keyIDVoting)));
52  obj.push_back(Pair("isValid", isValid));
53 }
54 
55 CSimplifiedMNList::CSimplifiedMNList(const std::vector<CSimplifiedMNListEntry>& smlEntries)
56 {
57  mnList.resize(smlEntries.size());
58  for (size_t i = 0; i < smlEntries.size(); i++) {
59  mnList[i] = std::make_unique<CSimplifiedMNListEntry>(smlEntries[i]);
60  }
61 
62  std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr<CSimplifiedMNListEntry>& a, const std::unique_ptr<CSimplifiedMNListEntry>& b) {
63  return a->proRegTxHash.Compare(b->proRegTxHash) < 0;
64  });
65 }
66 
68 {
69  mnList.resize(dmnList.GetAllMNsCount());
70 
71  size_t i = 0;
72  dmnList.ForEachMN(false, [this, &i](const CDeterministicMNCPtr& dmn) {
73  mnList[i++] = std::make_unique<CSimplifiedMNListEntry>(*dmn);
74  });
75 
76  std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr<CSimplifiedMNListEntry>& a, const std::unique_ptr<CSimplifiedMNListEntry>& b) {
77  return a->proRegTxHash.Compare(b->proRegTxHash) < 0;
78  });
79 }
80 
82 {
83  std::vector<uint256> leaves;
84  leaves.reserve(mnList.size());
85  for (const auto& e : mnList) {
86  leaves.emplace_back(e->CalcHash());
87  }
88  return ComputeMerkleRoot(leaves, pmutated);
89 }
90 
92 {
93 }
94 
96 {
97 }
98 
99 bool CSimplifiedMNListDiff::BuildQuorumsDiff(const CBlockIndex* baseBlockIndex, const CBlockIndex* blockIndex)
100 {
101  auto baseQuorums = llmq::quorumBlockProcessor->GetMinedAndActiveCommitmentsUntilBlock(baseBlockIndex);
103 
104  std::set<std::pair<Consensus::LLMQType, uint256>> baseQuorumHashes;
105  std::set<std::pair<Consensus::LLMQType, uint256>> quorumHashes;
106  for (auto& p : baseQuorums) {
107  for (auto& p2 : p.second) {
108  baseQuorumHashes.emplace(p.first, p2->GetBlockHash());
109  }
110  }
111  for (auto& p : quorums) {
112  for (auto& p2 : p.second) {
113  quorumHashes.emplace(p.first, p2->GetBlockHash());
114  }
115  }
116 
117  for (auto& p : baseQuorumHashes) {
118  if (!quorumHashes.count(p)) {
119  deletedQuorums.emplace_back((uint8_t)p.first, p.second);
120  }
121  }
122  for (auto& p : quorumHashes) {
123  if (!baseQuorumHashes.count(p)) {
125  uint256 minedBlockHash;
126  if (!llmq::quorumBlockProcessor->GetMinedCommitment(p.first, p.second, qc, minedBlockHash)) {
127  return false;
128  }
129  newQuorums.emplace_back(qc);
130  }
131  }
132  return true;
133 }
134 
136 {
137  obj.setObject();
138 
139  obj.push_back(Pair("baseBlockHash", baseBlockHash.ToString()));
140  obj.push_back(Pair("blockHash", blockHash.ToString()));
141 
142  CDataStream ssCbTxMerkleTree(SER_NETWORK, PROTOCOL_VERSION);
143  ssCbTxMerkleTree << cbTxMerkleTree;
144  obj.push_back(Pair("cbTxMerkleTree", HexStr(ssCbTxMerkleTree.begin(), ssCbTxMerkleTree.end())));
145 
146  obj.push_back(Pair("cbTx", EncodeHexTx(*cbTx)));
147 
148  UniValue deletedMNsArr(UniValue::VARR);
149  for (const auto& h : deletedMNs) {
150  deletedMNsArr.push_back(h.ToString());
151  }
152  obj.push_back(Pair("deletedMNs", deletedMNsArr));
153 
154  UniValue mnListArr(UniValue::VARR);
155  for (const auto& e : mnList) {
156  UniValue eObj;
157  e.ToJson(eObj);
158  mnListArr.push_back(eObj);
159  }
160  obj.push_back(Pair("mnList", mnListArr));
161 
162  UniValue deletedQuorumsArr(UniValue::VARR);
163  for (const auto& e : deletedQuorums) {
164  UniValue eObj(UniValue::VOBJ);
165  eObj.push_back(Pair("llmqType", e.first));
166  eObj.push_back(Pair("quorumHash", e.second.ToString()));
167  deletedQuorumsArr.push_back(eObj);
168  }
169  obj.push_back(Pair("deletedQuorums", deletedQuorumsArr));
170 
171  UniValue newQuorumsArr(UniValue::VARR);
172  for (const auto& e : newQuorums) {
173  UniValue eObj;
174  e.ToJson(eObj);
175  newQuorumsArr.push_back(eObj);
176  }
177  obj.push_back(Pair("newQuorums", newQuorumsArr));
178 
179  CCbTx cbTxPayload;
180  if (GetTxPayload(*cbTx, cbTxPayload)) {
181  obj.push_back(Pair("merkleRootMNList", cbTxPayload.merkleRootMNList.ToString()));
182  if (cbTxPayload.nVersion >= 2) {
183  obj.push_back(Pair("merkleRootQuorums", cbTxPayload.merkleRootQuorums.ToString()));
184  }
185  }
186 }
187 
188 bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet)
189 {
191  mnListDiffRet = CSimplifiedMNListDiff();
192 
193  const CBlockIndex* baseBlockIndex = chainActive.Genesis();
194  if (!baseBlockHash.IsNull()) {
195  auto it = mapBlockIndex.find(baseBlockHash);
196  if (it == mapBlockIndex.end()) {
197  errorRet = strprintf("block %s not found", baseBlockHash.ToString());
198  return false;
199  }
200  baseBlockIndex = it->second;
201  }
202  auto blockIt = mapBlockIndex.find(blockHash);
203  if (blockIt == mapBlockIndex.end()) {
204  errorRet = strprintf("block %s not found", blockHash.ToString());
205  return false;
206  }
207  const CBlockIndex* blockIndex = blockIt->second;
208 
209  if (!chainActive.Contains(baseBlockIndex) || !chainActive.Contains(blockIndex)) {
210  errorRet = strprintf("block %s and %s are not in the same chain", baseBlockHash.ToString(), blockHash.ToString());
211  return false;
212  }
213  if (baseBlockIndex->nHeight > blockIndex->nHeight) {
214  errorRet = strprintf("base block %s is higher then block %s", baseBlockHash.ToString(), blockHash.ToString());
215  return false;
216  }
217 
219 
220  auto baseDmnList = deterministicMNManager->GetListForBlock(baseBlockIndex);
221  auto dmnList = deterministicMNManager->GetListForBlock(blockIndex);
222  mnListDiffRet = baseDmnList.BuildSimplifiedDiff(dmnList);
223 
224  // We need to return the value that was provided by the other peer as it otherwise won't be able to recognize the
225  // response. This will usually be identical to the block found in baseBlockIndex. The only difference is when a
226  // null block hash was provided to get the diff from the genesis block.
227  mnListDiffRet.baseBlockHash = baseBlockHash;
228 
229  if (!mnListDiffRet.BuildQuorumsDiff(baseBlockIndex, blockIndex)) {
230  errorRet = strprintf("failed to build quorums diff");
231  return false;
232  }
233 
234  // TODO store coinbase TX in CBlockIndex
235  CBlock block;
236  if (!ReadBlockFromDisk(block, blockIndex, Params().GetConsensus())) {
237  errorRet = strprintf("failed to read block %s from disk", blockHash.ToString());
238  return false;
239  }
240 
241  mnListDiffRet.cbTx = block.vtx[0];
242 
243  std::vector<uint256> vHashes;
244  std::vector<bool> vMatch(block.vtx.size(), false);
245  for (const auto& tx : block.vtx) {
246  vHashes.emplace_back(tx->GetHash());
247  }
248  vMatch[0] = true; // only coinbase matches
249  mnListDiffRet.cbTxMerkleTree = CPartialMerkleTree(vHashes, vMatch);
250 
251  return true;
252 }
bool GetTxPayload(const std::vector< unsigned char > &payload, T &obj)
Definition: specialtx.h:21
CKeyID keyIDVoting
Definition: simplifiedmns.h:31
uint256 confirmedHash
Definition: simplifiedmns.h:28
std::vector< llmq::CFinalCommitment > newQuorums
std::string ToString(bool fUseGetnameinfo=true) const
Definition: netaddress.cpp:581
bool BuildSimplifiedMNListDiff(const uint256 &baseBlockHash, const uint256 &blockHash, CSimplifiedMNListDiff &mnListDiffRet, std::string &errorRet)
void ToJson(UniValue &obj) const
Definition: block.h:72
Definition: cbtx.h:16
#define strprintf
Definition: tinyformat.h:1066
CQuorumBlockProcessor * quorumBlockProcessor
BlockMap & mapBlockIndex
Definition: validation.cpp:215
CCriticalSection cs_main
Definition: validation.cpp:213
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
Definition: chain.h:448
size_t GetAllMNsCount() const
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:103
std::shared_ptr< const CDeterministicMN > CDeterministicMNCPtr
Data structure that represents a partial merkle tree.
Definition: merkleblock.h:50
uint256 proRegTxHash
Definition: simplifiedmns.h:27
void ForEachMN(bool onlyValid, Callback &&cb) const
CTransactionRef cbTx
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
bool IsNull() const
Definition: uint256.h:33
bool BuildQuorumsDiff(const CBlockIndex *baseBlockIndex, const CBlockIndex *blockIndex)
bool push_back(const UniValue &val)
Definition: univalue.cpp:110
uint256 CalcHash() const
std::map< Consensus::LLMQType, std::vector< const CBlockIndex * > > GetMinedAndActiveCommitmentsUntilBlock(const CBlockIndex *pindex)
std::string ToString() const
Definition: bls.h:210
#define LOCK(cs)
Definition: sync.h:178
uint256 merkleRootMNList
Definition: cbtx.h:24
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:471
uint256 merkleRootQuorums
Definition: cbtx.h:25
const BLSObject & Get() const
Definition: bls.h:402
std::string ToString() const
Definition: uint256.cpp:62
CBLSLazyPublicKey pubKeyOperator
Definition: simplifiedmns.h:30
static std::pair< std::string, UniValue > Pair(const char *cKey, const char *cVal)
Definition: univalue.h:185
std::string ToString() const
bool isValid
Definition: simplifiedmns.h:32
uint256 GetHash()
Definition: hash.h:203
256-bit opaque blob.
Definition: uint256.h:123
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:130
uint256 ComputeMerkleRoot(std::vector< uint256 > hashes, bool *mutated)
Definition: merkle.cpp:46
std::vector< CTransactionRef > vtx
Definition: block.h:76
const_iterator end() const
Definition: streams.h:192
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
const_iterator begin() const
Definition: streams.h:190
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
const CChainParams & Params()
Return the currently selected parameters.
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:14
bool setObject()
Definition: univalue.cpp:103
CPartialMerkleTree cbTxMerkleTree
uint256 CalcMerkleRoot(bool *pmutated=nullptr) const
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:184
std::vector< std::unique_ptr< CSimplifiedMNListEntry > > mnList
Definition: simplifiedmns.h:77
uint16_t nVersion
Definition: cbtx.h:22
void clear()
Definition: univalue.cpp:17
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:183
bool ReadBlockFromDisk(CBlock &block, const CDiskBlockPos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
CChain & chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:217
AssertLockHeld(g_cs_orphans)
static const int CLIENT_VERSION
dashd-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
void ToJson(UniValue &obj) const
std::vector< uint256 > deletedMNs
std::vector< CSimplifiedMNListEntry > mnList
CService service
Definition: simplifiedmns.h:29
std::vector< std::pair< uint8_t, uint256 > > deletedQuorums
CSimplifiedMNListEntry()
Definition: simplifiedmns.h:35
Released under the MIT license