Skip to content

Commit dd54011

Browse files
committed
refactor: move inexpensive checks earlier in ProcessInstantSendLock()
It's faster to check the InstantSend database than to search for a transaction and the block that included it, so allow that faster bail out. Additionally, we'll do some additional things: * Assign the success of `GetTransaction` to `found_transaction` to mark the two different processing paths taken when we know or don't know the transaction associated with the ISLock * Invert an if-else block to improve reading * Push down the networking requests to the tail end of the function as they are independent of the changes made by `ProcessInstantSendLock()` * The `peerman` passed to `RemoveMempoolConflictsForLock()` will be sorted by the next commit Review with `git log -p -n1 --color-moved=dimmed_zebra`.
1 parent c86d886 commit dd54011

File tree

1 file changed

+29
-30
lines changed

1 file changed

+29
-30
lines changed

src/instantsend/instantsend.cpp

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -353,18 +353,32 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, PeerManager& peerm
353353
{
354354
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: processing islock, peer=%d\n",
355355
__func__, islock->txid.ToString(), hash.ToString(), from);
356+
356357
if (m_signer) {
357358
m_signer->ClearLockFromQueue(islock);
358359
}
359360
if (db.KnownInstantSendLock(hash)) {
360361
return;
361362
}
362363

364+
if (const auto sameTxIsLock = db.GetInstantSendLockByTxid(islock->txid)) {
365+
// can happen, nothing to do
366+
return;
367+
}
368+
for (const auto& in : islock->inputs) {
369+
const auto sameOutpointIsLock = db.GetInstantSendLockByInput(in);
370+
if (sameOutpointIsLock != nullptr) {
371+
LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: conflicting outpoint in islock. input=%s, other islock=%s, peer=%d\n", __func__,
372+
islock->txid.ToString(), hash.ToString(), in.ToStringShort(), ::SerializeHash(*sameOutpointIsLock).ToString(), from);
373+
}
374+
}
375+
363376
uint256 hashBlock{};
364377
const auto tx = GetTransaction(nullptr, &mempool, islock->txid, Params().GetConsensus(), hashBlock);
365378
const CBlockIndex* pindexMined{nullptr};
379+
const bool found_transaction{tx != nullptr};
366380
// we ignore failure here as we must be able to propagate the lock even if we don't have the TX locally
367-
if (tx && !hashBlock.IsNull()) {
381+
if (found_transaction && !hashBlock.IsNull()) {
368382
pindexMined = WITH_LOCK(::cs_main, return m_chainstate.m_blockman.LookupBlockIndex(hashBlock));
369383

370384
// Let's see if the TX that was locked by this islock is already mined in a ChainLocked block. If yes,
@@ -376,55 +390,40 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, PeerManager& peerm
376390
}
377391
}
378392

379-
const auto sameTxIsLock = db.GetInstantSendLockByTxid(islock->txid);
380-
if (sameTxIsLock != nullptr) {
381-
// can happen, nothing to do
382-
return;
383-
}
384-
for (const auto& in : islock->inputs) {
385-
const auto sameOutpointIsLock = db.GetInstantSendLockByInput(in);
386-
if (sameOutpointIsLock != nullptr) {
387-
LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: conflicting outpoint in islock. input=%s, other islock=%s, peer=%d\n", __func__,
388-
islock->txid.ToString(), hash.ToString(), in.ToStringShort(), ::SerializeHash(*sameOutpointIsLock).ToString(), from);
389-
}
390-
}
391-
392-
if (tx == nullptr) {
393-
// put it in a separate pending map and try again later
394-
LOCK(cs_pendingLocks);
395-
pendingNoTxInstantSendLocks.try_emplace(hash, std::make_pair(from, islock));
396-
} else {
393+
if (found_transaction) {
397394
db.WriteNewInstantSendLock(hash, islock);
398395
if (pindexMined) {
399396
db.WriteInstantSendLockMined(hash, pindexMined->nHeight);
400397
}
398+
} else {
399+
// put it in a separate pending map and try again later
400+
LOCK(cs_pendingLocks);
401+
pendingNoTxInstantSendLocks.try_emplace(hash, std::make_pair(from, islock));
401402
}
402403

403404
// This will also add children TXs to pendingRetryTxs
404405
RemoveNonLockedTx(islock->txid, true);
405406
// We don't need the recovered sigs for the inputs anymore. This prevents unnecessary propagation of these sigs.
406407
// We only need the ISLOCK from now on to detect conflicts
407408
TruncateRecoveredSigsForInputs(*islock);
408-
409-
CInv inv(MSG_ISDLOCK, hash);
410-
if (tx != nullptr) {
411-
peerman.RelayInvFiltered(inv, *tx, ISDLOCK_PROTO_VERSION);
412-
} else {
413-
// we don't have the TX yet, so we only filter based on txid. Later when that TX arrives, we will re-announce
414-
// with the TX taken into account.
415-
peerman.RelayInvFiltered(inv, islock->txid, ISDLOCK_PROTO_VERSION);
416-
}
417-
418409
ResolveBlockConflicts(hash, *islock);
419410

420-
if (tx != nullptr) {
411+
if (found_transaction) {
421412
RemoveMempoolConflictsForLock(peerman, hash, *islock);
422413
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- notify about lock %s for tx %s\n", __func__,
423414
hash.ToString(), tx->GetHash().ToString());
424415
GetMainSignals().NotifyTransactionLock(tx, islock);
425416
// bump mempool counter to make sure newly locked txes are picked up by getblocktemplate
426417
mempool.AddTransactionsUpdated(1);
418+
}
419+
420+
CInv inv(MSG_ISDLOCK, hash);
421+
if (found_transaction) {
422+
peerman.RelayInvFiltered(inv, *tx, ISDLOCK_PROTO_VERSION);
427423
} else {
424+
// we don't have the TX yet, so we only filter based on txid. Later when that TX arrives, we will re-announce
425+
// with the TX taken into account.
426+
peerman.RelayInvFiltered(inv, islock->txid, ISDLOCK_PROTO_VERSION);
428427
peerman.AskPeersForTransaction(islock->txid, /*is_masternode=*/m_signer != nullptr);
429428
}
430429
}

0 commit comments

Comments
 (0)