forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
chainlocks.h
136 lines (105 loc) · 5.08 KB
/
chainlocks.h
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
// Copyright (c) 2019-2023 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_CHAINLOCKS_H
#define BITCOIN_LLMQ_CHAINLOCKS_H
#include <llmq/clsig.h>
#include <crypto/common.h>
#include <llmq/signing.h>
#include <net.h>
#include <net_types.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <saltedhasher.h>
#include <sync.h>
#include <gsl/pointers.h>
#include <atomic>
#include <map>
#include <unordered_map>
#include <unordered_set>
class CChainState;
class CConnman;
class CBlockIndex;
class CMasternodeSync;
class CScheduler;
class CSporkManager;
class CTxMemPool;
namespace llmq
{
class CSigningManager;
class CSigSharesManager;
class CChainLocksHandler : public CRecoveredSigsListener
{
static constexpr int64_t CLEANUP_INTERVAL = 1000 * 30;
static constexpr int64_t CLEANUP_SEEN_TIMEOUT = 24 * 60 * 60 * 1000;
// how long to wait for islocks until we consider a block with non-islocked TXs to be safe to sign
static constexpr int64_t WAIT_FOR_ISLOCK_TIMEOUT = 10 * 60;
private:
CChainState& m_chainstate;
CConnman& connman;
CMasternodeSync& m_mn_sync;
CQuorumManager& qman;
CSigningManager& sigman;
CSigSharesManager& shareman;
CSporkManager& spork_manager;
CTxMemPool& mempool;
std::unique_ptr<CScheduler> scheduler;
std::unique_ptr<std::thread> scheduler_thread;
mutable Mutex cs;
std::atomic<bool> tryLockChainTipScheduled{false};
std::atomic<bool> isEnabled{false};
uint256 bestChainLockHash GUARDED_BY(cs);
CChainLockSig bestChainLock GUARDED_BY(cs);
CChainLockSig bestChainLockWithKnownBlock GUARDED_BY(cs);
const CBlockIndex* bestChainLockBlockIndex GUARDED_BY(cs) {nullptr};
const CBlockIndex* lastNotifyChainLockBlockIndex GUARDED_BY(cs) {nullptr};
int32_t lastSignedHeight GUARDED_BY(cs) {-1};
uint256 lastSignedRequestId GUARDED_BY(cs);
uint256 lastSignedMsgHash GUARDED_BY(cs);
// We keep track of txids from recently received blocks so that we can check if all TXs got islocked
struct BlockHasher
{
size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); }
};
using BlockTxs = std::unordered_map<uint256, std::shared_ptr<std::unordered_set<uint256, StaticSaltedHasher>>, BlockHasher>;
BlockTxs blockTxs GUARDED_BY(cs);
std::unordered_map<uint256, int64_t, StaticSaltedHasher> txFirstSeenTime GUARDED_BY(cs);
std::map<uint256, int64_t> seenChainLocks GUARDED_BY(cs);
std::atomic<int64_t> lastCleanupTime{0};
public:
explicit CChainLocksHandler(CChainState& chainstate, CConnman& _connman, CMasternodeSync& mn_sync, CQuorumManager& _qman,
CSigningManager& _sigman, CSigSharesManager& _shareman, CSporkManager& sporkManager,
CTxMemPool& _mempool);
~CChainLocksHandler();
void Start();
void Stop();
bool AlreadyHave(const CInv& inv) const LOCKS_EXCLUDED(cs);
bool GetChainLockByHash(const uint256& hash, CChainLockSig& ret) const LOCKS_EXCLUDED(cs);
CChainLockSig GetBestChainLock() const LOCKS_EXCLUDED(cs);
PeerMsgRet ProcessMessage(const CNode& pfrom, const std::string& msg_type, CDataStream& vRecv);
PeerMsgRet ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash) LOCKS_EXCLUDED(cs);
void AcceptedBlockHeader(gsl::not_null<const CBlockIndex*> pindexNew) LOCKS_EXCLUDED(cs);
void UpdatedBlockTip();
void TransactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime) LOCKS_EXCLUDED(cs);
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, gsl::not_null<const CBlockIndex*> pindex) LOCKS_EXCLUDED(cs);
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, gsl::not_null<const CBlockIndex*> pindexDisconnected) LOCKS_EXCLUDED(cs);
void CheckActiveState() LOCKS_EXCLUDED(cs);
void TrySignChainTip() LOCKS_EXCLUDED(cs);
void EnforceBestChainLock() LOCKS_EXCLUDED(cs);
void HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) override LOCKS_EXCLUDED(cs);
bool HasChainLock(int nHeight, const uint256& blockHash) const LOCKS_EXCLUDED(cs);
bool HasConflictingChainLock(int nHeight, const uint256& blockHash) const LOCKS_EXCLUDED(cs);
bool VerifyChainLock(const CChainLockSig& clsig) const;
bool IsTxSafeForMining(const uint256& txid) const LOCKS_EXCLUDED(cs);
private:
// these require locks to be held already
bool InternalHasChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(cs);
bool InternalHasConflictingChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(cs);
BlockTxs::mapped_type GetBlockTxs(const uint256& blockHash) LOCKS_EXCLUDED(cs);
void Cleanup() LOCKS_EXCLUDED(cs);
};
extern std::unique_ptr<CChainLocksHandler> chainLocksHandler;
bool AreChainLocksEnabled(const CSporkManager& sporkManager);
bool ChainLocksSigningEnabled(const CSporkManager& sporkManager);
} // namespace llmq
#endif // BITCOIN_LLMQ_CHAINLOCKS_H