From d93f7556396af67977c37fa76b81a2a2dfde2e28 Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 26 May 2026 08:31:34 -0500 Subject: [PATCH 1/8] Merge #7332: fix: remove cs_main from MaybePunishNodeForTx, missing changes from #19607 eb769abfe6b3606f9eb148effee2fd3c03707a0f fix: remove cs_main from PeerManagerImpl::MaybePunishNodeForTx, missing changes from #19607 (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented Helper MaybePunishNodeForTx has been introduced when bitcoin#19607 is done, it caused missing changes. ## What was done? Removed cs_main from MaybePunishNodeForTx ## How Has This Been Tested? N/A ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: PastaPastaPasta: utACK eb769abfe6b3606f9eb148effee2fd3c03707a0f Tree-SHA512: ce9b26d5dd3036d1b8b5ff7f302e813b6c3e776f0132d8cdca5ccabbd9f485fd93cd55629c73d576362723f6f35fcc528c4be0ad3d3ae64aca6dd4546d913cbd --- src/net_processing.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index eeff7d1f5d85..c9aae000e50c 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1980,11 +1980,8 @@ bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationStat break; // The node is providing invalid data: case TxValidationResult::TX_CONSENSUS: - { - LOCK(cs_main); - Misbehaving(nodeid, 100); - return true; - } + Misbehaving(nodeid, 100); + return true; // Conflicting (but not necessarily invalid) data or different policy: case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE: case TxValidationResult::TX_INPUTS_NOT_STANDARD: From 47fa6316064c2958bc3708fe507c6040364e488f Mon Sep 17 00:00:00 2001 From: pasta Date: Sat, 13 Jun 2026 01:31:09 -0500 Subject: [PATCH 2/8] Merge #7352: perf: optimize division to uint32 to make re-target-pow calculation much faster e8435d38fd33bffbd922f7db5be1ade49ad0ed9c test: add regression test for faster division of base_uint<256> to uint32_t (Konstantin Akimov) de1e56a45f45ea9e8b2643f394b3d4097c34c09d perf: optimize division to uint32 to make re-target-pow calculation much faster (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented Dash retargets difficulty every block via DarkGravityWave (24-block loop), so every header processed during sync runs several 256-bit divisions. Bitcoin only retargets once per 2016 blocks. Every division in DGW is by a small integer (nCountBlocks+1) * nTargetTimespan (3600). But the code routes through the only available overload, `operator/=(const base_uint&)`, which does bit-by-bit long division: ~224 iterations, each doing a full-width `div >>= 1` During header sync up to 35% of CPU is wasted on this division on release build (accordingly `perf`): ``` 20.36% d-msghand dash-qt [.] base_uint<256u>::operator>>=(unsigned int) 15.00% d-msghand dash-qt [.] base_uint<256u>::operator/=(base_uint<256u> const&) ``` ## What was done? Implemented optimization for division to unsigned values that could fit inside uint32_t. ## How Has This Been Tested? Got GUIX build from changes in this PR and develop: ``` [develop] 5af9f5754e25/src/qt/dash-qt -datadir=/tmp/dd -reindex real 7m42.152s user 7m0.396s sys 0m3.328s [PR] 8608a3c3bbcd/src/qt/dash-qt -datadir=/tmp/dd -reindex real 4m17.294s user 2m55.474s sys 0m2.731s ``` Perf stats are updated as expected: ``` - 1.61% 0.06% d-msghand dash-qt [.] base_uint<256u>::operator/=(base_uint<256u> const&) - 1.55% base_uint<256u>::operator/=(base_uint<256u> const&) 0.92% base_uint<256u>::operator>>=(unsigned int) + 1.48% 0.57% d-msghand dash-qt [.] base_uint<256u>::operator>>=(unsigned int) ``` So total header sync just a half of the time. Please note, that header sync will be slightly slower due to https://github.com/dashpay/dash/pull/7320 so overall win is smaller. ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK e8435d38fd33bffbd922f7db5be1ade49ad0ed9c Tree-SHA512: 797c446cbfad6a1eecb98bee893d530e88db7576d0d15faa36c0d9ccb6d3872313c29f977194ba42cfdedf837a7227018dc750fa87b1f376106831204b08f650 --- src/arith_uint256.cpp | 18 ++++++++++++++++++ src/arith_uint256.h | 2 ++ src/test/arith_uint256_tests.cpp | 13 +++++++++++++ 3 files changed, 33 insertions(+) diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index e614102de3f9..f94bd5f2b59c 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -5,6 +5,7 @@ #include +#include #include #include @@ -79,6 +80,23 @@ base_uint& base_uint::operator*=(const base_uint& b) return *this; } +template +base_uint& base_uint::operator/=(uint64_t b32) +{ + if (b32 == 0) + throw uint_error("Division by zero"); + if (b32 > std::numeric_limits::max()) { + return *this /= base_uint(b32); + } + uint64_t rem = 0; + for (int i = WIDTH - 1; i >= 0; --i) { + uint64_t cur = (rem << 32) | pn[i]; + pn[i] = static_cast(cur / b32); + rem = cur % b32; + } + return *this; +} + template base_uint& base_uint::operator/=(const base_uint& b) { diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 4950bda3d550..8c0ef0c5b3d6 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -160,6 +160,7 @@ class base_uint base_uint& operator*=(uint32_t b32); base_uint& operator*=(const base_uint& b); + base_uint& operator/=(uint64_t b32); base_uint& operator/=(const base_uint& b); base_uint& operator++() @@ -209,6 +210,7 @@ class base_uint friend inline base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; } friend inline base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; } friend inline base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; } + friend inline base_uint operator/(const base_uint& a, uint64_t b) { return base_uint(a) /= b; } friend inline bool operator==(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) == 0; } friend inline bool operator!=(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) != 0; } friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; } diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index a923d3846775..0dc170954a7c 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -360,6 +360,19 @@ BOOST_AUTO_TEST_CASE( divide ) BOOST_CHECK(R2L / MaxL == ZeroL); BOOST_CHECK(MaxL / R2L == 1); BOOST_CHECK_THROW(R2L / ZeroL, uint_error); + + // The integer-divisor overload must be bit-identical to dividing by the same + // value widened to arith_uint256, for both the fast word-wise path + // (<= uint32 max) and the arith_uint256 fallback above it. + for (uint64_t d : {uint64_t{1}, uint64_t{2}, uint64_t{24}, uint64_t{3600}, + uint64_t{std::numeric_limits::max()}, + uint64_t{std::numeric_limits::max()} + 1, + uint64_t{0xFEDCBA9876543210}}) { + BOOST_CHECK(R1L / d == R1L / arith_uint256(d)); + BOOST_CHECK(R2L / d == R2L / arith_uint256(d)); + BOOST_CHECK(MaxL / d == MaxL / arith_uint256(d)); + } + BOOST_CHECK_THROW(R1L / uint64_t{0}, uint_error); } From 54187cd0bb42a07a4be6439572a74c1c7bd90f98 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Fri, 12 Jun 2026 13:25:25 +0700 Subject: [PATCH 3/8] perf: avoid re-validation of ehf signals during block-connect It also prevent potential crash in assert in case of huge re-organizations of blockchain when buried fork is re-validated in BlockUndo --- src/evo/chainhelper.cpp | 2 +- src/evo/mnhftx.cpp | 73 ++++++++++++++++------------------------- src/evo/mnhftx.h | 13 +++++--- 3 files changed, 38 insertions(+), 50 deletions(-) diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index 5c1f19a508d0..33ce3a25075f 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -23,7 +23,7 @@ CChainstateHelper::CChainstateHelper(CEvoDB& evodb, CDeterministicMNManager& dmn isman{isman}, credit_pool_manager{std::make_unique(evodb, chainman)}, m_chainlocks{chainlocks}, - ehf_manager{std::make_unique(evodb, chainman, qman)}, + ehf_manager{std::make_unique(evodb, chainman)}, mn_payments{std::make_unique(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)}, special_tx{std::make_unique(*credit_pool_manager, dmnman, *ehf_manager, qblockman, qsnapman, chainman, consensus_params, chainlocks, qman)} diff --git a/src/evo/mnhftx.cpp b/src/evo/mnhftx.cpp index d83fa4951dbf..b5666b5af80a 100644 --- a/src/evo/mnhftx.cpp +++ b/src/evo/mnhftx.cpp @@ -43,10 +43,9 @@ CMutableTransaction MNHFTxPayload::PrepareTx() const return tx; } -CMNHFManager::CMNHFManager(CEvoDB& evoDb, const ChainstateManager& chainman, const llmq::CQuorumManager& qman) : +CMNHFManager::CMNHFManager(CEvoDB& evoDb, const ChainstateManager& chainman) : m_evoDb(evoDb), - m_chainman{chainman}, - m_qman{qman} + m_chainman{chainman} { assert(globalInstance == nullptr); globalInstance = this; @@ -91,22 +90,13 @@ CMNHFManager::Signals CMNHFManager::GetSignalsStage(const CBlockIndex* const pin return signals_ret; } -bool MNHFTx::Verify(const llmq::CQuorumManager& qman, const uint256& quorumHash, const uint256& requestId, const uint256& msgHash, TxValidationState& state) const +bool MNHFTxPayload::IsTriviallyValid(TxValidationState& state) const { - if (versionBit >= VERSIONBITS_NUM_BITS) { - return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-nbit-out-of-bounds"); - } - - const Consensus::LLMQType& llmqType = Params().GetConsensus().llmqTypeMnhf; - const auto quorum = qman.GetQuorum(llmqType, quorumHash); - - if (!quorum) { - return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-missing-quorum"); + if (nVersion == 0 || nVersion > CURRENT_VERSION) { + return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-version"); } - - const llmq::SignHash signHash{llmqType, quorum->qc->quorumHash, requestId, msgHash}; - if (!sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash.Get())) { - return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-invalid"); + if (signal.versionBit >= VERSIONBITS_NUM_BITS) { + return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-nbit-out-of-bounds"); } return true; @@ -122,9 +112,10 @@ bool CheckMNHFTx(const ChainstateManager& chainman, const llmq::CQuorumManager& if (!opt_mnhfTx) { return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-payload"); } - auto& mnhfTx = *opt_mnhfTx; - if (mnhfTx.nVersion == 0 || mnhfTx.nVersion > MNHFTxPayload::CURRENT_VERSION) { - return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-version"); + const auto& mnhfTx = *opt_mnhfTx; + + if (!mnhfTx.IsTriviallyValid(state)) { + return false; } if (!Params().IsValidMNActivation(mnhfTx.signal.versionBit, pindexPrev->GetMedianTimePast())) { @@ -141,17 +132,22 @@ bool CheckMNHFTx(const ChainstateManager& chainman, const llmq::CQuorumManager& return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-quorum-hash"); } - // Copy transaction except `quorumSig` field to calculate hash + // Copy transaction except `sig` field to calculate the hash signed by the quorum CMutableTransaction tx_copy(tx); auto payload_copy = mnhfTx; payload_copy.signal.sig = CBLSSignature(); SetTxPayload(tx_copy, payload_copy); - uint256 msgHash = tx_copy.GetHash(); + const uint256 msgHash = tx_copy.GetHash(); + const Consensus::LLMQType llmqType = Params().GetConsensus().llmqTypeMnhf; + const auto quorum = qman.GetQuorum(llmqType, mnhfTx.signal.quorumHash); + if (!quorum) { + return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-missing-quorum"); + } - if (!mnhfTx.signal.Verify(qman, mnhfTx.signal.quorumHash, mnhfTx.GetRequestId(), msgHash, state)) { - // set up inside Verify - return false; + const llmq::SignHash signHash{llmqType, quorum->qc->quorumHash, mnhfTx.GetRequestId(), msgHash}; + if (!mnhfTx.signal.sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash.Get())) { + return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-invalid"); } return true; @@ -171,31 +167,21 @@ std::optional extractEHFSignal(const CTransaction& tx) return opt_mnhfTx->signal.versionBit; } -static bool extractSignals(const ChainstateManager& chainman, const llmq::CQuorumManager& qman, const CBlock& block, const CBlockIndex* const pindex, std::vector& new_signals, BlockValidationState& state) +static bool extractSignals(const CBlock& block, std::vector& new_signals, BlockValidationState& state) { + // Each signal's payload and signature were already validated by CheckMNHFTx during + // block processing, so here we only collect the version bits without re-validating. // we skip the coinbase for (size_t i = 1; i < block.vtx.size(); ++i) { - const CTransaction& tx = *block.vtx[i]; - - if (!tx.IsSpecialTxVersion() || tx.nType != TRANSACTION_MNHF_SIGNAL) { + const std::optional bit = extractEHFSignal(*block.vtx[i]); + if (!bit.has_value()) { // only interested in special TXs 'TRANSACTION_MNHF_SIGNAL' continue; } - - TxValidationState tx_state; - if (!CheckMNHFTx(chainman, qman, tx, pindex, tx_state)) { - return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(), tx_state.GetDebugMessage()); - } - - const auto opt_mnhfTx = GetTxPayload(tx); - if (!opt_mnhfTx) { - return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-mnhf-tx-payload"); - } - const uint8_t bit = opt_mnhfTx->signal.versionBit; if (std::find(new_signals.begin(), new_signals.end(), bit) != new_signals.end()) { return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-mnhf-duplicates-in-block"); } - new_signals.push_back(bit); + new_signals.push_back(*bit); } return true; @@ -205,7 +191,7 @@ std::optional CMNHFManager::ProcessBlock(const CBlock& bl { try { std::vector new_signals; - if (!extractSignals(m_chainman, m_qman, block, pindex, new_signals, state)) { + if (!extractSignals(block, new_signals, state)) { // state is set inside extractSignals return std::nullopt; } @@ -254,7 +240,7 @@ bool CMNHFManager::UndoBlock(const CBlock& block, const CBlockIndex* const pinde { std::vector excluded_signals; BlockValidationState state; - if (!extractSignals(m_chainman, m_qman, block, pindex, excluded_signals, state)) { + if (!extractSignals(block, excluded_signals, state)) { LogPrintf("CMNHFManager::%s: failed to extract signals\n", __func__); return false; } @@ -266,7 +252,6 @@ bool CMNHFManager::UndoBlock(const CBlock& block, const CBlockIndex* const pinde for (const auto& versionBit : excluded_signals) { LogPrintf("%s: exclude mnhf bit=%d block:%s number of known signals:%lld\n", __func__, versionBit, pindex->GetBlockHash().ToString(), signals.size()); assert(signals.find(versionBit) != signals.end()); - assert(Params().IsValidMNActivation(versionBit, pindex->GetMedianTimePast())); } return true; diff --git a/src/evo/mnhftx.h b/src/evo/mnhftx.h index d9b1c8e90c5a..16cd13b0b90c 100644 --- a/src/evo/mnhftx.h +++ b/src/evo/mnhftx.h @@ -39,8 +39,6 @@ class MNHFTx CBLSSignature sig{}; MNHFTx() = default; - bool Verify(const llmq::CQuorumManager& qman, const uint256& quorumHash, const uint256& requestId, const uint256& msgHash, - TxValidationState& state) const; SERIALIZE_METHODS(MNHFTx, obj) { @@ -74,6 +72,12 @@ class MNHFTxPayload */ CMutableTransaction PrepareTx() const; + /** + * Checks that don't depend on chain state or the BLS signature (payload version + * and signal version bit bounds). + */ + bool IsTriviallyValid(TxValidationState& state) const; + SERIALIZE_METHODS(MNHFTxPayload, obj) { READWRITE(obj.nVersion, obj.signal); @@ -90,12 +94,11 @@ class CMNHFManager : public AbstractEHFManager private: CEvoDB& m_evoDb; // TODO: move its functionallity of ProcessBlock, UndoBlock to specialtxman; - // it will help to drop dependency on m_chainman, m_qman here (and validation.h) + // it will help to drop dependency on m_chainman here (and validation.h) // Secondly, store in database active EHF signals not for each block; // but quite opposite: keep only hash of block where signal is added. // TODO: implement migration to a new format const ChainstateManager& m_chainman; - const llmq::CQuorumManager& m_qman; static constexpr size_t MNHFCacheSize = 1000; Mutex cs_cache; @@ -106,7 +109,7 @@ class CMNHFManager : public AbstractEHFManager CMNHFManager() = delete; CMNHFManager(const CMNHFManager&) = delete; CMNHFManager& operator=(const CMNHFManager&) = delete; - explicit CMNHFManager(CEvoDB& evoDb, const ChainstateManager& chainman, const llmq::CQuorumManager& qman); + explicit CMNHFManager(CEvoDB& evoDb, const ChainstateManager& chainman); ~CMNHFManager(); /** From 78b8274cccd592cc2f480a4ddca56f01e59878ae Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 13 Jun 2026 02:11:47 +0700 Subject: [PATCH 4/8] fix: don't let 2 protx with the same platform-id to be presented in mempool --- src/txmempool.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/txmempool.h | 2 ++ 2 files changed, 40 insertions(+) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index febec3d957ad..6330b5cd94ed 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -661,6 +661,9 @@ void CTxMemPool::addUncheckedProTx(CDeterministicMNManager& dmnman, indexed_tran } mapProTxPubKeyIDs.emplace(proTx.keyIDOwner, tx_hash); mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx_hash); + if (proTx.nType == MnType::Evo && !proTx.platformNodeID.IsNull()) { + mapProTxPlatformNodeIDs.emplace(proTx.platformNodeID, tx_hash); + } if (!proTx.collateralOutpoint.hash.IsNull()) { mapProTxCollaterals.emplace(proTx.collateralOutpoint, tx_hash); } else { @@ -672,6 +675,9 @@ void CTxMemPool::addUncheckedProTx(CDeterministicMNManager& dmnman, indexed_tran for (const auto& entry : proTx.netInfo->GetEntries()) { mapProTxAddresses.emplace(entry, tx_hash); } + if (proTx.nType == MnType::Evo && !proTx.platformNodeID.IsNull()) { + mapProTxPlatformNodeIDs.emplace(proTx.platformNodeID, tx_hash); + } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { auto proTx = *Assert(GetTxPayload(tx)); mapProTxRefs.emplace(proTx.proTxHash, tx_hash); @@ -765,6 +771,9 @@ void CTxMemPool::removeUncheckedProTx(const CTransaction& tx) } mapProTxPubKeyIDs.erase(proTx.keyIDOwner); mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash()); + if (proTx.nType == MnType::Evo && !proTx.platformNodeID.IsNull()) { + mapProTxPlatformNodeIDs.erase(proTx.platformNodeID); + } mapProTxCollaterals.erase(proTx.collateralOutpoint); mapProTxCollaterals.erase(COutPoint(tx_hash, proTx.collateralOutpoint.n)); } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { @@ -773,6 +782,9 @@ void CTxMemPool::removeUncheckedProTx(const CTransaction& tx) for (const auto& entry : proTx.netInfo->GetEntries()) { mapProTxAddresses.erase(entry); } + if (proTx.nType == MnType::Evo && !proTx.platformNodeID.IsNull()) { + mapProTxPlatformNodeIDs.erase(proTx.platformNodeID); + } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { auto proTx = *Assert(GetTxPayload(tx)); eraseProTxRef(proTx.proTxHash, tx_hash); @@ -919,6 +931,16 @@ void CTxMemPool::removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSLa } } +void CTxMemPool::removeProTxPlatformNodeIDConflicts(const CTransaction &tx, const uint160 &platformNodeID) +{ + if (mapProTxPlatformNodeIDs.count(platformNodeID)) { + uint256 conflictHash = mapProTxPlatformNodeIDs[platformNodeID]; + if (conflictHash != tx.GetHash() && mapTx.count(conflictHash)) { + removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); + } + } +} + void CTxMemPool::removeProTxCollateralConflicts(const CTransaction &tx, const COutPoint &collateralOutpoint) { if (mapProTxCollaterals.count(collateralOutpoint)) { @@ -1009,6 +1031,9 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx) } removeProTxPubKeyConflicts(tx, proTx.keyIDOwner); removeProTxPubKeyConflicts(tx, proTx.pubKeyOperator); + if (proTx.nType == MnType::Evo && !proTx.platformNodeID.IsNull()) { + removeProTxPlatformNodeIDConflicts(tx, proTx.platformNodeID); + } if (!proTx.collateralOutpoint.hash.IsNull()) { removeProTxCollateralConflicts(tx, proTx.collateralOutpoint); } else { @@ -1029,6 +1054,9 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx) } } } + if (opt_proTx->nType == MnType::Evo && !opt_proTx->platformNodeID.IsNull()) { + removeProTxPlatformNodeIDConflicts(tx, opt_proTx->platformNodeID); + } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { const auto opt_proTx = GetTxPayload(tx); if (!opt_proTx) { @@ -1110,6 +1138,7 @@ void CTxMemPool::_clear() mapNextTx.clear(); mapProTxAddresses.clear(); mapProTxPubKeyIDs.clear(); + mapProTxPlatformNodeIDs.clear(); totalTxSize = 0; m_total_fee = 0; cachedInnerUsage = 0; @@ -1367,6 +1396,9 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { if (mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash())) { return true; } + if (proTx.nType == MnType::Evo && !proTx.platformNodeID.IsNull() && mapProTxPlatformNodeIDs.count(proTx.platformNodeID)) { + return true; + } if (!proTx.collateralOutpoint.hash.IsNull()) { if (mapProTxCollaterals.count(proTx.collateralOutpoint)) { // there is another ProRegTx that refers to the same collateral @@ -1390,6 +1422,12 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { return true; } } + if (opt_proTx->nType == MnType::Evo && !opt_proTx->platformNodeID.IsNull()) { + auto it = mapProTxPlatformNodeIDs.find(opt_proTx->platformNodeID); + if (it != mapProTxPlatformNodeIDs.end() && it->second != opt_proTx->proTxHash) { + return true; + } + } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { const auto opt_proTx = GetTxPayload(tx); if (!opt_proTx) { diff --git a/src/txmempool.h b/src/txmempool.h index 959d02b6860f..7300134cf59b 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -531,6 +531,7 @@ class CTxMemPool std::map mapProTxAddresses; std::map mapProTxPubKeyIDs; std::map mapProTxBlsPubKeyHashes; + std::map mapProTxPlatformNodeIDs; std::map mapProTxCollaterals; std::map mapAssetUnlockExpiry; // tx hash -> height @@ -631,6 +632,7 @@ class CTxMemPool void removeConflicts(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs); void removeProTxPubKeyConflicts(const CTransaction &tx, const CKeyID &keyId) EXCLUSIVE_LOCKS_REQUIRED(cs); void removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSLazyPublicKey &pubKey) EXCLUSIVE_LOCKS_REQUIRED(cs); + void removeProTxPlatformNodeIDConflicts(const CTransaction &tx, const uint160 &platformNodeID) EXCLUSIVE_LOCKS_REQUIRED(cs); void removeProTxCollateralConflicts(const CTransaction &tx, const COutPoint &collateralOutpoint) EXCLUSIVE_LOCKS_REQUIRED(cs); void removeProTxSpentCollateralConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs); void removeProTxKeyChangedConflicts(const CTransaction &tx, const uint256& proTxHash, const uint256& newKeyHash) EXCLUSIVE_LOCKS_REQUIRED(cs); From 99305fbd5b4f8dc8268f9a11951f2cb6c9120b28 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 13 Jun 2026 03:06:41 +0700 Subject: [PATCH 5/8] test: add test for duplicated platform-node-id in mempool --- test/functional/rpc_netinfo.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/functional/rpc_netinfo.py b/test/functional/rpc_netinfo.py index fe45b1ca7b31..77db8018b458 100755 --- a/test/functional/rpc_netinfo.py +++ b/test/functional/rpc_netinfo.py @@ -579,5 +579,27 @@ def update_node_two(self, duplicate_addr = None, duplicate_tor = None, duplicate # All non-duplicate entries should still succeed update_node_two(self) + # Check for detection of duplicate platformNodeID + dup_platform = hash160(b'duplicate platformNodeID').hex() + self.node_evo.mn.update_service(self.node_evo.node, submit=True, addrs_core_p2p=f"127.0.0.1:{self.node_evo.mn.nodePort}", + platform_node_id=dup_platform, addrs_platform_p2p=DEFAULT_PORT_PLATFORM_P2P, addrs_platform_https=DEFAULT_PORT_PLATFORM_HTTP) + self.sync_mempools() + self.node_two.mn.update_service(self.node_two.node, submit=True, addrs_core_p2p=f"127.0.0.2:{self.node_two.mn.nodePort}", + platform_node_id=dup_platform, addrs_platform_p2p=DEFAULT_PORT_PLATFORM_P2P, addrs_platform_https=DEFAULT_PORT_PLATFORM_HTTP, + expected_assert_code=-26, expected_assert_msg="protx-dup") + + # Same check via the ProRegTx path: two fresh EvoNodes sharing a platformNodeID, the second is rejected from the mempool + dup_platform_2 = hash160(b'duplicate ProRegTx platformNodeID').hex() + node_reg_one = EvoNode(self.nodes[0]) + node_reg_one.generate_collateral(self) + node_reg_two = EvoNode(self.nodes[1]) + node_reg_two.generate_collateral(self) + node_reg_one.mn.register(node_reg_one.node, submit=True, addrs_core_p2p=f"127.0.0.10:{node_reg_one.mn.nodePort}", + platform_node_id=dup_platform_2, addrs_platform_p2p=DEFAULT_PORT_PLATFORM_P2P, addrs_platform_https=DEFAULT_PORT_PLATFORM_HTTP) + self.sync_mempools() + node_reg_two.mn.register(node_reg_two.node, submit=True, addrs_core_p2p=f"127.0.0.11:{node_reg_two.mn.nodePort}", + platform_node_id=dup_platform_2, addrs_platform_p2p=DEFAULT_PORT_PLATFORM_P2P, addrs_platform_https=DEFAULT_PORT_PLATFORM_HTTP, + expected_assert_code=-26, expected_assert_msg="protx-dup") + if __name__ == "__main__": NetInfoTest().main() From 59620167a412f81c64c0a62d52bf09d0e96b1413 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 13 Jun 2026 14:02:55 +0700 Subject: [PATCH 6/8] chore: update min-chainwork, checkpoints and seeds for v23.1.4 --- contrib/seeds/nodes_main.txt | 230 ++++++---------------------------- contrib/seeds/nodes_test.txt | 5 + src/chainparams.cpp | 11 +- src/chainparamsseeds.h | 235 +++++++---------------------------- 4 files changed, 94 insertions(+), 387 deletions(-) diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt index d7d89246ed2d..f621e2623c02 100644 --- a/contrib/seeds/nodes_main.txt +++ b/contrib/seeds/nodes_main.txt @@ -23,88 +23,47 @@ ayhwwpjq4rg3bslbtt7yejqyhucyaqsbb7tn45blh4r7xj62wfonryqd.onion:9999 3uvcjymiixi6n6m2p6fsgyjxkx2ceaesd7eopi3p7jn364i5z646koid.onion:9999 3cova3snmiydrdaqrszj5krnujpwgkueh2kjodun4hvixk3y5l5zmgid.onion:9999 2br37z5ilg3i3rawwkznmh6lhczboql5zdrfgmkaxns4tpfrxmu6s5yd.onion:9999 -216.250.97.52:9999 -216.238.82.108:9999 +217.154.231.20:9999 216.238.75.46:9999 -216.238.73.67:9999 216.230.232.125:9999 -216.189.157.22:9999 -216.106.186.179:9999 -216.106.186.131:9999 -213.171.15.125:9999 -213.159.77.221:9999 -212.71.239.75:9999 -212.52.0.210:9999 -212.24.109.253:9999 +212.132.105.190:9999 212.24.104.225:9999 209.141.36.206:9999 208.87.102.91:9999 -208.87.102.89:9999 207.244.247.40:9999 -207.180.233.6:9999 -205.206.255.206:9999 -205.206.254.21:9999 -202.182.105.95:9999 202.71.14.79:9999 202.5.16.33:9999 -198.244.213.69:9999 195.98.95.210:9999 195.26.254.228:9999 +194.238.25.199:9999 194.135.84.100:9999 -194.135.80.33:9999 194.5.157.214:9999 -193.160.119.129:9999 192.175.127.198:9999 192.169.6.87:9999 -191.101.2.231:9999 -188.244.117.12:9999 -188.166.182.47:9999 -188.40.205.3:9999 -185.252.234.238:9999 185.243.115.219:9999 185.228.83.156:9999 185.228.83.132:9999 -185.213.24.34:9999 -185.198.234.25:9999 -185.198.234.17:9999 -185.198.234.12:9999 +185.216.179.5:9999 185.193.19.214:9999 -185.185.40.171:9999 -185.185.40.167:9999 185.185.40.104:9999 -185.185.40.14:9999 185.166.217.154:9999 185.165.171.117:9999 -185.164.163.220:9999 185.164.163.218:9999 -185.164.163.217:9999 185.164.163.85:9999 -185.164.163.59:9999 -185.141.216.4:9999 185.112.249.53:9999 -185.112.249.52:9999 -185.112.249.51:9999 185.112.249.49:9999 185.28.101.145:9999 184.107.182.198:9999 -178.253.42.64:9999 +178.253.253.5:9999 178.215.237.135:9999 178.215.237.134:9999 178.208.87.226:9999 -178.208.87.225:9999 178.208.87.213:9999 -178.208.87.72:9999 -178.208.87.33:9999 -178.157.91.184:9999 -178.157.91.178:9999 178.157.91.177:9999 178.63.121.129:9999 -178.62.171.16:9999 177.93.141.86:9999 177.93.141.60:9999 176.102.65.145:9999 -173.212.245.118:9999 -173.212.232.90:9999 172.238.7.25:9999 172.236.244.81:9999 172.104.145.166:9999 @@ -112,236 +71,125 @@ ayhwwpjq4rg3bslbtt7yejqyhucyaqsbb7tn45blh4r7xj62wfonryqd.onion:9999 172.86.73.160:9999 168.119.87.196:9999 168.119.80.4:9999 -167.71.229.90:9999 +167.104.216.28:9999 +167.88.169.16:9999 165.22.234.135:9999 165.22.221.97:9999 163.172.66.41:9999 -162.250.191.31:9999 -162.212.35.104:9999 -162.212.35.100:9999 -161.35.17.210:9999 -159.89.122.128:9999 +161.97.165.115:9999 159.75.121.163:9999 +154.16.63.112:9999 152.67.95.184:9999 -151.244.85.229:9999 -151.244.85.197:9999 +151.244.85.219:9999 +151.244.85.195:9999 151.244.85.178:9999 151.244.85.123:9999 -151.244.85.64:9999 -151.244.85.48:9999 -149.28.241.190:9999 -147.93.132.12:9999 -147.93.131.52:9999 -147.45.183.128:9999 -147.45.103.99:9999 -146.59.153.204:9999 -146.59.45.235:9999 -144.126.143.197:9999 -144.126.141.62:9999 +149.104.110.119:9999 +147.45.41.210:9999 +144.31.188.42:9999 144.24.238.178:9999 -142.179.162.14:9999 -142.93.149.185:9999 -139.162.215.169:9999 -139.162.211.76:9999 -139.28.97.2:9999 136.244.99.17:9999 -136.243.142.39:9999 -136.243.142.35:9999 -135.181.8.82:9999 -134.255.182.186:9999 133.18.97.226:9999 +132.243.197.240:9999 +132.243.197.179:9999 +132.243.197.99:9999 +132.243.197.23:9999 +130.255.155.163:9999 130.162.233.186:9999 123.193.64.166:9999 115.190.248.57:9999 -115.120.238.240:9999 114.132.172.215:9999 109.235.67.246:9999 -109.199.96.61:9999 -109.173.240.233:9999 +108.160.131.192:9999 107.189.3.74:9999 107.179.202.74:9999 -107.174.204.106:9999 +107.174.204.232:9999 107.170.254.160:9999 106.55.9.22:9999 104.234.167.115:9999 -100.42.182.181:9999 -95.183.51.141:9999 -95.171.21.131:9999 -94.172.109.161:9999 93.115.172.39:9999 -93.115.172.38:9999 93.115.172.37:9999 -92.255.76.59:9999 -92.53.120.89:9999 -91.239.5.12:9999 91.199.149.177:9999 91.198.108.40:9999 91.198.108.39:9999 -91.198.108.38:9999 91.198.108.37:9999 -91.198.108.36:9999 91.198.108.35:9999 +91.184.249.209:9999 89.179.73.96:9999 89.125.209.195:9999 -89.125.209.178:9999 -89.125.209.120:9999 89.125.209.110:9999 -89.125.209.106:9999 89.125.209.69:9999 +89.117.57.27:9999 89.117.3.242:9999 -89.47.167.131:9999 89.46.42.218:9999 -89.46.42.216:9999 -89.40.15.222:9999 89.35.131.149:9999 -89.35.131.61:9999 -89.35.131.39:9999 87.228.24.64:9999 85.209.241.245:9999 -85.209.241.235:9999 -85.209.241.234:9999 -85.209.241.198:9999 -85.209.241.185:9999 85.209.241.93:9999 85.209.241.87:9999 85.209.241.86:9999 -85.209.241.73:9999 -85.209.241.10:9999 -85.193.90.107:9999 -85.92.111.111:9999 +85.155.188.138:9999 84.247.180.201:9999 84.242.179.204:9999 +84.98.12.196:9999 84.9.50.17:9999 83.239.99.40:9999 -83.222.9.253:9999 83.149.100.186:9999 83.149.100.185:9999 83.149.100.184:9999 83.149.100.183:9999 -82.211.21.240:9999 -82.211.21.226:9999 -82.211.21.179:9999 -82.211.21.131:9999 -82.211.21.110:9999 -82.211.21.99:9999 -82.211.21.32:9999 -82.211.21.30:9999 -82.211.21.23:9999 -82.211.21.4:9999 82.202.230.83:9999 -82.180.149.107:9999 82.180.146.192:9999 81.227.250.51:9999 -81.200.152.144:9999 80.249.147.8:9999 80.240.132.231:9999 -80.209.239.129:9999 -80.209.233.182:9999 80.208.230.144:9999 78.83.19.0:9999 77.223.99.4:9999 77.221.148.204:9999 -74.208.174.63:9999 74.50.90.113:9999 72.62.58.108:9999 72.60.38.160:9999 -70.34.198.26:9999 -69.167.168.63:9999 69.61.107.215:9999 66.245.196.52:9999 66.244.243.70:9999 -66.42.84.27:9999 -66.29.147.83:9999 +66.163.113.113:9999 +66.163.113.91:9999 +66.163.113.7:9999 +62.171.133.125:9999 62.60.244.174:9999 -57.128.212.163:9999 -54.69.95.118:9999 52.36.102.91:9999 52.33.9.172:9999 -52.10.213.198:9999 51.158.188.88:9999 +51.158.169.237:9999 51.158.167.31:9999 -51.79.109.200:9999 -51.79.109.182:9999 -50.116.28.103:9999 -47.110.197.29:9999 -47.110.184.51:9999 -47.110.165.177:9999 -47.110.157.147:9999 -47.110.154.77:9999 -47.110.146.65:9999 -47.99.229.213:9999 -47.98.66.95:9999 46.250.254.10:9999 -46.148.231.121:9999 46.36.40.242:9999 -46.10.241.191:9999 +46.30.189.187:9999 46.4.162.127:9999 45.153.186.100:9999 -45.153.70.126:9999 45.149.154.194:9999 -45.140.19.201:9999 -45.135.180.130:9999 -45.135.180.114:9999 -45.135.180.79:9999 -45.132.74.89:9999 45.128.156.30:9999 -45.91.94.217:9999 -45.76.84.108:9999 +45.79.18.106:9999 45.61.186.121:9999 45.58.56.79:9999 -45.58.52.247:9999 44.240.99.214:9999 43.229.77.46:9999 43.167.244.109:9999 43.167.239.145:9999 43.134.180.113:9999 -38.242.197.189:9999 +43.133.171.101:9999 38.102.125.108:9999 -35.180.128.14:9999 -35.174.217.98:9999 -34.209.37.222:9999 +38.54.12.111:9999 +37.97.227.21:9999 +34.246.176.25:9999 31.148.99.148:9999 -31.58.170.181:9999 -31.58.170.180:9999 -31.58.170.139:9999 -31.58.170.130:9999 31.10.97.36:9999 -15.188.53.12:9999 -8.222.147.169:9999 -8.222.146.149:9999 -8.219.246.164:9999 -8.219.220.160:9999 -8.219.206.45:9999 -8.219.205.129:9999 -8.219.204.148:9999 -8.219.170.241:9999 -8.219.160.147:9999 -8.219.54.127:9999 -5.230.228.97:9999 -5.230.119.203:9999 -5.230.119.202:9999 -5.230.119.201:9999 -5.230.119.199:9999 -5.230.119.189:9999 -5.230.119.188:9999 -5.230.119.186:9999 -5.230.119.182:9999 -5.230.119.180:9999 -5.189.164.253:9999 +23.163.0.174:9999 5.161.110.79:9999 -5.53.124.120:9999 -5.39.11.80:9999 -5.39.10.23:9999 -5.35.103.123:9999 -5.35.103.26:9999 -5.35.103.25:9999 5.35.103.19:9999 -5.9.237.37:9999 -5.9.237.32:9999 5.2.73.58:9999 5.2.67.190:9999 2.233.120.35:9999 -2.57.241.178:9999 -2.57.241.155:9999 -2.56.213.221:9999 -2.56.213.218:9999 +2.59.219.54:9999 +1.117.75.220:9999 diff --git a/contrib/seeds/nodes_test.txt b/contrib/seeds/nodes_test.txt index df2588204786..9dac4950aff0 100644 --- a/contrib/seeds/nodes_test.txt +++ b/contrib/seeds/nodes_test.txt @@ -1,6 +1,11 @@ 212.47.68.199:19999 185.187.169.193:19999 +206.245.167.63:19999 147.93.132.9:19999 +68.67.122.72:19999 +68.67.122.42:19999 +68.67.122.33:19999 +68.67.122.23:19999 62.60.244.174:19999 54.213.94.216:19999 54.191.146.137:19999 diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 88afa4dd87ce..76c499f9b609 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -218,8 +218,8 @@ class CMainParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_V24].nFalloffCoeff = 5; // this corresponds to 10 periods consensus.vDeployments[Consensus::DEPLOYMENT_V24].useEHF = true; - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000b9040746437784aaec47"); // 2471728 - consensus.defaultAssumeValid = uint256S("0x000000000000001a19ad7270422a00f86123ea94e0b295a3a796d6861bd7b032"); // 2471728 + consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000ba7225adc3153945d14d"); // 2487500 + consensus.defaultAssumeValid = uint256S("0x00000000000000119fe42827219e0686d3f7b494ae65f823194c740c5dbab492"); // 2487500 /** * The message start string is designed to be unlikely to occur in normal data. @@ -333,6 +333,7 @@ class CMainParams : public CChainParams { {2361500, uint256S("0x0000000000000009ba1e8f47851d036bb618a4f6565eb3c32d1f647d450ff195")}, {2421800, uint256S("0x000000000000000718ed026ebd644a8b70b42d4cbd7b25304c066c9bf15f85b7")}, {2471728, uint256S("0x000000000000001a19ad7270422a00f86123ea94e0b295a3a796d6861bd7b032")}, + {2487500, uint256S("0x00000000000000000000000000000000000000000000ba7225adc3153945d14d")}, } }; @@ -342,10 +343,10 @@ class CMainParams : public CChainParams { // getchaintxstats 17280 000000000000001a19ad7270422a00f86123ea94e0b295a3a796d6861bd7b032 chainTxData = ChainTxData{ - 1778832687, // * UNIX timestamp of last known number of transactions (Block 2471728) - 69379403, // * total number of transactions between genesis and that timestamp + 1781318234, // * UNIX timestamp of last known number of transactions (Block 2487500) + 69770814, // * total number of transactions between genesis and that timestamp // (the tx=... number in the ChainStateFlushed debug.log lines) - 0.1476929741159368, // * estimated number of transactions per second after that timestamp + 0.1569520632249578, // * estimated number of transactions per second after that timestamp }; } }; diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index 333ff3bafc4f..6f25f87fd780 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -32,88 +32,47 @@ static const uint8_t chainparams_seed_main[] = { 0x04,0x20,0xdd,0x2a,0x24,0xe1,0x88,0x45,0xd1,0xe6,0xf9,0x9a,0x7f,0x8b,0x23,0x61,0x37,0x55,0xf4,0x22,0x00,0x92,0x1f,0xc8,0xe7,0xa3,0x6f,0xfa,0x5b,0xbf,0x71,0x1d,0xcf,0xb9,0x27,0x0f, 0x04,0x20,0xd8,0x9d,0x50,0x6e,0x4d,0x62,0x30,0x38,0x8c,0x10,0x8c,0xb2,0x9e,0xaa,0x2d,0xa2,0x5f,0x63,0x2a,0x84,0x3e,0x94,0x97,0x0e,0x8d,0xe1,0xea,0x8b,0xab,0x78,0xea,0xfb,0x27,0x0f, 0x04,0x20,0xd0,0x63,0xbf,0xe7,0xa8,0x59,0xb6,0x8d,0xc4,0x16,0xb2,0xb2,0xd6,0x1f,0xcb,0x38,0xb2,0x17,0x41,0x7d,0xc8,0xe2,0x53,0x31,0x40,0xbb,0x65,0xc9,0xbc,0xb1,0xbb,0x29,0x27,0x0f, - 0x01,0x04,0xd8,0xfa,0x61,0x34,0x27,0x0f, - 0x01,0x04,0xd8,0xee,0x52,0x6c,0x27,0x0f, + 0x01,0x04,0xd9,0x9a,0xe7,0x14,0x27,0x0f, 0x01,0x04,0xd8,0xee,0x4b,0x2e,0x27,0x0f, - 0x01,0x04,0xd8,0xee,0x49,0x43,0x27,0x0f, 0x01,0x04,0xd8,0xe6,0xe8,0x7d,0x27,0x0f, - 0x01,0x04,0xd8,0xbd,0x9d,0x16,0x27,0x0f, - 0x01,0x04,0xd8,0x6a,0xba,0xb3,0x27,0x0f, - 0x01,0x04,0xd8,0x6a,0xba,0x83,0x27,0x0f, - 0x01,0x04,0xd5,0xab,0x0f,0x7d,0x27,0x0f, - 0x01,0x04,0xd5,0x9f,0x4d,0xdd,0x27,0x0f, - 0x01,0x04,0xd4,0x47,0xef,0x4b,0x27,0x0f, - 0x01,0x04,0xd4,0x34,0x00,0xd2,0x27,0x0f, - 0x01,0x04,0xd4,0x18,0x6d,0xfd,0x27,0x0f, + 0x01,0x04,0xd4,0x84,0x69,0xbe,0x27,0x0f, 0x01,0x04,0xd4,0x18,0x68,0xe1,0x27,0x0f, 0x01,0x04,0xd1,0x8d,0x24,0xce,0x27,0x0f, 0x01,0x04,0xd0,0x57,0x66,0x5b,0x27,0x0f, - 0x01,0x04,0xd0,0x57,0x66,0x59,0x27,0x0f, 0x01,0x04,0xcf,0xf4,0xf7,0x28,0x27,0x0f, - 0x01,0x04,0xcf,0xb4,0xe9,0x06,0x27,0x0f, - 0x01,0x04,0xcd,0xce,0xff,0xce,0x27,0x0f, - 0x01,0x04,0xcd,0xce,0xfe,0x15,0x27,0x0f, - 0x01,0x04,0xca,0xb6,0x69,0x5f,0x27,0x0f, 0x01,0x04,0xca,0x47,0x0e,0x4f,0x27,0x0f, 0x01,0x04,0xca,0x05,0x10,0x21,0x27,0x0f, - 0x01,0x04,0xc6,0xf4,0xd5,0x45,0x27,0x0f, 0x01,0x04,0xc3,0x62,0x5f,0xd2,0x27,0x0f, 0x01,0x04,0xc3,0x1a,0xfe,0xe4,0x27,0x0f, + 0x01,0x04,0xc2,0xee,0x19,0xc7,0x27,0x0f, 0x01,0x04,0xc2,0x87,0x54,0x64,0x27,0x0f, - 0x01,0x04,0xc2,0x87,0x50,0x21,0x27,0x0f, 0x01,0x04,0xc2,0x05,0x9d,0xd6,0x27,0x0f, - 0x01,0x04,0xc1,0xa0,0x77,0x81,0x27,0x0f, 0x01,0x04,0xc0,0xaf,0x7f,0xc6,0x27,0x0f, 0x01,0x04,0xc0,0xa9,0x06,0x57,0x27,0x0f, - 0x01,0x04,0xbf,0x65,0x02,0xe7,0x27,0x0f, - 0x01,0x04,0xbc,0xf4,0x75,0x0c,0x27,0x0f, - 0x01,0x04,0xbc,0xa6,0xb6,0x2f,0x27,0x0f, - 0x01,0x04,0xbc,0x28,0xcd,0x03,0x27,0x0f, - 0x01,0x04,0xb9,0xfc,0xea,0xee,0x27,0x0f, 0x01,0x04,0xb9,0xf3,0x73,0xdb,0x27,0x0f, 0x01,0x04,0xb9,0xe4,0x53,0x9c,0x27,0x0f, 0x01,0x04,0xb9,0xe4,0x53,0x84,0x27,0x0f, - 0x01,0x04,0xb9,0xd5,0x18,0x22,0x27,0x0f, - 0x01,0x04,0xb9,0xc6,0xea,0x19,0x27,0x0f, - 0x01,0x04,0xb9,0xc6,0xea,0x11,0x27,0x0f, - 0x01,0x04,0xb9,0xc6,0xea,0x0c,0x27,0x0f, + 0x01,0x04,0xb9,0xd8,0xb3,0x05,0x27,0x0f, 0x01,0x04,0xb9,0xc1,0x13,0xd6,0x27,0x0f, - 0x01,0x04,0xb9,0xb9,0x28,0xab,0x27,0x0f, - 0x01,0x04,0xb9,0xb9,0x28,0xa7,0x27,0x0f, 0x01,0x04,0xb9,0xb9,0x28,0x68,0x27,0x0f, - 0x01,0x04,0xb9,0xb9,0x28,0x0e,0x27,0x0f, 0x01,0x04,0xb9,0xa6,0xd9,0x9a,0x27,0x0f, 0x01,0x04,0xb9,0xa5,0xab,0x75,0x27,0x0f, - 0x01,0x04,0xb9,0xa4,0xa3,0xdc,0x27,0x0f, 0x01,0x04,0xb9,0xa4,0xa3,0xda,0x27,0x0f, - 0x01,0x04,0xb9,0xa4,0xa3,0xd9,0x27,0x0f, 0x01,0x04,0xb9,0xa4,0xa3,0x55,0x27,0x0f, - 0x01,0x04,0xb9,0xa4,0xa3,0x3b,0x27,0x0f, - 0x01,0x04,0xb9,0x8d,0xd8,0x04,0x27,0x0f, 0x01,0x04,0xb9,0x70,0xf9,0x35,0x27,0x0f, - 0x01,0x04,0xb9,0x70,0xf9,0x34,0x27,0x0f, - 0x01,0x04,0xb9,0x70,0xf9,0x33,0x27,0x0f, 0x01,0x04,0xb9,0x70,0xf9,0x31,0x27,0x0f, 0x01,0x04,0xb9,0x1c,0x65,0x91,0x27,0x0f, 0x01,0x04,0xb8,0x6b,0xb6,0xc6,0x27,0x0f, - 0x01,0x04,0xb2,0xfd,0x2a,0x40,0x27,0x0f, + 0x01,0x04,0xb2,0xfd,0xfd,0x05,0x27,0x0f, 0x01,0x04,0xb2,0xd7,0xed,0x87,0x27,0x0f, 0x01,0x04,0xb2,0xd7,0xed,0x86,0x27,0x0f, 0x01,0x04,0xb2,0xd0,0x57,0xe2,0x27,0x0f, - 0x01,0x04,0xb2,0xd0,0x57,0xe1,0x27,0x0f, 0x01,0x04,0xb2,0xd0,0x57,0xd5,0x27,0x0f, - 0x01,0x04,0xb2,0xd0,0x57,0x48,0x27,0x0f, - 0x01,0x04,0xb2,0xd0,0x57,0x21,0x27,0x0f, - 0x01,0x04,0xb2,0x9d,0x5b,0xb8,0x27,0x0f, - 0x01,0x04,0xb2,0x9d,0x5b,0xb2,0x27,0x0f, 0x01,0x04,0xb2,0x9d,0x5b,0xb1,0x27,0x0f, 0x01,0x04,0xb2,0x3f,0x79,0x81,0x27,0x0f, - 0x01,0x04,0xb2,0x3e,0xab,0x10,0x27,0x0f, 0x01,0x04,0xb1,0x5d,0x8d,0x56,0x27,0x0f, 0x01,0x04,0xb1,0x5d,0x8d,0x3c,0x27,0x0f, 0x01,0x04,0xb0,0x66,0x41,0x91,0x27,0x0f, - 0x01,0x04,0xad,0xd4,0xf5,0x76,0x27,0x0f, - 0x01,0x04,0xad,0xd4,0xe8,0x5a,0x27,0x0f, 0x01,0x04,0xac,0xee,0x07,0x19,0x27,0x0f, 0x01,0x04,0xac,0xec,0xf4,0x51,0x27,0x0f, 0x01,0x04,0xac,0x68,0x91,0xa6,0x27,0x0f, @@ -121,245 +80,139 @@ static const uint8_t chainparams_seed_main[] = { 0x01,0x04,0xac,0x56,0x49,0xa0,0x27,0x0f, 0x01,0x04,0xa8,0x77,0x57,0xc4,0x27,0x0f, 0x01,0x04,0xa8,0x77,0x50,0x04,0x27,0x0f, - 0x01,0x04,0xa7,0x47,0xe5,0x5a,0x27,0x0f, + 0x01,0x04,0xa7,0x68,0xd8,0x1c,0x27,0x0f, + 0x01,0x04,0xa7,0x58,0xa9,0x10,0x27,0x0f, 0x01,0x04,0xa5,0x16,0xea,0x87,0x27,0x0f, 0x01,0x04,0xa5,0x16,0xdd,0x61,0x27,0x0f, 0x01,0x04,0xa3,0xac,0x42,0x29,0x27,0x0f, - 0x01,0x04,0xa2,0xfa,0xbf,0x1f,0x27,0x0f, - 0x01,0x04,0xa2,0xd4,0x23,0x68,0x27,0x0f, - 0x01,0x04,0xa2,0xd4,0x23,0x64,0x27,0x0f, - 0x01,0x04,0xa1,0x23,0x11,0xd2,0x27,0x0f, - 0x01,0x04,0x9f,0x59,0x7a,0x80,0x27,0x0f, + 0x01,0x04,0xa1,0x61,0xa5,0x73,0x27,0x0f, 0x01,0x04,0x9f,0x4b,0x79,0xa3,0x27,0x0f, + 0x01,0x04,0x9a,0x10,0x3f,0x70,0x27,0x0f, 0x01,0x04,0x98,0x43,0x5f,0xb8,0x27,0x0f, - 0x01,0x04,0x97,0xf4,0x55,0xe5,0x27,0x0f, - 0x01,0x04,0x97,0xf4,0x55,0xc5,0x27,0x0f, + 0x01,0x04,0x97,0xf4,0x55,0xdb,0x27,0x0f, + 0x01,0x04,0x97,0xf4,0x55,0xc3,0x27,0x0f, 0x01,0x04,0x97,0xf4,0x55,0xb2,0x27,0x0f, 0x01,0x04,0x97,0xf4,0x55,0x7b,0x27,0x0f, - 0x01,0x04,0x97,0xf4,0x55,0x40,0x27,0x0f, - 0x01,0x04,0x97,0xf4,0x55,0x30,0x27,0x0f, - 0x01,0x04,0x95,0x1c,0xf1,0xbe,0x27,0x0f, - 0x01,0x04,0x93,0x5d,0x84,0x0c,0x27,0x0f, - 0x01,0x04,0x93,0x5d,0x83,0x34,0x27,0x0f, - 0x01,0x04,0x93,0x2d,0xb7,0x80,0x27,0x0f, - 0x01,0x04,0x93,0x2d,0x67,0x63,0x27,0x0f, - 0x01,0x04,0x92,0x3b,0x99,0xcc,0x27,0x0f, - 0x01,0x04,0x92,0x3b,0x2d,0xeb,0x27,0x0f, - 0x01,0x04,0x90,0x7e,0x8f,0xc5,0x27,0x0f, - 0x01,0x04,0x90,0x7e,0x8d,0x3e,0x27,0x0f, + 0x01,0x04,0x95,0x68,0x6e,0x77,0x27,0x0f, + 0x01,0x04,0x93,0x2d,0x29,0xd2,0x27,0x0f, + 0x01,0x04,0x90,0x1f,0xbc,0x2a,0x27,0x0f, 0x01,0x04,0x90,0x18,0xee,0xb2,0x27,0x0f, - 0x01,0x04,0x8e,0xb3,0xa2,0x0e,0x27,0x0f, - 0x01,0x04,0x8e,0x5d,0x95,0xb9,0x27,0x0f, - 0x01,0x04,0x8b,0xa2,0xd7,0xa9,0x27,0x0f, - 0x01,0x04,0x8b,0xa2,0xd3,0x4c,0x27,0x0f, - 0x01,0x04,0x8b,0x1c,0x61,0x02,0x27,0x0f, 0x01,0x04,0x88,0xf4,0x63,0x11,0x27,0x0f, - 0x01,0x04,0x88,0xf3,0x8e,0x27,0x27,0x0f, - 0x01,0x04,0x88,0xf3,0x8e,0x23,0x27,0x0f, - 0x01,0x04,0x87,0xb5,0x08,0x52,0x27,0x0f, - 0x01,0x04,0x86,0xff,0xb6,0xba,0x27,0x0f, 0x01,0x04,0x85,0x12,0x61,0xe2,0x27,0x0f, + 0x01,0x04,0x84,0xf3,0xc5,0xf0,0x27,0x0f, + 0x01,0x04,0x84,0xf3,0xc5,0xb3,0x27,0x0f, + 0x01,0x04,0x84,0xf3,0xc5,0x63,0x27,0x0f, + 0x01,0x04,0x84,0xf3,0xc5,0x17,0x27,0x0f, + 0x01,0x04,0x82,0xff,0x9b,0xa3,0x27,0x0f, 0x01,0x04,0x82,0xa2,0xe9,0xba,0x27,0x0f, 0x01,0x04,0x7b,0xc1,0x40,0xa6,0x27,0x0f, 0x01,0x04,0x73,0xbe,0xf8,0x39,0x27,0x0f, - 0x01,0x04,0x73,0x78,0xee,0xf0,0x27,0x0f, 0x01,0x04,0x72,0x84,0xac,0xd7,0x27,0x0f, 0x01,0x04,0x6d,0xeb,0x43,0xf6,0x27,0x0f, - 0x01,0x04,0x6d,0xc7,0x60,0x3d,0x27,0x0f, - 0x01,0x04,0x6d,0xad,0xf0,0xe9,0x27,0x0f, + 0x01,0x04,0x6c,0xa0,0x83,0xc0,0x27,0x0f, 0x01,0x04,0x6b,0xbd,0x03,0x4a,0x27,0x0f, 0x01,0x04,0x6b,0xb3,0xca,0x4a,0x27,0x0f, - 0x01,0x04,0x6b,0xae,0xcc,0x6a,0x27,0x0f, + 0x01,0x04,0x6b,0xae,0xcc,0xe8,0x27,0x0f, 0x01,0x04,0x6b,0xaa,0xfe,0xa0,0x27,0x0f, 0x01,0x04,0x6a,0x37,0x09,0x16,0x27,0x0f, 0x01,0x04,0x68,0xea,0xa7,0x73,0x27,0x0f, - 0x01,0x04,0x64,0x2a,0xb6,0xb5,0x27,0x0f, - 0x01,0x04,0x5f,0xb7,0x33,0x8d,0x27,0x0f, - 0x01,0x04,0x5f,0xab,0x15,0x83,0x27,0x0f, - 0x01,0x04,0x5e,0xac,0x6d,0xa1,0x27,0x0f, 0x01,0x04,0x5d,0x73,0xac,0x27,0x27,0x0f, - 0x01,0x04,0x5d,0x73,0xac,0x26,0x27,0x0f, 0x01,0x04,0x5d,0x73,0xac,0x25,0x27,0x0f, - 0x01,0x04,0x5c,0xff,0x4c,0x3b,0x27,0x0f, - 0x01,0x04,0x5c,0x35,0x78,0x59,0x27,0x0f, - 0x01,0x04,0x5b,0xef,0x05,0x0c,0x27,0x0f, 0x01,0x04,0x5b,0xc7,0x95,0xb1,0x27,0x0f, 0x01,0x04,0x5b,0xc6,0x6c,0x28,0x27,0x0f, 0x01,0x04,0x5b,0xc6,0x6c,0x27,0x27,0x0f, - 0x01,0x04,0x5b,0xc6,0x6c,0x26,0x27,0x0f, 0x01,0x04,0x5b,0xc6,0x6c,0x25,0x27,0x0f, - 0x01,0x04,0x5b,0xc6,0x6c,0x24,0x27,0x0f, 0x01,0x04,0x5b,0xc6,0x6c,0x23,0x27,0x0f, + 0x01,0x04,0x5b,0xb8,0xf9,0xd1,0x27,0x0f, 0x01,0x04,0x59,0xb3,0x49,0x60,0x27,0x0f, 0x01,0x04,0x59,0x7d,0xd1,0xc3,0x27,0x0f, - 0x01,0x04,0x59,0x7d,0xd1,0xb2,0x27,0x0f, - 0x01,0x04,0x59,0x7d,0xd1,0x78,0x27,0x0f, 0x01,0x04,0x59,0x7d,0xd1,0x6e,0x27,0x0f, - 0x01,0x04,0x59,0x7d,0xd1,0x6a,0x27,0x0f, 0x01,0x04,0x59,0x7d,0xd1,0x45,0x27,0x0f, + 0x01,0x04,0x59,0x75,0x39,0x1b,0x27,0x0f, 0x01,0x04,0x59,0x75,0x03,0xf2,0x27,0x0f, - 0x01,0x04,0x59,0x2f,0xa7,0x83,0x27,0x0f, 0x01,0x04,0x59,0x2e,0x2a,0xda,0x27,0x0f, - 0x01,0x04,0x59,0x2e,0x2a,0xd8,0x27,0x0f, - 0x01,0x04,0x59,0x28,0x0f,0xde,0x27,0x0f, 0x01,0x04,0x59,0x23,0x83,0x95,0x27,0x0f, - 0x01,0x04,0x59,0x23,0x83,0x3d,0x27,0x0f, - 0x01,0x04,0x59,0x23,0x83,0x27,0x27,0x0f, 0x01,0x04,0x57,0xe4,0x18,0x40,0x27,0x0f, 0x01,0x04,0x55,0xd1,0xf1,0xf5,0x27,0x0f, - 0x01,0x04,0x55,0xd1,0xf1,0xeb,0x27,0x0f, - 0x01,0x04,0x55,0xd1,0xf1,0xea,0x27,0x0f, - 0x01,0x04,0x55,0xd1,0xf1,0xc6,0x27,0x0f, - 0x01,0x04,0x55,0xd1,0xf1,0xb9,0x27,0x0f, 0x01,0x04,0x55,0xd1,0xf1,0x5d,0x27,0x0f, 0x01,0x04,0x55,0xd1,0xf1,0x57,0x27,0x0f, 0x01,0x04,0x55,0xd1,0xf1,0x56,0x27,0x0f, - 0x01,0x04,0x55,0xd1,0xf1,0x49,0x27,0x0f, - 0x01,0x04,0x55,0xd1,0xf1,0x0a,0x27,0x0f, - 0x01,0x04,0x55,0xc1,0x5a,0x6b,0x27,0x0f, - 0x01,0x04,0x55,0x5c,0x6f,0x6f,0x27,0x0f, + 0x01,0x04,0x55,0x9b,0xbc,0x8a,0x27,0x0f, 0x01,0x04,0x54,0xf7,0xb4,0xc9,0x27,0x0f, 0x01,0x04,0x54,0xf2,0xb3,0xcc,0x27,0x0f, + 0x01,0x04,0x54,0x62,0x0c,0xc4,0x27,0x0f, 0x01,0x04,0x54,0x09,0x32,0x11,0x27,0x0f, 0x01,0x04,0x53,0xef,0x63,0x28,0x27,0x0f, - 0x01,0x04,0x53,0xde,0x09,0xfd,0x27,0x0f, 0x01,0x04,0x53,0x95,0x64,0xba,0x27,0x0f, 0x01,0x04,0x53,0x95,0x64,0xb9,0x27,0x0f, 0x01,0x04,0x53,0x95,0x64,0xb8,0x27,0x0f, 0x01,0x04,0x53,0x95,0x64,0xb7,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0xf0,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0xe2,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0xb3,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0x83,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0x6e,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0x63,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0x20,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0x1e,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0x17,0x27,0x0f, - 0x01,0x04,0x52,0xd3,0x15,0x04,0x27,0x0f, 0x01,0x04,0x52,0xca,0xe6,0x53,0x27,0x0f, - 0x01,0x04,0x52,0xb4,0x95,0x6b,0x27,0x0f, 0x01,0x04,0x52,0xb4,0x92,0xc0,0x27,0x0f, 0x01,0x04,0x51,0xe3,0xfa,0x33,0x27,0x0f, - 0x01,0x04,0x51,0xc8,0x98,0x90,0x27,0x0f, 0x01,0x04,0x50,0xf9,0x93,0x08,0x27,0x0f, 0x01,0x04,0x50,0xf0,0x84,0xe7,0x27,0x0f, - 0x01,0x04,0x50,0xd1,0xef,0x81,0x27,0x0f, - 0x01,0x04,0x50,0xd1,0xe9,0xb6,0x27,0x0f, 0x01,0x04,0x50,0xd0,0xe6,0x90,0x27,0x0f, 0x01,0x04,0x4e,0x53,0x13,0x00,0x27,0x0f, 0x01,0x04,0x4d,0xdf,0x63,0x04,0x27,0x0f, 0x01,0x04,0x4d,0xdd,0x94,0xcc,0x27,0x0f, - 0x01,0x04,0x4a,0xd0,0xae,0x3f,0x27,0x0f, 0x01,0x04,0x4a,0x32,0x5a,0x71,0x27,0x0f, 0x01,0x04,0x48,0x3e,0x3a,0x6c,0x27,0x0f, 0x01,0x04,0x48,0x3c,0x26,0xa0,0x27,0x0f, - 0x01,0x04,0x46,0x22,0xc6,0x1a,0x27,0x0f, - 0x01,0x04,0x45,0xa7,0xa8,0x3f,0x27,0x0f, 0x01,0x04,0x45,0x3d,0x6b,0xd7,0x27,0x0f, 0x01,0x04,0x42,0xf5,0xc4,0x34,0x27,0x0f, 0x01,0x04,0x42,0xf4,0xf3,0x46,0x27,0x0f, - 0x01,0x04,0x42,0x2a,0x54,0x1b,0x27,0x0f, - 0x01,0x04,0x42,0x1d,0x93,0x53,0x27,0x0f, + 0x01,0x04,0x42,0xa3,0x71,0x71,0x27,0x0f, + 0x01,0x04,0x42,0xa3,0x71,0x5b,0x27,0x0f, + 0x01,0x04,0x42,0xa3,0x71,0x07,0x27,0x0f, + 0x01,0x04,0x3e,0xab,0x85,0x7d,0x27,0x0f, 0x01,0x04,0x3e,0x3c,0xf4,0xae,0x27,0x0f, - 0x01,0x04,0x39,0x80,0xd4,0xa3,0x27,0x0f, - 0x01,0x04,0x36,0x45,0x5f,0x76,0x27,0x0f, 0x01,0x04,0x34,0x24,0x66,0x5b,0x27,0x0f, 0x01,0x04,0x34,0x21,0x09,0xac,0x27,0x0f, - 0x01,0x04,0x34,0x0a,0xd5,0xc6,0x27,0x0f, 0x01,0x04,0x33,0x9e,0xbc,0x58,0x27,0x0f, + 0x01,0x04,0x33,0x9e,0xa9,0xed,0x27,0x0f, 0x01,0x04,0x33,0x9e,0xa7,0x1f,0x27,0x0f, - 0x01,0x04,0x33,0x4f,0x6d,0xc8,0x27,0x0f, - 0x01,0x04,0x33,0x4f,0x6d,0xb6,0x27,0x0f, - 0x01,0x04,0x32,0x74,0x1c,0x67,0x27,0x0f, - 0x01,0x04,0x2f,0x6e,0xc5,0x1d,0x27,0x0f, - 0x01,0x04,0x2f,0x6e,0xb8,0x33,0x27,0x0f, - 0x01,0x04,0x2f,0x6e,0xa5,0xb1,0x27,0x0f, - 0x01,0x04,0x2f,0x6e,0x9d,0x93,0x27,0x0f, - 0x01,0x04,0x2f,0x6e,0x9a,0x4d,0x27,0x0f, - 0x01,0x04,0x2f,0x6e,0x92,0x41,0x27,0x0f, - 0x01,0x04,0x2f,0x63,0xe5,0xd5,0x27,0x0f, - 0x01,0x04,0x2f,0x62,0x42,0x5f,0x27,0x0f, 0x01,0x04,0x2e,0xfa,0xfe,0x0a,0x27,0x0f, - 0x01,0x04,0x2e,0x94,0xe7,0x79,0x27,0x0f, 0x01,0x04,0x2e,0x24,0x28,0xf2,0x27,0x0f, - 0x01,0x04,0x2e,0x0a,0xf1,0xbf,0x27,0x0f, + 0x01,0x04,0x2e,0x1e,0xbd,0xbb,0x27,0x0f, 0x01,0x04,0x2e,0x04,0xa2,0x7f,0x27,0x0f, 0x01,0x04,0x2d,0x99,0xba,0x64,0x27,0x0f, - 0x01,0x04,0x2d,0x99,0x46,0x7e,0x27,0x0f, 0x01,0x04,0x2d,0x95,0x9a,0xc2,0x27,0x0f, - 0x01,0x04,0x2d,0x8c,0x13,0xc9,0x27,0x0f, - 0x01,0x04,0x2d,0x87,0xb4,0x82,0x27,0x0f, - 0x01,0x04,0x2d,0x87,0xb4,0x72,0x27,0x0f, - 0x01,0x04,0x2d,0x87,0xb4,0x4f,0x27,0x0f, - 0x01,0x04,0x2d,0x84,0x4a,0x59,0x27,0x0f, 0x01,0x04,0x2d,0x80,0x9c,0x1e,0x27,0x0f, - 0x01,0x04,0x2d,0x5b,0x5e,0xd9,0x27,0x0f, - 0x01,0x04,0x2d,0x4c,0x54,0x6c,0x27,0x0f, + 0x01,0x04,0x2d,0x4f,0x12,0x6a,0x27,0x0f, 0x01,0x04,0x2d,0x3d,0xba,0x79,0x27,0x0f, 0x01,0x04,0x2d,0x3a,0x38,0x4f,0x27,0x0f, - 0x01,0x04,0x2d,0x3a,0x34,0xf7,0x27,0x0f, 0x01,0x04,0x2c,0xf0,0x63,0xd6,0x27,0x0f, 0x01,0x04,0x2b,0xe5,0x4d,0x2e,0x27,0x0f, 0x01,0x04,0x2b,0xa7,0xf4,0x6d,0x27,0x0f, 0x01,0x04,0x2b,0xa7,0xef,0x91,0x27,0x0f, 0x01,0x04,0x2b,0x86,0xb4,0x71,0x27,0x0f, - 0x01,0x04,0x26,0xf2,0xc5,0xbd,0x27,0x0f, + 0x01,0x04,0x2b,0x85,0xab,0x65,0x27,0x0f, 0x01,0x04,0x26,0x66,0x7d,0x6c,0x27,0x0f, - 0x01,0x04,0x23,0xb4,0x80,0x0e,0x27,0x0f, - 0x01,0x04,0x23,0xae,0xd9,0x62,0x27,0x0f, - 0x01,0x04,0x22,0xd1,0x25,0xde,0x27,0x0f, + 0x01,0x04,0x26,0x36,0x0c,0x6f,0x27,0x0f, + 0x01,0x04,0x25,0x61,0xe3,0x15,0x27,0x0f, + 0x01,0x04,0x22,0xf6,0xb0,0x19,0x27,0x0f, 0x01,0x04,0x1f,0x94,0x63,0x94,0x27,0x0f, - 0x01,0x04,0x1f,0x3a,0xaa,0xb5,0x27,0x0f, - 0x01,0x04,0x1f,0x3a,0xaa,0xb4,0x27,0x0f, - 0x01,0x04,0x1f,0x3a,0xaa,0x8b,0x27,0x0f, - 0x01,0x04,0x1f,0x3a,0xaa,0x82,0x27,0x0f, 0x01,0x04,0x1f,0x0a,0x61,0x24,0x27,0x0f, - 0x01,0x04,0x0f,0xbc,0x35,0x0c,0x27,0x0f, - 0x01,0x04,0x08,0xde,0x93,0xa9,0x27,0x0f, - 0x01,0x04,0x08,0xde,0x92,0x95,0x27,0x0f, - 0x01,0x04,0x08,0xdb,0xf6,0xa4,0x27,0x0f, - 0x01,0x04,0x08,0xdb,0xdc,0xa0,0x27,0x0f, - 0x01,0x04,0x08,0xdb,0xce,0x2d,0x27,0x0f, - 0x01,0x04,0x08,0xdb,0xcd,0x81,0x27,0x0f, - 0x01,0x04,0x08,0xdb,0xcc,0x94,0x27,0x0f, - 0x01,0x04,0x08,0xdb,0xaa,0xf1,0x27,0x0f, - 0x01,0x04,0x08,0xdb,0xa0,0x93,0x27,0x0f, - 0x01,0x04,0x08,0xdb,0x36,0x7f,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0xe4,0x61,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xcb,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xca,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xc9,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xc7,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xbd,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xbc,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xba,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xb6,0x27,0x0f, - 0x01,0x04,0x05,0xe6,0x77,0xb4,0x27,0x0f, - 0x01,0x04,0x05,0xbd,0xa4,0xfd,0x27,0x0f, + 0x01,0x04,0x17,0xa3,0x00,0xae,0x27,0x0f, 0x01,0x04,0x05,0xa1,0x6e,0x4f,0x27,0x0f, - 0x01,0x04,0x05,0x35,0x7c,0x78,0x27,0x0f, - 0x01,0x04,0x05,0x27,0x0b,0x50,0x27,0x0f, - 0x01,0x04,0x05,0x27,0x0a,0x17,0x27,0x0f, - 0x01,0x04,0x05,0x23,0x67,0x7b,0x27,0x0f, - 0x01,0x04,0x05,0x23,0x67,0x1a,0x27,0x0f, - 0x01,0x04,0x05,0x23,0x67,0x19,0x27,0x0f, 0x01,0x04,0x05,0x23,0x67,0x13,0x27,0x0f, - 0x01,0x04,0x05,0x09,0xed,0x25,0x27,0x0f, - 0x01,0x04,0x05,0x09,0xed,0x20,0x27,0x0f, 0x01,0x04,0x05,0x02,0x49,0x3a,0x27,0x0f, 0x01,0x04,0x05,0x02,0x43,0xbe,0x27,0x0f, 0x01,0x04,0x02,0xe9,0x78,0x23,0x27,0x0f, - 0x01,0x04,0x02,0x39,0xf1,0xb2,0x27,0x0f, - 0x01,0x04,0x02,0x39,0xf1,0x9b,0x27,0x0f, - 0x01,0x04,0x02,0x38,0xd5,0xdd,0x27,0x0f, - 0x01,0x04,0x02,0x38,0xd5,0xda,0x27,0x0f, + 0x01,0x04,0x02,0x3b,0xdb,0x36,0x27,0x0f, + 0x01,0x04,0x01,0x75,0x4b,0xdc,0x27,0x0f, }; static const uint8_t chainparams_seed_test[] = { 0x01,0x04,0xd4,0x2f,0x44,0xc7,0x4e,0x1f, 0x01,0x04,0xb9,0xbb,0xa9,0xc1,0x4e,0x1f, + 0x01,0x04,0xce,0xf5,0xa7,0x3f,0x4e,0x1f, 0x01,0x04,0x93,0x5d,0x84,0x09,0x4e,0x1f, + 0x01,0x04,0x44,0x43,0x7a,0x48,0x4e,0x1f, + 0x01,0x04,0x44,0x43,0x7a,0x2a,0x4e,0x1f, + 0x01,0x04,0x44,0x43,0x7a,0x21,0x4e,0x1f, + 0x01,0x04,0x44,0x43,0x7a,0x17,0x4e,0x1f, 0x01,0x04,0x3e,0x3c,0xf4,0xae,0x4e,0x1f, 0x01,0x04,0x36,0xd5,0x5e,0xd8,0x4e,0x1f, 0x01,0x04,0x36,0xbf,0x92,0x89,0x4e,0x1f, From 78bb4c4a9de46a6194a831e047b33d47f0531b96 Mon Sep 17 00:00:00 2001 From: pasta Date: Sat, 13 Jun 2026 03:31:21 -0500 Subject: [PATCH 7/8] Merge #7359: fix: make huge asset lock tx non-standard c8801b247313bb4af5da8060b10c707da1031af5 test: add test for non-standard asset-locks (Konstantin Akimov) 9ad2afb91004097f1e95df6b7a2beb2deb1b4975 feat: make v2 asset locks and huge asset locks as non-standard (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented Platform ignores asset-locks with amount of inputs more than 100 or with size of transaction bigger than 20480 bytes. If user will create too big asset-lock transaction that platform (L2) can not recognize it may cause to fund lost. Issue is worsened once user will have ability to create asset-lock tx himself by Dash Core after https://github.com/dashpay/dash/pull/7294 It's an addition to this PR: https://github.com/dashpay/platform/pull/3491/files ## What was done? Asset locks that have more than 100 inputs are non-standard txes Asset locks that have size bigger than 20480 bytes are non-standard txes Asset locks that have v2 payload are non-standard txes. Once v24 is activated, platform may be not ready to process them. This non-standard limitation is a feature for soft enabling v2 asset-locks without 2nd fork. ## How Has This Been Tested? See updates in functional test. ## Breaking Changes Some special transactions are now valid for consensus if they are mined in block but they are non-standard and won't be relayed to network. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone Top commit has no ACKs. Tree-SHA512: ce2a6221f66367d839696ce2bfd93941a74eae1469276703fae06e1ccb3f979beaf14ca4dc05c75d03496cdabb5ae58d6b87b902c0a7bfb16e42d558cbb10d96 --- src/evo/specialtxman.cpp | 29 ++++++++++++++++++++++ src/evo/specialtxman.h | 16 ++++++++++++ src/validation.cpp | 3 +++ test/functional/feature_asset_locks.py | 34 ++++++++++++++++++++++++-- 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/src/evo/specialtxman.cpp b/src/evo/specialtxman.cpp index c1434cc9acc7..873742feb7cf 100644 --- a/src/evo/specialtxman.cpp +++ b/src/evo/specialtxman.cpp @@ -1234,3 +1234,32 @@ bool CheckProUpRevTx(const CTransaction& tx, gsl::not_null p return true; } + +bool IsStandardSpecialTx(const CTransaction& tx, std::string& reason) +{ + if (!tx.IsSpecialTxVersion()) return true; + + if (tx.nType != TRANSACTION_ASSET_LOCK) return true; + + // Each input is referenced by Platform's funding state transition; beyond this + // many inputs that state transition exceeds Platform's ~20 kB size limit. + static constexpr size_t MAX_STANDARD_ASSET_LOCK_INPUTS{100}; + if (tx.vin.size() > MAX_STANDARD_ASSET_LOCK_INPUTS) { + reason = "assetlocktx-too-many-inputs"; + return false; + } + + constexpr int max_tx_size_for_platform = 20480; + if (tx.GetTotalSize() > max_tx_size_for_platform) { + reason = "assetlocktx-too-big"; + return false; + } + + if (const auto opt_assetLockTx = GetTxPayload(tx); + opt_assetLockTx.has_value() && opt_assetLockTx->getVersion() >= 2) { + reason = "assetlocktx-version-2"; + return false; + } + + return true; +} diff --git a/src/evo/specialtxman.h b/src/evo/specialtxman.h index 2d5ab32096bb..a6164069a15e 100644 --- a/src/evo/specialtxman.h +++ b/src/evo/specialtxman.h @@ -104,4 +104,20 @@ bool CheckProUpRegTx(const CTransaction& tx, gsl::not_null p bool CheckProUpRevTx(const CTransaction& tx, gsl::not_null pindexPrev, CDeterministicMNManager& dmnman, const ChainstateManager& chainman, TxValidationState& state, bool check_sigs); + +/** + * Asset lock transactions with more than 100 inputs (and so over ~20 kB) can not + * be processed by Platform, so Dash Core nodes should not relay them: they are + * marked non-standard, which keeps the network from propagating them over p2p. + * + * Asset lock v2 is enabled by the v24 fork, but Platform can not process it yet. + * It is kept non-standard so it can be enabled later without another hard fork. + * + * These are relay/mempool checks only: a rejected transaction stays valid inside + * a block. + * + * Returns false (with `reason` set) for a non-standard asset lock, and + * true for any transaction that is not an asset lock or not special-tx. + */ +bool IsStandardSpecialTx(const CTransaction& tx, std::string& reason); #endif // BITCOIN_EVO_SPECIALTXMAN_H diff --git a/src/validation.cpp b/src/validation.cpp index e9641a545224..eec5df7cc815 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -787,6 +787,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) if (fRequireStandard && !IsStandardTx(tx, reason)) return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason); + if (fRequireStandard && !IsStandardSpecialTx(tx, reason)) + return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason); + // Do not work on transactions that are too small. // A transaction with 1 empty scriptSig input and 1 P2SH output has size of 83 bytes. // Transactions smaller than this are not relayed to mitigate CVE-2017-12842 by not relaying diff --git a/test/functional/feature_asset_locks.py b/test/functional/feature_asset_locks.py index 24d9ccf27277..eea745b5494e 100755 --- a/test/functional/feature_asset_locks.py +++ b/test/functional/feature_asset_locks.py @@ -67,7 +67,8 @@ def create_assetlock(self, coin, amount, pubkey): node_wallet = self.nodes[0] - inputs = [CTxIn(COutPoint(int(coin["txid"], 16), coin["vout"]))] + coins = coin if isinstance(coin, list) else [coin] + inputs = [CTxIn(COutPoint(int(c["txid"], 16), c["vout"])) for c in coins] credit_outputs = [] tmp_amount = amount @@ -78,7 +79,7 @@ def create_assetlock(self, coin, amount, pubkey): lockTx_payload = CAssetLockTx(1, credit_outputs) - remaining = int(COIN * coin['amount']) - tiny_amount - amount + remaining = sum(int(COIN * c['amount']) for c in coins) - tiny_amount - amount tx_output_ret = CTxOut(amount, CScript([OP_RETURN, b""])) tx_output = CTxOut(remaining, key_to_p2pk_script(pubkey)) @@ -270,6 +271,7 @@ def run_test(self): self.test_mn_rr(node_wallet, node, pubkey) self.test_withdrawals_fork(node_wallet, node, pubkey) self.test_v24_fork(node_wallet, node, pubkey) + self.test_non_standard(node_wallet, node, pubkey) def test_asset_locks(self, node_wallet, node, pubkey): @@ -761,5 +763,33 @@ def test_v24_fork(self, node_wallet, node, pubkey): assert txid_in_block not in node.getblock(tip_hash)['tx'] + def test_non_standard(self, node_wallet, node, pubkey): + self.log.info("Split one coin into 101 outputs to build an asset lock with >100 inputs") + raw = node_wallet.createrawtransaction([], [{node_wallet.getnewaddress(): 1} for _ in range(101)]) + funded = node_wallet.fundrawtransaction(raw, {'change_position': 101})['hex'] + split_txid = node_wallet.sendrawtransaction(node_wallet.signrawtransactionwithwallet(funded)['hex']) + self.generate(node, 1) + many_coins = [{'txid': split_txid, 'vout': i, 'amount': 1} for i in range(101)] + tx_many_inputs = self.create_assetlock(many_coins, COIN, pubkey) + assert_equal(len(tx_many_inputs.vin), 101) + + self.log.info("A standard node (-acceptnonstdtxn=1) rejects them; the permissive node accepts them") + self.restart_node(1, self.extra_args[1] + ["-acceptnonstdtxn=1"]) + self.connect_nodes(1, 0) + + tx_hex = tx_many_inputs.serialize().hex() + assert_equal(node.testmempoolaccept([tx_hex])[0]['allowed'], True) + rejected = node_wallet.testmempoolaccept([tx_hex])[0] + assert_equal(rejected['allowed'], False) + assert_equal(rejected['reject-reason'], 'assetlocktx-too-many-inputs') + + txid = node.sendrawtransaction(tx_hex) + block_hash = self.generate(node, 1)[0] + for checked_node in self.nodes: + assert txid in checked_node.getblock(block_hash)['tx'] + self.restart_node(1, self.extra_args[1]) + self.connect_nodes(1, 0) + + if __name__ == '__main__': AssetLocksTest().main() From 6f7a0eff4d7b6c91db973dad6503aeb576c9825f Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 13 Jun 2026 03:09:13 +0700 Subject: [PATCH 8/8] chore: version bump, man pages, flatpak, release notes for release v23.1.4 --- configure.ac | 2 +- .../flatpak/org.dash.dash-core.metainfo.xml | 1 + doc/man/dash-cli.1 | 6 +- doc/man/dash-qt.1 | 6 +- doc/man/dash-util.1 | 6 +- doc/man/dash-wallet.1 | 6 +- doc/man/dashd.1 | 6 +- doc/release-notes.md | 33 ++++++--- .../dash/release-notes-23.1.3.md | 72 +++++++++++++++++++ 9 files changed, 112 insertions(+), 26 deletions(-) create mode 100644 doc/release-notes/dash/release-notes-23.1.3.md diff --git a/configure.ac b/configure.ac index cf82907c421e..6f86a0af5210 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) dnl Don't forget to push a corresponding tag when updating any of _CLIENT_VERSION_* numbers define(_CLIENT_VERSION_MAJOR, 23) define(_CLIENT_VERSION_MINOR, 1) -define(_CLIENT_VERSION_BUILD, 3) +define(_CLIENT_VERSION_BUILD, 4) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2026) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/contrib/flatpak/org.dash.dash-core.metainfo.xml b/contrib/flatpak/org.dash.dash-core.metainfo.xml index 0c55086cbe41..151ab757926d 100644 --- a/contrib/flatpak/org.dash.dash-core.metainfo.xml +++ b/contrib/flatpak/org.dash.dash-core.metainfo.xml @@ -21,6 +21,7 @@ + diff --git a/doc/man/dash-cli.1 b/doc/man/dash-cli.1 index 9cc231e532ee..3c24d052df1b 100644 --- a/doc/man/dash-cli.1 +++ b/doc/man/dash-cli.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASH-CLI "1" "May 2026" "dash-cli v23.1.3" "User Commands" +.TH DASH-CLI "1" "June 2026" "dash-cli v23.1.4" "User Commands" .SH NAME -dash-cli \- manual page for dash-cli v23.1.3 +dash-cli \- manual page for dash-cli v23.1.4 .SH SYNOPSIS .B dash-cli [\fI\,options\/\fR] \fI\, \/\fR[\fI\,params\/\fR] \fI\,Send command to Dash Core\/\fR @@ -15,7 +15,7 @@ dash-cli \- manual page for dash-cli v23.1.3 .B dash-cli [\fI\,options\/\fR] \fI\,help Get help for a command\/\fR .SH DESCRIPTION -Dash Core RPC client version v23.1.3 +Dash Core RPC client version v23.1.4 .SH OPTIONS .HP \-? diff --git a/doc/man/dash-qt.1 b/doc/man/dash-qt.1 index 54655be0285a..93074e1cab3b 100644 --- a/doc/man/dash-qt.1 +++ b/doc/man/dash-qt.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASH-QT "1" "May 2026" "dash-qt v23.1.3" "User Commands" +.TH DASH-QT "1" "June 2026" "dash-qt v23.1.4" "User Commands" .SH NAME -dash-qt \- manual page for dash-qt v23.1.3 +dash-qt \- manual page for dash-qt v23.1.4 .SH SYNOPSIS .B dash-qt [\fI\,command-line options\/\fR] [\fI\,URI\/\fR] .SH DESCRIPTION -Dash Core version v23.1.3 +Dash Core version v23.1.4 .PP Optional URI is a Dash address in BIP21 URI format. .SH OPTIONS diff --git a/doc/man/dash-util.1 b/doc/man/dash-util.1 index f65c79eae172..d0251569b6e1 100644 --- a/doc/man/dash-util.1 +++ b/doc/man/dash-util.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASH-UTIL "1" "May 2026" "dash-util v23.1.3" "User Commands" +.TH DASH-UTIL "1" "June 2026" "dash-util v23.1.4" "User Commands" .SH NAME -dash-util \- manual page for dash-util v23.1.3 +dash-util \- manual page for dash-util v23.1.4 .SH SYNOPSIS .B dash-util [\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR .SH DESCRIPTION -Dash Core dash\-util utility version v23.1.3 +Dash Core dash\-util utility version v23.1.4 .SH OPTIONS .HP \-? diff --git a/doc/man/dash-wallet.1 b/doc/man/dash-wallet.1 index 127882e90910..32f9fe0bab78 100644 --- a/doc/man/dash-wallet.1 +++ b/doc/man/dash-wallet.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASH-WALLET "1" "May 2026" "dash-wallet v23.1.3" "User Commands" +.TH DASH-WALLET "1" "June 2026" "dash-wallet v23.1.4" "User Commands" .SH NAME -dash-wallet \- manual page for dash-wallet v23.1.3 +dash-wallet \- manual page for dash-wallet v23.1.4 .SH DESCRIPTION -Dash Core dash\-wallet version v23.1.3 +Dash Core dash\-wallet version v23.1.4 .PP dash\-wallet is an offline tool for creating and interacting with Dash Core wallet files. By default dash\-wallet will act on wallets in the default mainnet wallet directory in the datadir. diff --git a/doc/man/dashd.1 b/doc/man/dashd.1 index 9f7b1d8cec1f..577c049d2776 100644 --- a/doc/man/dashd.1 +++ b/doc/man/dashd.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASHD "1" "May 2026" "dashd v23.1.3" "User Commands" +.TH DASHD "1" "June 2026" "dashd v23.1.4" "User Commands" .SH NAME -dashd \- manual page for dashd v23.1.3 +dashd \- manual page for dashd v23.1.4 .SH SYNOPSIS .B dashd [\fI\,options\/\fR] \fI\,Start Dash Core\/\fR .SH DESCRIPTION -Dash Core version v23.1.3 +Dash Core version v23.1.4 .SH OPTIONS .HP \-? diff --git a/doc/release-notes.md b/doc/release-notes.md index 651adca404b6..37aeaede22c7 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -25,18 +25,31 @@ require a reindex. # Release Notes -## GUI changes - -- Restored the Send button when using an external signer (dash#7271). +## Notable changes +- Asset lock transactions that Dash Platform cannot process are now treated as + non-standard, so they are no longer relayed across the network. + This covers asset locks with more than 100 inputs, or larger than 20480 bytes, + and those using the v2 payload (for post-v24 release), protecting users from + creating oversized asset locks that could result in lost funds. + Such transactions remain valid for consensus if mined into a block (dash#7359). ## Bug Fixes -- Kept relaying InstantSend lock inventory messages to non-masternode peers that request recovered signatures (dash#7293). -- Reverted an improper dual-way connection attempt avoidance change that could break recovered-signature handshakes under spork 21 (dash#7289). -- Fixed intermittent incorrect `CheckQueue` logging for invalid blocks (dash#7312). -- Fixed `listaddressbalances` RPC help so the documented result matches returned address balances (dash#7279). +- Reject two ProRegTx/ProUpServTx with the same Platform node ID from being + present in the mempool simultaneously. + +## Performance Improvements + +- Reduced lock contention when penalizing peers for invalid transactions, + improving networking responsiveness under load (dash#7332). +- Made header sync almost twice as fast by optimization of low-level math + primitives (dash#7352). +- Avoid re-validation of EHF signals during block connect. This also prevents + a potential assertion crash during large blockchain re-organizations when a + buried fork is re-validated in `BlockUndo`. + -# v23.1.3 Change log +# v23.1.4 Change log See detailed [set of changes][set-of-changes]. @@ -45,7 +58,6 @@ See detailed [set of changes][set-of-changes]. Thanks to everyone who directly contributed to this release: - Konstantin Akimov -- PastaPastaPasta As well as everyone that submitted issues, reviewed pull requests and helped debug the release candidates. @@ -54,6 +66,7 @@ debug the release candidates. These releases are considered obsolete. Old release notes can be found here: +- [v23.1.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-23.1.3.md) released May/28/2026 - [v23.1.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-23.1.2.md) released Mar/12/2026 - [v23.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-23.1.0.md) released Feb/15/2026 - [v23.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-23.0.2.md) released Dec/4/2025 @@ -69,4 +82,4 @@ These releases are considered obsolete. Old release notes can be found here: - [v21.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.0.0.md) released Jul/25/2024 - [v20.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.1.1.md) released April/3/2024 -[set-of-changes]: https://github.com/dashpay/dash/compare/v23.1.2...dashpay:v23.1.3 +[set-of-changes]: https://github.com/dashpay/dash/compare/v23.1.3...dashpay:v23.1.4 diff --git a/doc/release-notes/dash/release-notes-23.1.3.md b/doc/release-notes/dash/release-notes-23.1.3.md new file mode 100644 index 000000000000..651adca404b6 --- /dev/null +++ b/doc/release-notes/dash/release-notes-23.1.3.md @@ -0,0 +1,72 @@ +# Dash Core version v23.1.3 + +This is a new patch version release, bringing GUI improvements and bugfixes. +This release is **optional** for all nodes, although recommended. + +Please report bugs using the issue tracker at GitHub: + + + +# Upgrading and downgrading + +## How to Upgrade + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes for older versions), then run the +installer (on Windows) or just copy over /Applications/Dash-Qt (on Mac) or +dashd/dash-qt (on Linux). + +## Downgrade warning + +### Downgrade to a version < v23.0.0 + +Downgrading to a version older than v23.0.0 is not supported, and will +require a reindex. + +# Release Notes + +## GUI changes + +- Restored the Send button when using an external signer (dash#7271). + +## Bug Fixes + +- Kept relaying InstantSend lock inventory messages to non-masternode peers that request recovered signatures (dash#7293). +- Reverted an improper dual-way connection attempt avoidance change that could break recovered-signature handshakes under spork 21 (dash#7289). +- Fixed intermittent incorrect `CheckQueue` logging for invalid blocks (dash#7312). +- Fixed `listaddressbalances` RPC help so the documented result matches returned address balances (dash#7279). + +# v23.1.3 Change log + +See detailed [set of changes][set-of-changes]. + +# Credits + +Thanks to everyone who directly contributed to this release: + +- Konstantin Akimov +- PastaPastaPasta + +As well as everyone that submitted issues, reviewed pull requests and helped +debug the release candidates. + +# Older releases + +These releases are considered obsolete. Old release notes can be found here: + +- [v23.1.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-23.1.2.md) released Mar/12/2026 +- [v23.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-23.1.0.md) released Feb/15/2026 +- [v23.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-23.0.2.md) released Dec/4/2025 +- [v23.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-23.0.0.md) released Nov/10/2025 +- [v22.1.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-22.1.3.md) released Jul/15/2025 +- [v22.1.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-22.1.2.md) released Apr/15/2025 +- [v22.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-22.1.1.md) released Feb/17/2025 +- [v22.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-22.1.0.md) released Feb/10/2025 +- [v22.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-22.0.0.md) released Dec/12/2024 +- [v21.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.1.1.md) released Oct/22/2024 +- [v21.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.1.0.md) released Aug/8/2024 +- [v21.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.0.2.md) released Aug/1/2024 +- [v21.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.0.0.md) released Jul/25/2024 +- [v20.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.1.1.md) released April/3/2024 + +[set-of-changes]: https://github.com/dashpay/dash/compare/v23.1.2...dashpay:v23.1.3