Skip to content

Commit 544791d

Browse files
committed
refactor: move masternode mode logic to instantsend/signer.{cpp,h}
Review with `git log -p -n1 --color-moved=dimmed_zebra`.
1 parent 82dded4 commit 544791d

File tree

3 files changed

+379
-348
lines changed

3 files changed

+379
-348
lines changed

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ libbitcoin_node_a_SOURCES = \
493493
instantsend/db.cpp \
494494
instantsend/instantsend.cpp \
495495
instantsend/lock.cpp \
496+
instantsend/signing.cpp \
496497
llmq/blockprocessor.cpp \
497498
llmq/chainlocks.cpp \
498499
llmq/clsig.cpp \

src/instantsend/instantsend.cpp

Lines changed: 0 additions & 348 deletions
Original file line numberDiff line numberDiff line change
@@ -88,288 +88,6 @@ void CInstantSendManager::Stop()
8888
}
8989
}
9090

91-
void CInstantSendManager::ProcessTx(const CTransaction& tx, bool fRetroactive, const Consensus::Params& params)
92-
{
93-
if (!m_is_masternode || !IsInstantSendEnabled() || !m_mn_sync.IsBlockchainSynced()) {
94-
return;
95-
}
96-
97-
if (params.llmqTypeDIP0024InstantSend == Consensus::LLMQType::LLMQ_NONE) {
98-
return;
99-
}
100-
101-
if (!CheckCanLock(tx, true, params)) {
102-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: CheckCanLock returned false\n", __func__,
103-
tx.GetHash().ToString());
104-
return;
105-
}
106-
107-
auto conflictingLock = GetConflictingLock(tx);
108-
if (conflictingLock != nullptr) {
109-
auto conflictingLockHash = ::SerializeHash(*conflictingLock);
110-
LogPrintf("CInstantSendManager::%s -- txid=%s: conflicts with islock %s, txid=%s\n", __func__,
111-
tx.GetHash().ToString(), conflictingLockHash.ToString(), conflictingLock->txid.ToString());
112-
return;
113-
}
114-
115-
// Only sign for inlocks or islocks if mempool IS signing is enabled.
116-
// However, if we are processing a tx because it was included in a block we should
117-
// sign even if mempool IS signing is disabled. This allows a ChainLock to happen on this
118-
// block after we retroactively locked all transactions.
119-
if (!IsInstantSendMempoolSigningEnabled() && !fRetroactive) return;
120-
121-
if (!TrySignInputLocks(tx, fRetroactive, params.llmqTypeDIP0024InstantSend, params)) {
122-
return;
123-
}
124-
125-
// We might have received all input locks before we got the corresponding TX. In this case, we have to sign the
126-
// islock now instead of waiting for the input locks.
127-
TrySignInstantSendLock(tx);
128-
}
129-
130-
bool CInstantSendManager::TrySignInputLocks(const CTransaction& tx, bool fRetroactive, Consensus::LLMQType llmqType, const Consensus::Params& params)
131-
{
132-
std::vector<uint256> ids;
133-
ids.reserve(tx.vin.size());
134-
135-
size_t alreadyVotedCount = 0;
136-
for (const auto& in : tx.vin) {
137-
auto id = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in.prevout));
138-
ids.emplace_back(id);
139-
140-
uint256 otherTxHash;
141-
if (sigman.GetVoteForId(params.llmqTypeDIP0024InstantSend, id, otherTxHash)) {
142-
if (otherTxHash != tx.GetHash()) {
143-
LogPrintf("CInstantSendManager::%s -- txid=%s: input %s is conflicting with previous vote for tx %s\n", __func__,
144-
tx.GetHash().ToString(), in.prevout.ToStringShort(), otherTxHash.ToString());
145-
return false;
146-
}
147-
alreadyVotedCount++;
148-
}
149-
150-
// don't even try the actual signing if any input is conflicting
151-
if (sigman.IsConflicting(params.llmqTypeDIP0024InstantSend, id, tx.GetHash())) {
152-
LogPrintf("CInstantSendManager::%s -- txid=%s: sigman.IsConflicting returned true. id=%s\n", __func__,
153-
tx.GetHash().ToString(), id.ToString());
154-
return false;
155-
}
156-
}
157-
if (!fRetroactive && alreadyVotedCount == ids.size()) {
158-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: already voted on all inputs, bailing out\n", __func__,
159-
tx.GetHash().ToString());
160-
return true;
161-
}
162-
163-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: trying to vote on %d inputs\n", __func__,
164-
tx.GetHash().ToString(), tx.vin.size());
165-
166-
for (const auto i : irange::range(tx.vin.size())) {
167-
const auto& in = tx.vin[i];
168-
auto& id = ids[i];
169-
WITH_LOCK(cs_inputReqests, inputRequestIds.emplace(id));
170-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: trying to vote on input %s with id %s. fRetroactive=%d\n", __func__,
171-
tx.GetHash().ToString(), in.prevout.ToStringShort(), id.ToString(), fRetroactive);
172-
if (sigman.AsyncSignIfMember(llmqType, shareman, id, tx.GetHash(), {}, fRetroactive)) {
173-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: voted on input %s with id %s\n", __func__,
174-
tx.GetHash().ToString(), in.prevout.ToStringShort(), id.ToString());
175-
}
176-
}
177-
178-
return true;
179-
}
180-
181-
bool CInstantSendManager::CheckCanLock(const CTransaction& tx, bool printDebug, const Consensus::Params& params) const
182-
{
183-
if (tx.vin.empty()) {
184-
// can't lock TXs without inputs (e.g. quorum commitments)
185-
return false;
186-
}
187-
188-
return ranges::all_of(tx.vin,
189-
[&](const auto& in) { return CheckCanLock(in.prevout, printDebug, tx.GetHash(), params); });
190-
}
191-
192-
bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebug, const uint256& txHash, const Consensus::Params& params) const
193-
{
194-
int nInstantSendConfirmationsRequired = params.nInstantSendConfirmationsRequired;
195-
196-
if (IsLocked(outpoint.hash)) {
197-
// if prevout was ix locked, allow locking of descendants (no matter if prevout is in mempool or already mined)
198-
return true;
199-
}
200-
201-
auto mempoolTx = mempool.get(outpoint.hash);
202-
if (mempoolTx) {
203-
if (printDebug) {
204-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: parent mempool TX %s is not locked\n", __func__,
205-
txHash.ToString(), outpoint.hash.ToString());
206-
}
207-
return false;
208-
}
209-
210-
uint256 hashBlock{};
211-
const auto tx = GetTransaction(nullptr, &mempool, outpoint.hash, params, hashBlock);
212-
// this relies on enabled txindex and won't work if we ever try to remove the requirement for txindex for masternodes
213-
if (!tx) {
214-
if (printDebug) {
215-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: failed to find parent TX %s\n", __func__,
216-
txHash.ToString(), outpoint.hash.ToString());
217-
}
218-
return false;
219-
}
220-
221-
const CBlockIndex* pindexMined;
222-
int nTxAge;
223-
{
224-
LOCK(::cs_main);
225-
pindexMined = m_chainstate.m_blockman.LookupBlockIndex(hashBlock);
226-
nTxAge = m_chainstate.m_chain.Height() - pindexMined->nHeight + 1;
227-
}
228-
229-
if (nTxAge < nInstantSendConfirmationsRequired && !clhandler.HasChainLock(pindexMined->nHeight, pindexMined->GetBlockHash())) {
230-
if (printDebug) {
231-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: outpoint %s too new and not ChainLocked. nTxAge=%d, nInstantSendConfirmationsRequired=%d\n", __func__,
232-
txHash.ToString(), outpoint.ToStringShort(), nTxAge, nInstantSendConfirmationsRequired);
233-
}
234-
return false;
235-
}
236-
237-
return true;
238-
}
239-
240-
MessageProcessingResult CInstantSendManager::HandleNewRecoveredSig(const CRecoveredSig& recoveredSig)
241-
{
242-
if (!IsInstantSendEnabled()) {
243-
return {};
244-
}
245-
246-
if (Params().GetConsensus().llmqTypeDIP0024InstantSend == Consensus::LLMQType::LLMQ_NONE) {
247-
return {};
248-
}
249-
250-
uint256 txid;
251-
if (LOCK(cs_inputReqests); inputRequestIds.count(recoveredSig.getId())) {
252-
txid = recoveredSig.getMsgHash();
253-
}
254-
if (!txid.IsNull()) {
255-
HandleNewInputLockRecoveredSig(recoveredSig, txid);
256-
} else if (/*isInstantSendLock=*/ WITH_LOCK(cs_creating, return creatingInstantSendLocks.count(recoveredSig.getId()))) {
257-
HandleNewInstantSendLockRecoveredSig(recoveredSig);
258-
}
259-
return {};
260-
}
261-
262-
void CInstantSendManager::HandleNewInputLockRecoveredSig(const CRecoveredSig& recoveredSig, const uint256& txid)
263-
{
264-
if (g_txindex) {
265-
g_txindex->BlockUntilSyncedToCurrentChain();
266-
}
267-
268-
269-
uint256 hashBlock{};
270-
const auto tx = GetTransaction(nullptr, &mempool, txid, Params().GetConsensus(), hashBlock);
271-
if (!tx) {
272-
return;
273-
}
274-
275-
if (LogAcceptDebug(BCLog::INSTANTSEND)) {
276-
for (const auto& in : tx->vin) {
277-
auto id = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in.prevout));
278-
if (id == recoveredSig.getId()) {
279-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: got recovered sig for input %s\n", __func__,
280-
txid.ToString(), in.prevout.ToStringShort());
281-
break;
282-
}
283-
}
284-
}
285-
286-
TrySignInstantSendLock(*tx);
287-
}
288-
289-
void CInstantSendManager::TrySignInstantSendLock(const CTransaction& tx)
290-
{
291-
const auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend;
292-
293-
for (const auto& in : tx.vin) {
294-
auto id = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in.prevout));
295-
if (!sigman.HasRecoveredSig(llmqType, id, tx.GetHash())) {
296-
return;
297-
}
298-
}
299-
300-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: got all recovered sigs, creating CInstantSendLock\n", __func__,
301-
tx.GetHash().ToString());
302-
303-
CInstantSendLock islock;
304-
islock.txid = tx.GetHash();
305-
for (const auto& in : tx.vin) {
306-
islock.inputs.emplace_back(in.prevout);
307-
}
308-
309-
auto id = islock.GetRequestId();
310-
311-
if (sigman.HasRecoveredSigForId(llmqType, id)) {
312-
return;
313-
}
314-
315-
const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
316-
assert(llmq_params_opt);
317-
const auto quorum = SelectQuorumForSigning(llmq_params_opt.value(), m_chainstate.m_chain, qman, id);
318-
319-
if (!quorum) {
320-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- failed to select quorum. islock id=%s, txid=%s\n",
321-
__func__, id.ToString(), tx.GetHash().ToString());
322-
return;
323-
}
324-
325-
const int cycle_height = quorum->m_quorum_base_block_index->nHeight -
326-
quorum->m_quorum_base_block_index->nHeight % llmq_params_opt->dkgInterval;
327-
islock.cycleHash = quorum->m_quorum_base_block_index->GetAncestor(cycle_height)->GetBlockHash();
328-
329-
{
330-
LOCK(cs_creating);
331-
auto e = creatingInstantSendLocks.emplace(id, std::move(islock));
332-
if (!e.second) {
333-
return;
334-
}
335-
txToCreatingInstantSendLocks.emplace(tx.GetHash(), &e.first->second);
336-
}
337-
338-
sigman.AsyncSignIfMember(llmqType, shareman, id, tx.GetHash(), quorum->m_quorum_base_block_index->GetBlockHash());
339-
}
340-
341-
void CInstantSendManager::HandleNewInstantSendLockRecoveredSig(const llmq::CRecoveredSig& recoveredSig)
342-
{
343-
CInstantSendLockPtr islock;
344-
345-
{
346-
LOCK(cs_creating);
347-
auto it = creatingInstantSendLocks.find(recoveredSig.getId());
348-
if (it == creatingInstantSendLocks.end()) {
349-
return;
350-
}
351-
352-
islock = std::make_shared<CInstantSendLock>(std::move(it->second));
353-
creatingInstantSendLocks.erase(it);
354-
txToCreatingInstantSendLocks.erase(islock->txid);
355-
}
356-
357-
if (islock->txid != recoveredSig.getMsgHash()) {
358-
LogPrintf("CInstantSendManager::%s -- txid=%s: islock conflicts with %s, dropping own version\n", __func__,
359-
islock->txid.ToString(), recoveredSig.getMsgHash().ToString());
360-
return;
361-
}
362-
363-
islock->sig = recoveredSig.sig;
364-
auto hash = ::SerializeHash(*islock);
365-
366-
if (WITH_LOCK(cs_pendingLocks, return pendingInstantSendLocks.count(hash)) || db.KnownInstantSendLock(hash)) {
367-
return;
368-
}
369-
LOCK(cs_pendingLocks);
370-
pendingInstantSendLocks.emplace(hash, std::make_pair(-1, islock));
371-
}
372-
37391
PeerMsgRet CInstantSendManager::ProcessMessage(const CNode& pfrom, PeerManager& peerman, std::string_view msg_type,
37492
CDataStream& vRecv)
37593
{
@@ -1080,67 +798,6 @@ void CInstantSendManager::RemoveConflictingLock(const uint256& islockHash, const
1080798
}
1081799
}
1082800

