forked from dashpay/dash
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcommitment.h
More file actions
180 lines (154 loc) · 6.72 KB
/
commitment.h
File metadata and controls
180 lines (154 loc) · 6.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright (c) 2018-2025 The Dash Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_LLMQ_COMMITMENT_H
#define BITCOIN_LLMQ_COMMITMENT_H
#include <bls/bls.h>
#include <llmq/params.h>
#include <primitives/transaction.h>
#include <util/irange.h>
#include <util/strencodings.h>
#include <util/underlying.h>
#include <gsl/pointers.h>
#include <univalue.h>
#include <algorithm>
#include <limits>
#include <memory>
#include <string>
#include <vector>
class CBlockIndex;
class CDeterministicMNManager;
class ChainstateManager;
class TxValidationState;
namespace llmq
{
class CQuorumSnapshotManager;
// This message is an aggregation of all received premature commitments and only valid if
// enough (>=threshold) premature commitments were aggregated
// This is mined on-chain as part of TRANSACTION_QUORUM_COMMITMENT
class CFinalCommitment
{
public:
static constexpr uint16_t LEGACY_BLS_NON_INDEXED_QUORUM_VERSION = 1;
static constexpr uint16_t LEGACY_BLS_INDEXED_QUORUM_VERSION = 2;
static constexpr uint16_t BASIC_BLS_NON_INDEXED_QUORUM_VERSION = 3;
static constexpr uint16_t BASIC_BLS_INDEXED_QUORUM_VERSION = 4;
uint16_t nVersion{LEGACY_BLS_NON_INDEXED_QUORUM_VERSION};
Consensus::LLMQType llmqType{Consensus::LLMQType::LLMQ_NONE};
uint256 quorumHash;
int16_t quorumIndex{0};
std::vector<bool> signers;
std::vector<bool> validMembers;
CBLSPublicKey quorumPublicKey;
uint256 quorumVvecHash;
CBLSSignature quorumSig; // recovered threshold sig of blockHash+validMembers+pubKeyHash+vvecHash
CBLSSignature membersSig; // aggregated member sig of blockHash+validMembers+pubKeyHash+vvecHash
public:
CFinalCommitment() = default;
CFinalCommitment(const Consensus::LLMQParams& params, const uint256& _quorumHash);
int CountSigners() const
{
return int(std::count(signers.begin(), signers.end(), true));
}
int CountValidMembers() const
{
return int(std::count(validMembers.begin(), validMembers.end(), true));
}
bool Verify(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman,
gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, bool checkSigs) const;
bool VerifyNull() const;
bool VerifySizes(const Consensus::LLMQParams& params) const;
[[nodiscard]] static constexpr uint16_t GetVersion(const bool is_rotation_enabled, const bool is_basic_scheme_active)
{
if (is_rotation_enabled)
return is_basic_scheme_active ? BASIC_BLS_INDEXED_QUORUM_VERSION : LEGACY_BLS_INDEXED_QUORUM_VERSION;
else
return is_basic_scheme_active ? BASIC_BLS_NON_INDEXED_QUORUM_VERSION : LEGACY_BLS_NON_INDEXED_QUORUM_VERSION;
}
public:
SERIALIZE_METHODS(CFinalCommitment, obj)
{
READWRITE(
obj.nVersion,
obj.llmqType,
obj.quorumHash
);
if (obj.nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION || obj.nVersion == BASIC_BLS_INDEXED_QUORUM_VERSION) {
READWRITE(
obj.quorumIndex
);
}
READWRITE(
DYNBITSET(obj.signers),
DYNBITSET(obj.validMembers),
CBLSPublicKeyVersionWrapper(const_cast<CBLSPublicKey&>(obj.quorumPublicKey), (obj.nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || obj.nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION)),
obj.quorumVvecHash,
CBLSSignatureVersionWrapper(const_cast<CBLSSignature&>(obj.quorumSig), (obj.nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || obj.nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION)),
CBLSSignatureVersionWrapper(const_cast<CBLSSignature&>(obj.membersSig), (obj.nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || obj.nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION))
);
}
public:
bool IsNull() const
{
if (std::count(signers.begin(), signers.end(), true) ||
std::count(validMembers.begin(), validMembers.end(), true)) {
return false;
}
if (quorumPublicKey.IsValid() ||
!quorumVvecHash.IsNull() ||
membersSig.IsValid() ||
quorumSig.IsValid()) {
return false;
}
return true;
}
[[nodiscard]] UniValue ToJson() const
{
UniValue obj(UniValue::VOBJ);
obj.pushKV("version", int{nVersion});
obj.pushKV("llmqType", ToUnderlying(llmqType));
obj.pushKV("quorumHash", quorumHash.ToString());
obj.pushKV("quorumIndex", quorumIndex);
obj.pushKV("signersCount", CountSigners());
obj.pushKV("signers", BitsVectorToHexStr(signers));
obj.pushKV("validMembersCount", CountValidMembers());
obj.pushKV("validMembers", BitsVectorToHexStr(validMembers));
obj.pushKV("quorumPublicKey", quorumPublicKey.ToString(nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION));
obj.pushKV("quorumVvecHash", quorumVvecHash.ToString());
obj.pushKV("quorumSig", quorumSig.ToString(nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION));
obj.pushKV("membersSig", membersSig.ToString(nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION));
return obj;
}
private:
static std::string BitsVectorToHexStr(const std::vector<bool>& vBits)
{
std::vector<uint8_t> vBytes((vBits.size() + 7) / 8);
for (const auto i : irange::range(vBits.size())) {
vBytes[i / 8] |= vBits[i] << (i % 8);
}
return HexStr(vBytes);
}
};
using CFinalCommitmentPtr = std::unique_ptr<CFinalCommitment>;
class CFinalCommitmentTxPayload
{
public:
static constexpr auto SPECIALTX_TYPE = TRANSACTION_QUORUM_COMMITMENT;
static constexpr uint16_t CURRENT_VERSION = 1;
public:
uint16_t nVersion{CURRENT_VERSION};
uint32_t nHeight{std::numeric_limits<uint32_t>::max()};
CFinalCommitment commitment;
public:
SERIALIZE_METHODS(CFinalCommitmentTxPayload, obj)
{
READWRITE(obj.nVersion, obj.nHeight, obj.commitment);
}
[[nodiscard]] UniValue ToJson() const;
};
bool CheckLLMQCommitment(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman,
const ChainstateManager& chainman, const CTransaction& tx,
gsl::not_null<const CBlockIndex*> pindexPrev, TxValidationState& state);
uint256 BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256& blockHash, const std::vector<bool>& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash);
} // namespace llmq
#endif // BITCOIN_LLMQ_COMMITMENT_H