mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Only sign ChainLocks when all included TXs are "safe"
Safe means that the TX is either ixlocked or known since at least 10 minutes. Also change miner code to only include safe TXs in block templates.
This commit is contained in:
parent
96291e7a0f
commit
2a7a5c6338
@ -4,6 +4,7 @@
|
||||
|
||||
#include "quorums.h"
|
||||
#include "quorums_chainlocks.h"
|
||||
#include "quorums_instantsend.h"
|
||||
#include "quorums_signing.h"
|
||||
#include "quorums_utils.h"
|
||||
|
||||
@ -262,6 +263,61 @@ void CChainLocksHandler::TrySignChainTip()
|
||||
}
|
||||
}
|
||||
|
||||
LogPrintf("CChainLocksHandler::%s -- trying to sign %s, height=%d\n", __func__, pindex->GetBlockHash().ToString(), pindex->nHeight);
|
||||
|
||||
// When the new IX system is activated, we only try to ChainLock blocks which include safe transactions. A TX is
|
||||
// considered safe when it is ixlocked or at least known since 10 minutes (from mempool or block). These checks are
|
||||
// performed for the tip (which we try to sign) and the previous 5 blocks. If a ChainLocked block is found on the
|
||||
// way down, we consider all TXs to be safe.
|
||||
if (IsNewInstantSendEnabled() && sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
|
||||
auto pindexWalk = pindex;
|
||||
while (pindexWalk) {
|
||||
if (pindex->nHeight - pindexWalk->nHeight > 5) {
|
||||
// no need to check further down, 6 confs is safe to assume that TXs below this height won't be
|
||||
// ixlocked anymore if they aren't already
|
||||
LogPrintf("CChainLocksHandler::%s -- tip and previous 5 blocks all safe\n", __func__);
|
||||
break;
|
||||
}
|
||||
if (HasChainLock(pindexWalk->nHeight, pindexWalk->GetBlockHash())) {
|
||||
// we don't care about ixlocks for TXs that are ChainLocked already
|
||||
LogPrintf("CChainLocksHandler::%s -- chainlock at height %d \n", __func__, pindexWalk->nHeight);
|
||||
break;
|
||||
}
|
||||
|
||||
decltype(blockTxs.begin()->second) txids;
|
||||
{
|
||||
LOCK(cs);
|
||||
auto it = blockTxs.find(pindexWalk->GetBlockHash());
|
||||
if (it == blockTxs.end()) {
|
||||
// this should actually not happen as NewPoWValidBlock should have been called before
|
||||
LogPrintf("CChainLocksHandler::%s -- blockTxs for %s not found\n", __func__,
|
||||
pindexWalk->GetBlockHash().ToString());
|
||||
return;
|
||||
}
|
||||
txids = it->second;
|
||||
}
|
||||
|
||||
for (auto& txid : *txids) {
|
||||
int64_t txAge = 0;
|
||||
{
|
||||
LOCK(cs);
|
||||
auto it = txFirstSeenTime.find(txid);
|
||||
if (it != txFirstSeenTime.end()) {
|
||||
txAge = GetAdjustedTime() - it->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (txAge < WAIT_FOR_IXLOCK_TIMEOUT && !quorumInstantSendManager->IsLocked(txid)) {
|
||||
LogPrintf("CChainLocksHandler::%s -- not signing block %s due to TX %s not being ixlocked and not old enough. age=%d\n", __func__,
|
||||
pindexWalk->GetBlockHash().ToString(), txid.ToString(), txAge);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pindexWalk = pindexWalk->pprev;
|
||||
}
|
||||
}
|
||||
|
||||
uint256 requestId = ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, pindex->nHeight));
|
||||
uint256 msgHash = pindex->GetBlockHash();
|
||||
|
||||
@ -324,6 +380,30 @@ void CChainLocksHandler::SyncTransaction(const CTransaction& tx, const CBlockInd
|
||||
txFirstSeenTime.emplace(tx.GetHash(), curTime);
|
||||
}
|
||||
|
||||
bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid)
|
||||
{
|
||||
if (!sporkManager.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED) || !sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
|
||||
return true;
|
||||
}
|
||||
if (!IsNewInstantSendEnabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t txAge = 0;
|
||||
{
|
||||
LOCK(cs);
|
||||
auto it = txFirstSeenTime.find(txid);
|
||||
if (it != txFirstSeenTime.end()) {
|
||||
txAge = GetAdjustedTime() - it->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (txAge < WAIT_FOR_IXLOCK_TIMEOUT && !quorumInstantSendManager->IsLocked(txid)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// WARNING: cs_main and cs should not be held!
|
||||
void CChainLocksHandler::EnforceBestChainLock()
|
||||
{
|
||||
|
@ -46,6 +46,9 @@ class CChainLocksHandler : public CRecoveredSigsListener
|
||||
static const int64_t CLEANUP_INTERVAL = 1000 * 30;
|
||||
static const int64_t CLEANUP_SEEN_TIMEOUT = 24 * 60 * 60 * 1000;
|
||||
|
||||
// how long to wait for ixlocks until we consider a block with non-ixlocked TXs to be safe to sign
|
||||
static const int64_t WAIT_FOR_IXLOCK_TIMEOUT = 10 * 60;
|
||||
|
||||
private:
|
||||
CScheduler* scheduler;
|
||||
CCriticalSection cs;
|
||||
@ -94,6 +97,8 @@ public:
|
||||
bool HasChainLock(int nHeight, const uint256& blockHash);
|
||||
bool HasConflictingChainLock(int nHeight, const uint256& blockHash);
|
||||
|
||||
bool IsTxSafeForMining(const uint256& txid);
|
||||
|
||||
private:
|
||||
// these require locks to be held already
|
||||
bool InternalHasChainLock(int nHeight, const uint256& blockHash);
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "evo/deterministicmns.h"
|
||||
|
||||
#include "llmq/quorums_blockprocessor.h"
|
||||
#include "llmq/quorums_chainlocks.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/thread.hpp>
|
||||
@ -453,6 +454,11 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!llmq::chainLocksHandler->IsTxSafeForMining(mi->GetTx().GetHash())) {
|
||||
++mi;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now that mi is not stale, determine which transaction to evaluate:
|
||||
// the next entry from mapTx, or the best from mapModifiedTx?
|
||||
bool fUsingModified = false;
|
||||
@ -601,6 +607,10 @@ void BlockAssembler::addPriorityTxs()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!llmq::chainLocksHandler->IsTxSafeForMining(iter->GetTx().GetHash())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this tx fits in the block add it, otherwise keep looping
|
||||
if (TestForBlock(iter)) {
|
||||
AddToBlock(iter);
|
||||
|
Loading…
Reference in New Issue
Block a user