1083-
void CInstantSendManager::ProcessPendingRetryLockTxs()
1084-
{
1085-
const auto retryTxs = WITH_LOCK(cs_pendingRetry, return pendingRetryTxs);
1086-
1087-
if (retryTxs.empty()) {
1088-
return;
1089-
}
1090-
1091-
if (!IsInstantSendEnabled()) {
1092-
return;
1093-
}
1094-
1095-
int retryCount = 0;
1096-
for (const auto& txid : retryTxs) {
1097-
CTransactionRef tx;
1098-
{
1099-
{
1100-
LOCK(cs_nonLocked);
1101-
auto it = nonLockedTxs.find(txid);
1102-
if (it == nonLockedTxs.end()) {
1103-
continue;
1104-
}
1105-
tx = it->second.tx;
1106-
}
1107-
if (!tx) {
1108-
continue;
1109-
}
1110-
1111-
if (LOCK(cs_creating); txToCreatingInstantSendLocks.count(tx->GetHash())) {
1112-
// we're already in the middle of locking this one
1113-
continue;
1114-
}
1115-
if (IsLocked(tx->GetHash())) {
1116-
continue;
1117-
}
1118-
if (GetConflictingLock(*tx) != nullptr) {
1119-
// should not really happen as we have already filtered these out
1120-
continue;
1121-
}
1122-
}
1123-
1124-
// CheckCanLock is already called by ProcessTx, so we should avoid calling it twice. But we also shouldn't spam
1125-
// the logs when retrying TXs that are not ready yet.
1126-
if (LogAcceptDebug(BCLog::INSTANTSEND)) {
1127-
if (!CheckCanLock(*tx, false, Params().GetConsensus())) {
1128-
continue;
1129-
}
1130-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: retrying to lock\n", __func__,
1131-
tx->GetHash().ToString());
1132-
}
1133-
1134-
ProcessTx(*tx, false, Params().GetConsensus());
1135-
retryCount++;
1136-
}
1137-
1138-
if (retryCount != 0) {
1139-
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- retried %d TXs. nonLockedTxs.size=%d\n", __func__,
1140-
retryCount, WITH_LOCK(cs_nonLocked, return nonLockedTxs.size()));
1141-
}
1142-
}
1143-
1144801
bool CInstantSendManager::AlreadyHave(const CInv& inv) const
1145802
{
1146803
if (!IsInstantSendEnabled()) {
@@ -1254,11 +911,6 @@ bool CInstantSendManager::IsInstantSendEnabled() const
1254911
return !fReindex && !fImporting && spork_manager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED);
1255912
}
1256913

1257-
bool CInstantSendManager::IsInstantSendMempoolSigningEnabled() const
1258-
{
1259-
return !fReindex && !fImporting && spork_manager.GetSporkValue(SPORK_2_INSTANTSEND_ENABLED) == 0;
1260-
}
1261-
1262914
bool CInstantSendManager::RejectConflictingBlocks() const
1263915
{
1264916
if (!m_mn_sync.IsBlockchainSynced()) {

0 commit comments

Comments
 (0)