25 static const std::string DB_MINED_COMMITMENT =
"q_mc";
26 static const std::string DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT =
"q_mcih";
34 template<
typename... Args>
35 static int LogMisbehaving(
CNode* pfrom,
int nDoS,
const char* fmt,
const Args&... args)
41 LogPrintf(
"Error (%s) while formatting message %s\n", std::string(e.what()), fmt);
59 retMisbehavingScore = LogMisbehaving(pfrom, 100,
"null commitment");
72 static std::set<std::string> not_punishable_reasons = {
75 "bad-qc-quorum-hash-not-found",
"bad-qc-quorum-hash-not-active-chain"
79 retMisbehavingScore = LogMisbehaving(pfrom, dos,
"invalid commtiment for quorum %s: %s",
84 LogPrintf(
"%s :received commitment for quorum %s:%d, validMembers=%d, signers=%d, peer=%d\n", __func__,
100 std::map<Consensus::LLMQType, CFinalCommitment> qcs;
109 for (
const auto&
llmq : consensus.llmqs) {
117 bool hasCommitmentInNewBlock = qcs.count(type) != 0;
120 if (hasCommitmentInNewBlock && !isCommitmentRequired) {
122 return state.
DoS(100,
false, REJECT_INVALID,
"bad-qc-not-allowed");
125 if (!hasCommitmentInNewBlock && isCommitmentRequired) {
128 return state.
DoS(100,
false, REJECT_INVALID,
"bad-qc-missing");
134 for (
const auto& p : qcs) {
135 const auto& qc = p.second;
146 static std::tuple<std::string, uint8_t, uint32_t> BuildInversedHeightKey(
Consensus::LLMQType llmqType,
int nMinedHeight)
149 return std::make_tuple(DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT,
static_cast<uint8_t
>(llmqType),
htobe32(std::numeric_limits<uint32_t>::max() - nMinedHeight));
159 if (quorumHash.
IsNull()) {
160 return state.
DoS(100,
false, REJECT_INVALID,
"bad-qc-null-quorumhash");
163 return state.
DoS(100,
false, REJECT_INVALID,
"bad-qc-block");
169 if (fJustCheck || qc.
IsNull()) {
174 auto cacheKey = std::make_pair(qc.
llmqType, quorumHash);
175 evoDb.
Write(std::make_pair(DB_MINED_COMMITMENT, cacheKey), std::make_pair(qc, blockHash));
185 LogPrintf(
"%s: processed commitment from block. type=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s\n", __func__,
193 std::map<Consensus::LLMQType, CFinalCommitment> qcs;
199 for (
const auto& p : qcs) {
200 const auto& qc = p.second;
205 evoDb.
Erase(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(
static_cast<uint8_t
>(qc.llmqType), qc.quorumHash)));
225 for (
const auto& tx : block.
vtx) {
226 if (!tx->IsQuorumCommitmentTx()) {
232 return state.
DoS(100,
false, REJECT_INVALID,
"bad-qc-payload");
237 return state.
DoS(100,
false, REJECT_INVALID,
"bad-qc-dup");
249 int phaseIndex = nHeight % params.dkgInterval;
250 return phaseIndex >= params.dkgMiningWindowStart && phaseIndex <= params.dkgMiningWindowEnd;
264 return isMiningPhase && !hasMinedCommitment;
271 int quorumStartHeight = nHeight - (nHeight % params.dkgInterval);
277 return chainActive[quorumStartHeight]->GetBlockHash();
285 if (mapHasMinedCommitmentCache.at((
Consensus::LLMQType)llmqType).get(quorumHash, fExists)) {
290 fExists =
evoDb.
Exists(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(
static_cast<uint8_t
>(llmqType), quorumHash)));
300 auto key = std::make_pair(DB_MINED_COMMITMENT, std::make_pair(
static_cast<uint8_t
>(llmqType), quorumHash));
301 std::pair<CFinalCommitment, uint256> p;
305 retQc = std::move(p.first);
306 retMinedBlockHash = p.second;
317 auto firstKey = BuildInversedHeightKey(llmqType, pindex->
nHeight);
318 auto lastKey = BuildInversedHeightKey(llmqType, 0);
320 dbIt->Seek(firstKey);
322 std::vector<const CBlockIndex*> ret;
323 ret.reserve(maxCount);
325 while (dbIt->Valid() && ret.size() < maxCount) {
326 decltype(firstKey) curKey;
328 if (!dbIt->GetKey(curKey) || curKey >= lastKey) {
331 if (std::get<0>(curKey) != DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT || std::get<1>(curKey) !=
static_cast<uint8_t
>(llmqType)) {
335 uint32_t nMinedHeight = std::numeric_limits<uint32_t>::max() -
be32toh(std::get<2>(curKey));
336 if (nMinedHeight > (uint32_t) pindex->
nHeight) {
340 if (!dbIt->GetValue(quorumHeight)) {
344 auto quorumIndex = pindex->
GetAncestor(quorumHeight);
346 ret.emplace_back(quorumIndex);
357 std::map<Consensus::LLMQType, std::vector<const CBlockIndex*>> ret;
359 for (
const auto& p :
Params().GetConsensus().llmqs) {
360 auto& v = ret[p.second.type];
361 v.reserve(p.second.signingActiveQuorumCount);
363 for (
auto& c : commitments) {
399 ins.first->second = commitmentHash;
404 if (status.quorumHash != fqc.quorumHash || status.receivedFinalCommitment) {
420 LOCK(minableCommitmentsCs);
421 auto it = minableCommitments.find(commitmentHash);
422 if (it == minableCommitments.end()) {
433 if (!IsCommitmentRequired(llmqType, nHeight)) {
438 uint256 quorumHash = GetQuorumBlockHash(llmqType, nHeight);
439 if (quorumHash.
IsNull()) {
449 LOCK(minableCommitmentsCs);
451 auto k = std::make_pair(
static_cast<uint8_t
>(llmqType), quorumHash);
452 auto it = minableCommitmentsByQuorum.find(k);
453 if (it == minableCommitmentsByQuorum.end()) {
459 ret = minableCommitments.at(it->second);
467 if (!GetMinableCommitment(llmqType, nHeight, pl.
commitment)) {
475 tx.
nType = CTransaction::TxType::LLMQCOMM;
478 ret = MakeTransactionRef(tx);
const CChainParams & Params()
Return the currently selected parameters.
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
int Height() const
Return the maximal height in the chain.
const Consensus::Params & GetConsensus() const
std::unique_ptr< CDBTransactionIterator< CDBTransaction > > NewIteratorUniquePtr()
bool Exists(const K &key)
CurTransaction & GetCurTransaction()
void Write(const K &key, const V &value)
bool Read(const K &key, V &value)
Information about a peer.
bool IsSporkActive(SporkId nSporkID)
Capture information about block/transaction validation.
bool DoS(int level, bool ret=false, unsigned int chRejectCodeIn=0, std::string strRejectReasonIn="", bool corruptionIn=false, const std::string &strDebugMessageIn="")
std::string GetRejectReason() const
std::string ToString() const
bool receivedFinalCommitment
CBLSPublicKey quorumPublicKey
int CountValidMembers() const
CQuorumBlockProcessor(CEvoDB &_evoDb)
RecursiveMutex minableCommitmentsCs
bool IsCommitmentRequired(Consensus::LLMQType llmqType, int nHeight)
bool ProcessCommitment(int nHeight, const uint256 &blockHash, const CFinalCommitment &qc, CValidationState &state, bool fJustCheck)
std::map< uint256, CFinalCommitment > minableCommitments
bool HasBetterMinableCommitment(const CFinalCommitment &qc)
bool HasMinableCommitment(const uint256 &hash)
bool UndoBlock(const CBlock &block, const CBlockIndex *pindex)
static uint256 GetQuorumBlockHash(Consensus::LLMQType llmqType, int nHeight)
std::map< std::pair< uint8_t, uint256 >, uint256 > minableCommitmentsByQuorum
bool ProcessBlock(const CBlock &block, const CBlockIndex *pindex, CValidationState &state, bool fJustCheck)
std::map< Consensus::LLMQType, std::vector< const CBlockIndex * > > GetMinedAndActiveCommitmentsUntilBlock(const CBlockIndex *pindex)
std::vector< const CBlockIndex * > GetMinedCommitmentsUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex *pindex, size_t maxCount)
bool GetMinedCommitment(Consensus::LLMQType llmqType, const uint256 &quorumHash, CFinalCommitment &ret, uint256 &retMinedBlockHash)
static bool GetCommitmentsFromBlock(const CBlock &block, const CBlockIndex *pindex, std::map< Consensus::LLMQType, CFinalCommitment > &ret, CValidationState &state)
bool HasMinedCommitment(Consensus::LLMQType llmqType, const uint256 &quorumHash)
static bool IsMiningPhase(Consensus::LLMQType llmqType, int nHeight)
void AddAndRelayMinableCommitment(const CFinalCommitment &fqc, uint256 *cached_fqc_hash=nullptr)
void ProcessMessage(CNode *pfrom, CDataStream &vRecv, int &retMisbehavingScore)
CFinalCommitment commitment
uint32_t htobe32(uint32_t host_32bits)
uint32_t be32toh(uint32_t big_endian_32bits)
std::unique_ptr< CEvoDB > evoDb
uint256 SerializeHash(const T &obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Compute the 256-bit hash of an object's serialization.
std::unique_ptr< CConnman > g_connman
#define LogPrint(category,...)
std::string EncodePublic(const CChainParams ¶ms, const CBLSPublicKey &pk)
void InitQuorumsCache(CacheType &cache)
std::unique_ptr< CQuorumBlockProcessor > quorumBlockProcessor
std::unique_ptr< CDKGDebugManager > quorumDKGDebugManager
RecursiveMutex cs_main
Global state.
@ MSG_QUORUM_FINAL_COMMITMENT
bool VerifyLLMQCommitment(const llmq::CFinalCommitment &qfc, const CBlockIndex *pindexPrev, CValidationState &state)
CSporkManager sporkManager
@ SPORK_22_LLMQ_DKG_MAINTENANCE
A mutable version of CTransaction.
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const
Returns true if the given network upgrade is active as of the given block height.
std::map< LLMQType, LLMQParams > llmqs
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
void SetTxPayload(CMutableTransaction &tx, const T &payload)
bool GetTxPayload(const std::vector< unsigned char > &payload, T &obj)
std::shared_ptr< const CTransaction > CTransactionRef
const uint256 UINT256_ZERO
constant uint256 instances
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).