Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

quorums_commitment.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2019 The Dash Core developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
6 #include <llmq/quorums_utils.h>
7 
8 #include <chainparams.h>
9 #include <validation.h>
10 
11 #include <evo/specialtx.h>
12 
13 namespace llmq
14 {
15 
17  llmqType(params.type),
18  quorumHash(_quorumHash),
19  signers(params.size),
20  validMembers(params.size)
21 {
22 }
23 
24 #define LogPrintfFinalCommitment(...) do { \
25  LogPrintStr(strprintf("CFinalCommitment::%s -- %s", __func__, tinyformat::format(__VA_ARGS__))); \
26 } while(0)
27 
28 bool CFinalCommitment::Verify(const std::vector<CDeterministicMNCPtr>& members, bool checkSigs) const
29 {
30  if (nVersion == 0 || nVersion > CURRENT_VERSION) {
31  return false;
32  }
33 
34  if (!Params().GetConsensus().llmqs.count((Consensus::LLMQType)llmqType)) {
35  LogPrintfFinalCommitment("invalid llmqType=%d\n", llmqType);
36  return false;
37  }
38  const auto& params = Params().GetConsensus().llmqs.at((Consensus::LLMQType)llmqType);
39 
40  if (!VerifySizes(params)) {
41  return false;
42  }
43 
44  if (CountValidMembers() < params.minSize) {
45  LogPrintfFinalCommitment("invalid validMembers count. validMembersCount=%d\n", CountValidMembers());
46  return false;
47  }
48  if (CountSigners() < params.minSize) {
49  LogPrintfFinalCommitment("invalid signers count. signersCount=%d\n", CountSigners());
50  return false;
51  }
52  if (!quorumPublicKey.IsValid()) {
53  LogPrintfFinalCommitment("invalid quorumPublicKey\n");
54  return false;
55  }
56  if (quorumVvecHash.IsNull()) {
57  LogPrintfFinalCommitment("invalid quorumVvecHash\n");
58  return false;
59  }
60  if (!membersSig.IsValid()) {
61  LogPrintfFinalCommitment("invalid membersSig\n");
62  return false;
63  }
64  if (!quorumSig.IsValid()) {
65  LogPrintfFinalCommitment("invalid vvecSig\n");
66  return false;
67  }
68 
69  for (size_t i = members.size(); i < params.size; i++) {
70  if (validMembers[i]) {
71  LogPrintfFinalCommitment("invalid validMembers bitset. bit %d should not be set\n", i);
72  return false;
73  }
74  if (signers[i]) {
75  LogPrintfFinalCommitment("invalid signers bitset. bit %d should not be set\n", i);
76  return false;
77  }
78  }
79 
80  // sigs are only checked when the block is processed
81  if (checkSigs) {
83 
84  std::vector<CBLSPublicKey> memberPubKeys;
85  for (size_t i = 0; i < members.size(); i++) {
86  if (!signers[i]) {
87  continue;
88  }
89  memberPubKeys.emplace_back(members[i]->pdmnState->pubKeyOperator.Get());
90  }
91 
92  if (!membersSig.VerifySecureAggregated(memberPubKeys, commitmentHash)) {
93  LogPrintfFinalCommitment("invalid aggregated members signature\n");
94  return false;
95  }
96 
97  if (!quorumSig.VerifyInsecure(quorumPublicKey, commitmentHash)) {
98  LogPrintfFinalCommitment("invalid quorum signature\n");
99  return false;
100  }
101  }
102 
103  return true;
104 }
105 
107 {
108  if (!Params().GetConsensus().llmqs.count((Consensus::LLMQType)llmqType)) {
109  LogPrintfFinalCommitment("invalid llmqType=%d\n", llmqType);
110  return false;
111  }
112  const auto& params = Params().GetConsensus().llmqs.at((Consensus::LLMQType)llmqType);
113 
114  if (!IsNull() || !VerifySizes(params)) {
115  return false;
116  }
117 
118  return true;
119 }
120 
122 {
123  if (signers.size() != params.size) {
124  LogPrintfFinalCommitment("invalid signers.size=%d\n", signers.size());
125  return false;
126  }
127  if (validMembers.size() != params.size) {
128  LogPrintfFinalCommitment("invalid signers.size=%d\n", signers.size());
129  return false;
130  }
131  return true;
132 }
133 
134 bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
135 {
137  if (!GetTxPayload(tx, qcTx)) {
138  return state.DoS(100, false, REJECT_INVALID, "bad-qc-payload");
139  }
140 
142  return state.DoS(100, false, REJECT_INVALID, "bad-qc-version");
143  }
144 
145  if (qcTx.nHeight != pindexPrev->nHeight + 1) {
146  return state.DoS(100, false, REJECT_INVALID, "bad-qc-height");
147  }
148 
149  if (!mapBlockIndex.count(qcTx.commitment.quorumHash)) {
150  return state.DoS(100, false, REJECT_INVALID, "bad-qc-quorum-hash");
151  }
152 
153  const CBlockIndex* pindexQuorum = mapBlockIndex[qcTx.commitment.quorumHash];
154 
155  if (pindexQuorum != pindexPrev->GetAncestor(pindexQuorum->nHeight)) {
156  // not part of active chain
157  return state.DoS(100, false, REJECT_INVALID, "bad-qc-quorum-hash");
158  }
159 
160  if (!Params().GetConsensus().llmqs.count((Consensus::LLMQType)qcTx.commitment.llmqType)) {
161  return state.DoS(100, false, REJECT_INVALID, "bad-qc-type");
162  }
163  const auto& params = Params().GetConsensus().llmqs.at((Consensus::LLMQType)qcTx.commitment.llmqType);
164 
165  if (qcTx.commitment.IsNull()) {
166  if (!qcTx.commitment.VerifyNull()) {
167  return state.DoS(100, false, REJECT_INVALID, "bad-qc-invalid-null");
168  }
169  return true;
170  }
171 
172  auto members = CLLMQUtils::GetAllQuorumMembers(params.type, pindexQuorum);
173  if (!qcTx.commitment.Verify(members, false)) {
174  return state.DoS(100, false, REJECT_INVALID, "bad-qc-invalid");
175  }
176 
177  return true;
178 }
179 
180 } // namespace llmq
bool GetTxPayload(const std::vector< unsigned char > &payload, T &obj)
Definition: specialtx.h:21
BlockMap & mapBlockIndex
Definition: validation.cpp:215
bool VerifyInsecure(const CBLSPublicKey &pubKey, const uint256 &hash) const
Definition: bls.cpp:335
bool DoS(int level, bool ret=false, unsigned int chRejectCodeIn=0, const std::string &strRejectReasonIn="", bool corruptionIn=false, const std::string &strDebugMessageIn="")
Definition: validation.h:36
Consensus::LLMQType llmqType
bool VerifySizes(const Consensus::LLMQParams &params) const
bool CheckLLMQCommitment(const CTransaction &tx, const CBlockIndex *pindexPrev, CValidationState &state)
static const unsigned char REJECT_INVALID
Definition: validation.h:13
bool IsNull() const
Definition: uint256.h:33
static const uint16_t CURRENT_VERSION
static const uint16_t CURRENT_VERSION
LLMQType
Definition: params.h:48
static uint256 BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256 &blockHash, const std::vector< bool > &validMembers, const CBLSPublicKey &pubKey, const uint256 &vvecHash)
std::map< LLMQType, LLMQParams > llmqs
Definition: params.h:189
std::vector< bool > signers
Capture information about block/transaction validation.
Definition: validation.h:22
256-bit opaque blob.
Definition: uint256.h:123
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.
#define LogPrintfFinalCommitment(...)
bool Verify(const std::vector< CDeterministicMNCPtr > &members, bool checkSigs) const
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:198
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:183
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:54
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:110
std::vector< bool > validMembers
bool IsValid() const
Definition: bls.h:94
bool VerifySecureAggregated(const std::vector< CBLSPublicKey > &pks, const uint256 &hash) const
Definition: bls.cpp:375
static std::vector< CDeterministicMNCPtr > GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex *pindexQuorum)
Released under the MIT license