void CInstantSend::UpdateLockedTransaction(const CTxLockCandidate& txLockCandidate) { // cs_wallet and cs_instantsend should be already locked #ifdef ENABLE_WALLET if (pwalletMain) AssertLockHeld(pwalletMain->cs_wallet); #endif AssertLockHeld(cs_instantsend); uint256 txHash = txLockCandidate.GetHash(); if(!IsLockedInstantSendTransaction(txHash)) return; // not a locked tx, do not update/notify #ifdef ENABLE_WALLET if(pwalletMain && pwalletMain->UpdatedTransaction(txHash)) { // bumping this to update UI nCompleteTXLocks++; // notify an external script once threshold is reached std::string strCmd = GetArg("-instantsendnotify", ""); if(!strCmd.empty()) { boost::replace_all(strCmd, "%s", txHash.GetHex()); boost::thread t(runCommand, strCmd); // thread runs free } } #endif GetMainSignals().NotifyTransactionLock(*txLockCandidate.txLockRequest.tx); LogPrint("instantsend", "CInstantSend::UpdateLockedTransaction -- done, txid=%s\n", txHash.ToString()); }
bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool) { AssertLockHeld(pool.cs); CTxMemPool::setEntries setAncestors; // First check the transaction itself. if (SignalsOptInRBF(entry.GetTx())) { return true; } // If this transaction is not in our mempool, then we can't be sure // we will know about all its inputs. if (!pool.exists(entry.GetTx().GetHash())) { throw std::runtime_error("Cannot determine RBF opt-in signal for non-mempool transaction\n"); } // If all the inputs have nSequence >= maxint-1, it still might be // signaled for RBF if any unconfirmed parents have signaled. uint64_t noLimit = std::numeric_limits<uint64_t>::max(); std::string dummy; pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false); BOOST_FOREACH(CTxMemPool::txiter it, setAncestors) { if (SignalsOptInRBF(it->GetTx())) { return true; } } return false; }
bool CMasternodeBroadcast::CheckOutpoint(int& nDos) { // we are a masternode with the same outpoint (i.e. already activated) and this mnb is ours (matches our Masternode privkey) // so nothing to do here for us if (fMasternodeMode && outpoint == activeMasternode.outpoint && pubKeyMasternode == activeMasternode.pubKeyMasternode) { return false; } AssertLockHeld(cs_main); int nHeight; CollateralStatus err = CheckCollateral(outpoint, pubKeyCollateralAddress, nHeight); if (err == COLLATERAL_UTXO_NOT_FOUND) { LogPrint(MCLog::MN, "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", outpoint.ToStringShort()); return false; } if (err == COLLATERAL_INVALID_AMOUNT) { LogPrint(MCLog::MN, "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should have 1000 DASH, masternode=%s\n", outpoint.ToStringShort()); nDos = 33; return false; } if (err == COLLATERAL_INVALID_PUBKEY) { LogPrint(MCLog::MN, "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should match pubKeyCollateralAddress, masternode=%s\n", outpoint.ToStringShort()); nDos = 33; return false; } if (chainActive.Height() - nHeight + 1 < Params().GetConsensus().nMasternodeMinimumConfirmations) { LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO must have at least %d confirmations, masternode=%s\n", Params().GetConsensus().nMasternodeMinimumConfirmations, outpoint.ToStringShort()); // UTXO is legit but has not enough confirmations. // Maybe we miss few blocks, let this mnb be checked again later. mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); return false; } LogPrint(MCLog::MN, "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO verified\n"); // Verify that sig time is legit, should be at least not earlier than the timestamp of the block // at which collateral became nMasternodeMinimumConfirmations blocks deep. // NOTE: this is not accurate because block timestamp is NOT guaranteed to be 100% correct one. CBlockIndex* pRequiredConfIndex = chainActive[nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations if (pRequiredConfIndex->GetBlockTime() > sigTime) { LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n", sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pRequiredConfIndex->GetBlockTime(), outpoint.ToStringShort(), addr.ToString()); return false; } if (!CheckSignature(nDos)) { LogPrintf("CMasternodeBroadcast::CheckOutpoint -- CheckSignature() failed, masternode=%s\n", outpoint.ToStringShort()); return false; } // remember the block hash when collateral for this masternode had minimum required confirmations nCollateralMinConfBlockHash = pRequiredConfIndex->GetBlockHash(); return true; }
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { AssertLockHeld(cs_main); if (!CheckFinalTx(wtx)) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height()); else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } else { int nDepth = wtx.GetDepthInMainChain(); if (nDepth < 0) return tr("conflicted with a transaction with %1 confirmations").arg(-nDepth); else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline").arg(nDepth); else if (nDepth == 0) return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : ""); else if (nDepth < 6) return tr("%1/unconfirmed").arg(nDepth); else return tr("%1 confirmations").arg(nDepth); } }
void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) { AssertLockHeld(cs); UpdateForRemoveFromMempool(stage, updateDescendants); for (const txiter& it : stage) { removeUnchecked(it, reason); } }
void CNameMemPool::removeConflicts (const CTransaction& tx, std::list<CTransaction>& removed) { AssertLockHeld (pool.cs); if (!tx.IsNamecoin ()) return; BOOST_FOREACH (const CTxOut& txout, tx.vout) { const CNameScript nameOp(txout.scriptPubKey); if (nameOp.isNameOp () && nameOp.getNameOp () == OP_NAME_FIRSTUPDATE) { const valtype& name = nameOp.getOpName (); const NameTxMap::const_iterator mit = mapNameRegs.find (name); if (mit != mapNameRegs.end ()) { const CTxMemPool::txiter mit2 = pool.mapTx.find (mit->second); assert (mit2 != pool.mapTx.end ()); pool.removeRecursive (mit2->GetTx (), removed); } } } }
int CMerkleTx::SetMerkleBranch(const CBlock& block) { AssertLockHeld(cs_main); CBlock blockTmp; // Update the tx's hashBlock hashBlock = block.GetHash(); // Locate the transaction for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++) if (block.vtx[nIndex] == *(CTransaction*)this) break; if (nIndex == (int)block.vtx.size()) { vMerkleBranch.clear(); nIndex = -1; LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n"); return 0; } // Fill in merkle branch GetMerkleBranch(block, nIndex, vMerkleBranch); // Is the tx in a block that's in the main chain BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi == mapBlockIndex.end()) return 0; const CBlockIndex* pindex = (*mi).second; if (!pindex || !chainActive.Contains(pindex)) return 0; return chainActive.Height() - pindex->nHeight + 1; }
bool CGovernanceTriggerManager::AddNewTrigger(uint256 nHash) { AssertLockHeld(governance.cs); // IF WE ALREADY HAVE THIS HASH, RETURN if (mapTrigger.count(nHash)) { LogPrint("gobject", "CGovernanceTriggerManager::AddNewTrigger -- Already have hash, nHash = %s, count = %d, size = %s\n", nHash.GetHex(), mapTrigger.count(nHash), mapTrigger.size()); return false; } CSuperblock_sptr pSuperblock; try { CSuperblock_sptr pSuperblockTmp(new CSuperblock(nHash)); pSuperblock = pSuperblockTmp; } catch (std::exception& e) { LogPrintf("CGovernanceTriggerManager::AddNewTrigger -- Error creating superblock: %s\n", e.what()); return false; } catch (...) { LogPrintf("CGovernanceTriggerManager::AddNewTrigger: Unknown Error creating superblock\n"); return false; } pSuperblock->SetStatus(SEEN_OBJECT_IS_VALID); mapTrigger.insert(std::make_pair(nHash, pSuperblock)); return true; }
void CNameMemPool::addUnchecked (const uint256& hash, const CTxMemPoolEntry& entry) { AssertLockHeld (pool.cs); if (entry.isNameNew ()) { const valtype& newHash = entry.getNameNewHash (); const NameTxMap::const_iterator mit = mapNameNews.find (newHash); if (mit != mapNameNews.end ()) assert (mit->second == hash); else mapNameNews.insert (std::make_pair (newHash, hash)); } if (entry.isNameRegistration ()) { const valtype& name = entry.getName (); assert (mapNameRegs.count (name) == 0); mapNameRegs.insert (std::make_pair (name, hash)); } if (entry.isNameUpdate ()) { const valtype& name = entry.getName (); assert (mapNameUpdates.count (name) == 0); mapNameUpdates.insert (std::make_pair (name, hash)); } }
bool CSuperblockManager::GetBestSuperblock(CSuperblock_sptr& pSuperblockRet, int nBlockHeight) { if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) { return false; } AssertLockHeld(governance.cs); std::vector<CSuperblock_sptr> vecTriggers = triggerman.GetActiveTriggers(); int nYesCount = 0; for (const auto& pSuperblock : vecTriggers) { if (!pSuperblock || nBlockHeight != pSuperblock->GetBlockHeight()) { continue; } CGovernanceObject* pObj = pSuperblock->GetGovernanceObject(); if (!pObj) { continue; } // DO WE HAVE A NEW WINNER? int nTempYesCount = pObj->GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING); if (nTempYesCount > nYesCount) { nYesCount = nTempYesCount; pSuperblockRet = pSuperblock; } } return nYesCount > 0; }
RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool) { AssertLockHeld(pool.cs); CTxMemPool::setEntries setAncestors; // First check the transaction itself. if (SignalsOptInRBF(tx)) { return RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125; } // If this transaction is not in our mempool, then we can't be sure // we will know about all its inputs. if (!pool.exists(tx.GetHash())) { return RBF_TRANSACTIONSTATE_UNKNOWN; } // If all the inputs have nSequence >= maxint-1, it still might be // signaled for RBF if any unconfirmed parents have signaled. uint64_t noLimit = std::numeric_limits<uint64_t>::max(); std::string dummy; CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash()); pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false); BOOST_FOREACH(CTxMemPool::txiter it, setAncestors) { if (SignalsOptInRBF(it->GetTx())) { return RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125; } } return RBF_TRANSACTIONSTATE_FINAL; }
void CTxMemPool::trackPackageRemoved(const CFeeRate& rate) { AssertLockHeld(cs); if (rate.GetFeePerK() > rollingMinimumFeeRate) { rollingMinimumFeeRate = rate.GetFeePerK(); blockSinceLastRollingFeeBump = false; } }
void CGovernanceTriggerManager::CleanAndRemove() { AssertLockHeld(governance.cs); // Remove triggers that are invalid or expired LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- mapTrigger.size() = %d\n", mapTrigger.size()); trigger_m_it it = mapTrigger.begin(); while (it != mapTrigger.end()) { bool remove = false; CGovernanceObject* pObj = nullptr; CSuperblock_sptr& pSuperblock = it->second; if (!pSuperblock) { LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- NULL superblock marked for removal\n"); remove = true; } else { pObj = governance.FindGovernanceObject(it->first); if (!pObj || pObj->GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) { LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Unknown or non-trigger superblock\n"); pSuperblock->SetStatus(SEEN_OBJECT_ERROR_INVALID); } LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- superblock status = %d\n", pSuperblock->GetStatus()); switch (pSuperblock->GetStatus()) { case SEEN_OBJECT_ERROR_INVALID: case SEEN_OBJECT_UNKNOWN: LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Unknown or invalid trigger found\n"); remove = true; break; case SEEN_OBJECT_IS_VALID: case SEEN_OBJECT_EXECUTED: remove = pSuperblock->IsExpired(); break; default: break; } } LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- %smarked for removal\n", remove ? "" : "NOT "); if (remove) { std::string strDataAsPlainString = "NULL"; if (pObj) { strDataAsPlainString = pObj->GetDataAsPlainString(); } LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Removing trigger object %s\n", strDataAsPlainString); // mark corresponding object for deletion if (pObj) { pObj->fCachedDelete = true; if (pObj->nDeletionTime == 0) { pObj->nDeletionTime = GetAdjustedTime(); } } // delete the trigger mapTrigger.erase(it++); } else { ++it; } } }
int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const { AssertLockHeld(cs_main); int nResult = GetDepthInMainChainINTERNAL(pindexRet); if (nResult == 0 && !mempool.exists(GetHash())) return -1; // Not in chain, not in mempool return nResult; }
bool CMasternodeBroadcast::SimpleCheck(int& nDos) { nDos = 0; AssertLockHeld(cs_main); // make sure addr is valid if (!IsValidNetAddr()) { LogPrint(MCLog::MN, "CMasternodeBroadcast::SimpleCheck -- Invalid addr, rejected: masternode=%s addr=%s\n", outpoint.ToStringShort(), addr.ToString()); return false; } // make sure signature isn't in the future (past is OK) if (sigTime > GetAdjustedTime() + 60 * 60) { LogPrint(MCLog::MN, "CMasternodeBroadcast::SimpleCheck -- Signature rejected, too far into the future: masternode=%s\n", outpoint.ToStringShort()); nDos = 1; return false; } // empty ping or incorrect sigTime/unknown blockhash if (!lastPing || !lastPing.SimpleCheck(nDos)) { // one of us is probably forked or smth, just mark it as expired and check the rest of the rules nActiveState = MASTERNODE_EXPIRED; } if (nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) { LogPrintf("CMasternodeBroadcast::SimpleCheck -- outdated Masternode: masternode=%s nProtocolVersion=%d\n", outpoint.ToStringShort(), nProtocolVersion); nActiveState = MASTERNODE_UPDATE_REQUIRED; } CScript pubkeyScript; pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID()); if (pubkeyScript.size() != 25) { LogPrint(MCLog::MN, "CMasternodeBroadcast::SimpleCheck -- pubKeyCollateralAddress has the wrong size\n"); nDos = 100; return false; } CScript pubkeyScript2; pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID()); if (pubkeyScript2.size() != 25) { LogPrint(MCLog::MN, "CMasternodeBroadcast::SimpleCheck -- pubKeyMasternode has the wrong size\n"); nDos = 100; return false; } int mainnetDefaultPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPort(); if (Params().NetworkIDString() == CBaseChainParams::MAIN) { if (addr.GetPort() != mainnetDefaultPort) return false; } else if (addr.GetPort() == mainnetDefaultPort) return false; return true; }
bool CMasternodeBroadcast::Update(CMasternode* pmn, int& nDos, CConnman& connman) { nDos = 0; AssertLockHeld(cs_main); if (pmn->sigTime == sigTime && !fRecovery) { // mapSeenMasternodeBroadcast in CMasternodeMan::CheckMnbAndUpdateMasternodeList should filter legit duplicates // but this still can happen if we just started, which is ok, just do nothing here. return false; } // this broadcast is older than the one that we already have - it's bad and should never happen // unless someone is doing something fishy if (pmn->sigTime > sigTime) { LogPrint(MCLog::MN, "CMasternodeBroadcast::Update -- Bad sigTime %d (existing broadcast is at %d) for Masternode %s %s\n", sigTime, pmn->sigTime, outpoint.ToStringShort(), addr.ToString()); return false; } pmn->Check(); // masternode is banned by PoSe if (pmn->IsPoSeBanned()) { LogPrint(MCLog::MN, "CMasternodeBroadcast::Update -- Banned by PoSe, masternode=%s\n", outpoint.ToStringShort()); return false; } // IsVnAssociatedWithPubkey is validated once in CheckOutpoint, after that they just need to match if (pmn->pubKeyCollateralAddress != pubKeyCollateralAddress) { LogPrint(MCLog::MN, "CMasternodeBroadcast::Update -- Got mismatched pubKeyCollateralAddress and outpoint\n"); nDos = 33; return false; } if (!CheckSignature(nDos)) { LogPrint(MCLog::MN, "CMasternodeBroadcast::Update -- CheckSignature() failed, masternode=%s\n", outpoint.ToStringShort()); return false; } // if ther was no masternode broadcast recently or if it matches our Masternode privkey... if (!pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS) || (fMasternodeMode && pubKeyMasternode == activeMasternode.pubKeyMasternode)) { // take the newest entry LogPrint(MCLog::MN, "CMasternodeBroadcast::Update -- Got UPDATED Masternode entry: addr=%s\n", addr.ToString()); if (pmn->UpdateFromNewBroadcast(*this, connman)) { pmn->Check(); Relay(connman); } masternodeSync.BumpAssetLastTime("CMasternodeBroadcast::Update"); } return true; }
bool CInstantSend::ProcessOrphanTxLockVote(const CTxLockVote& vote) { // cs_main, cs_wallet and cs_instantsend should be already locked AssertLockHeld(cs_main); #ifdef ENABLE_WALLET if (pwalletMain) AssertLockHeld(pwalletMain->cs_wallet); #endif AssertLockHeld(cs_instantsend); uint256 txHash = vote.GetTxHash(); // We shouldn't process orphan votes without a valid tx lock candidate std::map<uint256, CTxLockCandidate>::iterator it = mapTxLockCandidates.find(txHash); if(it == mapTxLockCandidates.end() || !it->second.txLockRequest) return false; // this shouldn never happen CTxLockCandidate& txLockCandidate = it->second; if (txLockCandidate.IsTimedOut()) { LogPrint("instantsend", "CInstantSend::%s -- too late, Transaction Lock timed out, txid=%s\n", __func__, txHash.ToString()); return false; } LogPrint("instantsend", "CInstantSend::%s -- Transaction Lock Vote, txid=%s\n", __func__, txHash.ToString()); UpdateVotedOutpoints(vote, txLockCandidate); if(!txLockCandidate.AddVote(vote)) { // this should never happen return false; } int nSignatures = txLockCandidate.CountVotes(); int nSignaturesMax = txLockCandidate.txLockRequest.GetMaxSignatures(); LogPrint("instantsend", "CInstantSend::%s -- Transaction Lock signatures count: %d/%d, vote hash=%s\n", __func__, nSignatures, nSignaturesMax, vote.GetHash().ToString()); return true; }
std::vector<CTxMemPool::indexed_transaction_set::const_iterator> CTxMemPool::GetSortedDepthAndScore() const { std::vector<indexed_transaction_set::const_iterator> iters; AssertLockHeld(cs); iters.reserve(mapTx.size()); for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) { iters.push_back(mi); } std::sort(iters.begin(), iters.end(), DepthAndScoreComparator()); return iters; }
bool CFeeBumper::commit(CWallet *pWallet) { AssertLockHeld(pWallet->cs_wallet); if (!vErrors.empty() || currentResult != BumpFeeResult::OK) { return false; } if (txid.IsNull() || !pWallet->mapWallet.count(txid)) { vErrors.push_back("Invalid or non-wallet transaction id"); currentResult = BumpFeeResult::MISC_ERROR; return false; } CWalletTx& oldWtx = pWallet->mapWallet[txid]; // make sure the transaction still has no descendants and hasen't been mined in the meantime if (!preconditionChecks(pWallet, oldWtx)) { return false; } CWalletTx wtxBumped(pWallet, MakeTransactionRef(std::move(mtx))); // commit/broadcast the tx CReserveKey reservekey(pWallet); wtxBumped.mapValue = oldWtx.mapValue; wtxBumped.mapValue["replaces_txid"] = oldWtx.GetHash().ToString(); wtxBumped.vOrderForm = oldWtx.vOrderForm; wtxBumped.strFromAccount = oldWtx.strFromAccount; wtxBumped.fTimeReceivedIsTxTime = true; wtxBumped.fFromMe = true; CValidationState state; if (!pWallet->CommitTransaction(wtxBumped, reservekey, g_connman.get(), state)) { // NOTE: CommitTransaction never returns false, so this should never happen. vErrors.push_back(strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason())); return false; } bumpedTxid = wtxBumped.GetHash(); if (state.IsInvalid()) { // This can happen if the mempool rejected the transaction. Report // what happened in the "errors" response. vErrors.push_back(strprintf("Error: The transaction was rejected: %s", FormatStateMessage(state))); } // mark the original tx as bumped if (!pWallet->MarkReplaced(oldWtx.GetHash(), wtxBumped.GetHash())) { // TODO: see if JSON-RPC has a standard way of returning a response // along with an exception. It would be good to return information about // wtxBumped to the caller even if marking the original transaction // replaced does not succeed for some reason. vErrors.push_back("Error: Created new bumpfee transaction but could not mark the original transaction as replaced."); } return true; }
void CDeterministicMNManager::CleanupCache(int nHeight) { AssertLockHeld(cs); std::vector<uint256> toDelete; for (const auto& p : mnListsCache) { if (p.second.GetHeight() + LISTS_CACHE_SIZE < nHeight) { toDelete.emplace_back(p.first); } } for (const auto& h : toDelete) { mnListsCache.erase(h); } }
std::vector<CSuperblock_sptr> CGovernanceTriggerManager::GetActiveTriggers() { AssertLockHeld(governance.cs); std::vector<CSuperblock_sptr> vecResults; // LOOK AT THESE OBJECTS AND COMPILE A VALID LIST OF TRIGGERS for (const auto& pair : mapTrigger) { CGovernanceObject* pObj = governance.FindGovernanceObject(pair.first); if (pObj) { vecResults.push_back(pair.second); } } return vecResults; }
void CInstantSend::Vote(const uint256& txHash, CConnman& connman) { AssertLockHeld(cs_main); LOCK(cs_instantsend); CTxLockRequest dummyRequest; CTxLockCandidate txLockCandidate(dummyRequest); { LOCK(cs_instantsend); auto itLockCandidate = mapTxLockCandidates.find(txHash); if (itLockCandidate == mapTxLockCandidates.end()) return; txLockCandidate = itLockCandidate->second; Vote(txLockCandidate, connman); } TryToFinalizeLockCandidate(txLockCandidate); }
void CTxMemPool::removeConflicts(const CTransaction &tx) { // Remove transactions which depend on inputs of tx, recursively AssertLockHeld(cs); for (const CTxIn &txin : tx.vin) { auto it = mapNextTx.find(txin.prevout); if (it != mapNextTx.end()) { const CTransaction &txConflict = *it->second; if (txConflict != tx) { ClearPrioritisation(txConflict.GetHash()); removeRecursive(txConflict, MemPoolRemovalReason::CONFLICT); } } } }
int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const { if (hashBlock.IsNull() || nIndex == -1) return 0; AssertLockHeld(cs_main); // Find the block it claims to be in BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi == mapBlockIndex.end()) return 0; CBlockIndex* pindex = (*mi).second; if (!pindex || !chainActive.Contains(pindex)) return 0; pindexRet = pindex; return chainActive.Height() - pindex->nHeight + 1; }
void CNameMemPool::remove (const CTxMemPoolEntry& entry) { AssertLockHeld (pool.cs); if (entry.isNameRegistration ()) { const NameTxMap::iterator mit = mapNameRegs.find (entry.getName ()); assert (mit != mapNameRegs.end ()); mapNameRegs.erase (mit); } if (entry.isNameUpdate ()) { const NameTxMap::iterator mit = mapNameUpdates.find (entry.getName ()); assert (mit != mapNameUpdates.end ()); mapNameUpdates.erase (mit); } }
void CNameMemPool::removeUnexpireConflicts (const std::set<valtype>& unexpired, std::list<CTransaction>& removed) { AssertLockHeld (pool.cs); BOOST_FOREACH (const valtype& name, unexpired) { LogPrint ("names", "unexpired: %s, mempool: %u\n", ValtypeToString (name).c_str (), mapNameRegs.count (name)); const NameTxMap::const_iterator mit = mapNameRegs.find (name); if (mit != mapNameRegs.end ()) { const CTxMemPool::txiter mit2 = pool.mapTx.find (mit->second); assert (mit2 != pool.mapTx.end ()); pool.removeRecursive (mit2->GetTx (), removed); } }
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, const CPubKey& pubkey, int& nHeightRet) { AssertLockHeld(cs_main); Coin coin; if (!GetUTXOCoin(outpoint, coin)) { return COLLATERAL_UTXO_NOT_FOUND; } if (coin.out.nValue != 25000 * COIN) { return COLLATERAL_INVALID_AMOUNT; } if (pubkey == CPubKey() || coin.out.scriptPubKey != GetScriptForDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubkey.GetID()))))) { return COLLATERAL_INVALID_PUBKEY; } nHeightRet = coin.nHeight; return COLLATERAL_OK; }
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { AssertLockHeld(cs_main); if (!wtx.IsFinal()) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) return tr("Open for %n block(s)", "", nBestHeight - wtx.nLockTime); else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } else { int nDepth = wtx.GetDepthInMainChain(); if (nDepth < 0) return tr("conflicted"); else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline").arg(nDepth); else if (nDepth < 10) return tr("%1/unconfirmed").arg(nDepth); else return tr("%1 confirmations").arg(nDepth); }; }
void CInstantSend::UpdateVotedOutpoints(const CTxLockVote& vote, CTxLockCandidate& txLockCandidate) { AssertLockHeld(cs_instantsend); uint256 txHash = vote.GetTxHash(); std::map<COutPoint, std::set<uint256> >::iterator it1 = mapVotedOutpoints.find(vote.GetOutpoint()); if(it1 != mapVotedOutpoints.end()) { for (const auto& hash : it1->second) { if(hash != txHash) { // same outpoint was already voted to be locked by another tx lock request, // let's see if it was the same masternode who voted on this outpoint // for another tx lock request std::map<uint256, CTxLockCandidate>::iterator it2 = mapTxLockCandidates.find(hash); if(it2 !=mapTxLockCandidates.end() && it2->second.HasMasternodeVoted(vote.GetOutpoint(), vote.GetMasternodeOutpoint())) { // yes, it was the same masternode LogPrintf("CInstantSend::%s -- masternode sent conflicting votes! %s\n", __func__, vote.GetMasternodeOutpoint().ToStringShort()); // mark both Lock Candidates as attacked, none of them should complete, // or at least the new (current) one shouldn't even // if the second one was already completed earlier txLockCandidate.MarkOutpointAsAttacked(vote.GetOutpoint()); it2->second.MarkOutpointAsAttacked(vote.GetOutpoint()); // apply maximum PoSe ban score to this masternode i.e. PoSe-ban it instantly mnodeman.PoSeBan(vote.GetMasternodeOutpoint()); // NOTE: This vote must be relayed further to let all other nodes know about such // misbehaviour of this masternode. This way they should also be able to construct // conflicting lock and PoSe-ban this masternode. } } } // store all votes, regardless of them being sent by malicious masternode or not it1->second.insert(txHash); } else { mapVotedOutpoints.emplace(vote.GetOutpoint(), std::set<uint256>({txHash})); } }
void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) { AssertLockHeld(cs_KeyStore); CKeyID key_id = pubkey.GetID(); // We must actually know about this key already. assert(HaveKey(key_id) || mapWatchKeys.count(key_id)); // This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH // outputs. Technically P2WPKH outputs don't have a redeemscript to be // spent. However, our current IsMine logic requires the corresponding // P2SH-P2WPKH redeemscript to be present in the wallet in order to accept // payment even to P2WPKH outputs. // Also note that having superfluous scripts in the keystore never hurts. // They're only used to guide recursion in signing and IsMine logic - if // a script is present but we can't do anything with it, it has no effect. // "Implicitly" refers to fact that scripts are derived automatically from // existing keys, and are present in memory, even without being explicitly // loaded (e.g. from a file). if (pubkey.IsCompressed()) { CScript script = GetScriptForDestination(WitnessV0KeyHash(key_id)); // This does not use AddCScript, as it may be overridden. CScriptID id(script); mapScripts[id] = std::move(script); } }