From d2b1becd975c5aa4611eb1099d4bfc52011aef96 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Tue, 24 Oct 2023 20:57:58 +0200 Subject: [PATCH] deprecate non-deterministic islocks --- src/Makefile.test.include | 1 - src/llmq/instantsend.cpp | 75 +++-------- src/llmq/instantsend.h | 10 +- src/llmq/snapshot.cpp | 2 +- src/net_processing.cpp | 16 +-- src/protocol.cpp | 1 - src/protocol.h | 3 +- src/test/evo_instantsend_tests.cpp | 40 ------ test/functional/feature_llmq_chainlocks.py | 13 +- test/functional/feature_llmq_evo.py | 14 +- .../feature_llmq_is_cl_conflicts.py | 37 ++++-- test/functional/feature_llmq_is_migration.py | 122 ------------------ .../functional/feature_llmq_is_retroactive.py | 18 ++- test/functional/feature_notifications.py | 14 +- test/functional/interface_zmq_dash.py | 47 +++---- test/functional/p2p_instantsend.py | 12 +- test/functional/rpc_verifyislock.py | 50 +++---- test/functional/test_framework/messages.py | 25 ---- test/functional/test_framework/mininode.py | 2 - .../test_framework/test_framework.py | 16 +-- test/functional/test_runner.py | 1 - 21 files changed, 165 insertions(+), 354 deletions(-) delete mode 100644 src/test/evo_instantsend_tests.cpp delete mode 100755 test/functional/feature_llmq_is_migration.py diff --git a/src/Makefile.test.include b/src/Makefile.test.include index b425f6444e5888..5f36425f7a1fa7 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -108,7 +108,6 @@ BITCOIN_TESTS =\ test/dynamic_activation_thresholds_tests.cpp \ test/evo_assetlocks_tests.cpp \ test/evo_deterministicmns_tests.cpp \ - test/evo_instantsend_tests.cpp \ test/evo_mnhf_tests.cpp \ test/evo_simplifiedmns_tests.cpp \ test/evo_trivialvalidation.cpp \ diff --git a/src/llmq/instantsend.cpp b/src/llmq/instantsend.cpp index 9f00f54c133d91..2006ca3b991698 100644 --- a/src/llmq/instantsend.cpp +++ b/src/llmq/instantsend.cpp @@ -697,23 +697,18 @@ void CInstantSendManager::TrySignInstantSendLock(const CTransaction& tx) LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: got all recovered sigs, creating CInstantSendLock\n", __func__, tx.GetHash().ToString()); - CInstantSendLock islock(llmqType == Params().GetConsensus().llmqTypeDIP0024InstantSend ? - CInstantSendLock::isdlock_version: - CInstantSendLock::islock_version); + CInstantSendLock islock; islock.txid = tx.GetHash(); for (const auto& in : tx.vin) { islock.inputs.emplace_back(in.prevout); } - // compute and set cycle hash if islock is deterministic - if (islock.IsDeterministic()) { - const auto& llmq_params_opt = GetLLMQParams(llmqType); - assert(llmq_params_opt); - LOCK(cs_main); - const auto dkgInterval = llmq_params_opt->dkgInterval; - const auto quorumHeight = m_chainstate.m_chain.Height() - (m_chainstate.m_chain.Height() % dkgInterval); - islock.cycleHash = m_chainstate.m_chain[quorumHeight]->GetBlockHash(); - } + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt); + LOCK(cs_main); + const auto dkgInterval = llmq_params_opt->dkgInterval; + const auto quorumHeight = m_chainstate.m_chain.Height() - (m_chainstate.m_chain.Height() % dkgInterval); + islock.cycleHash = m_chainstate.m_chain[quorumHeight]->GetBlockHash(); auto id = islock.GetRequestId(); @@ -771,9 +766,8 @@ void CInstantSendManager::ProcessMessage(const CNode& pfrom, const std::string& return; } - if (msg_type == NetMsgType::ISLOCK || msg_type == NetMsgType::ISDLOCK) { - const auto islock_version = msg_type == NetMsgType::ISLOCK ? CInstantSendLock::islock_version : CInstantSendLock::isdlock_version; - const auto islock = std::make_shared(islock_version); + if (msg_type == NetMsgType::ISDLOCK) { + const auto islock = std::make_shared(CInstantSendLock::isdlock_version); vRecv >> *islock; ProcessMessageInstantSendLock(pfrom, islock); } @@ -786,7 +780,7 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, cons bool fDIP0024IsActive = false; { LOCK(cs_main); - EraseObjectRequest(pfrom.GetId(), CInv(islock->IsDeterministic() ? MSG_ISDLOCK : MSG_ISLOCK, hash)); + EraseObjectRequest(pfrom.GetId(), CInv(MSG_ISDLOCK, hash)); fDIP0024IsActive = utils::IsDIP0024Active(m_chainstate.m_chain.Tip()); } @@ -796,7 +790,7 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, cons } // Deterministic ISLocks are only produced by rotation quorums, if we don't see DIP24 as active, then we won't be able to validate it anyway - if (islock->IsDeterministic() && fDIP0024IsActive) { + if (fDIP0024IsActive) { const auto blockIndex = WITH_LOCK(cs_main, return m_chainstate.m_blockman.LookupBlockIndex(islock->cycleHash)); if (blockIndex == nullptr) { // Maybe we don't have the block yet or maybe some peer spams invalid values for cycleHash @@ -854,19 +848,6 @@ bool CInstantSendLock::TriviallyValid() const } bool CInstantSendManager::ProcessPendingInstantSendLocks() -{ - const CBlockIndex* pBlockIndexTip = WITH_LOCK(cs_main, return m_chainstate.m_chain.Tip()); - if (pBlockIndexTip && utils::GetInstantSendLLMQType(qman, pBlockIndexTip) == Params().GetConsensus().llmqTypeDIP0024InstantSend) { - // Don't short circuit. Try to process both deterministic and not deterministic islocks independable - bool deterministicRes = ProcessPendingInstantSendLocks(true); - bool nondeterministicRes = ProcessPendingInstantSendLocks(false); - return deterministicRes && nondeterministicRes; - } else { - return ProcessPendingInstantSendLocks(false); - } -} - -bool CInstantSendManager::ProcessPendingInstantSendLocks(bool deterministic) { decltype(pendingInstantSendLocks) pend; bool fMoreWork{false}; @@ -885,16 +866,11 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks(bool deterministic) removed.reserve(maxCount); for (const auto& [islockHash, nodeid_islptr_pair] : pendingInstantSendLocks) { - const auto& [_, islock_ptr] = nodeid_islptr_pair; // Check if we've reached max count if (pend.size() >= maxCount) { fMoreWork = true; break; } - // Check if we care about this islock on this run - if (islock_ptr->IsDeterministic() != deterministic) { - continue; - } pend.emplace(islockHash, std::move(nodeid_islptr_pair)); removed.emplace_back(islockHash); } @@ -909,7 +885,7 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks(bool deterministic) } //TODO Investigate if leaving this is ok - auto llmqType = utils::GetInstantSendLLMQType(deterministic); + auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend; const auto& llmq_params_opt = GetLLMQParams(llmqType); assert(llmq_params_opt); const auto& llmq_params = llmq_params_opt.value(); @@ -965,7 +941,7 @@ std::unordered_set CInstantSendManager::ProcessPend } int nSignHeight{-1}; - if (islock->IsDeterministic()) { + { LOCK(cs_main); const auto blockIndex = m_chainstate.m_blockman.LookupBlockIndex(islock->cycleHash); @@ -1075,18 +1051,8 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, const uint256& has const auto sameTxIsLock = db.GetInstantSendLockByTxid(islock->txid); if (sameTxIsLock != nullptr) { - if (sameTxIsLock->IsDeterministic() == islock->IsDeterministic()) { - // shouldn't happen, investigate - LogPrintf("CInstantSendManager::%s -- txid=%s, islock=%s: duplicate islock, other islock=%s, peer=%d\n", __func__, - islock->txid.ToString(), hash.ToString(), ::SerializeHash(*sameTxIsLock).ToString(), from); - } - if (sameTxIsLock->IsDeterministic()) { - // can happen, nothing to do - return; - } else if (islock->IsDeterministic()) { - // can happen, remove and archive the non-deterministic sameTxIsLock - db.RemoveAndArchiveInstantSendLock(sameTxIsLock, WITH_LOCK(::cs_main, return m_chainstate.m_chain.Height())); - } + // can happen, nothing to do + return; } else { for (const auto& in : islock->inputs) { const auto sameOutpointIsLock = db.GetInstantSendLockByInput(in); @@ -1114,14 +1080,13 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, const uint256& has // We only need the ISLOCK from now on to detect conflicts TruncateRecoveredSigsForInputs(*islock); - const auto is_det = islock->IsDeterministic(); - CInv inv(is_det ? MSG_ISDLOCK : MSG_ISLOCK, hash); + CInv inv(MSG_ISDLOCK, hash); if (tx != nullptr) { - connman.RelayInvFiltered(inv, *tx, is_det ? ISDLOCK_PROTO_VERSION : MIN_PEER_PROTO_VERSION); + connman.RelayInvFiltered(inv, *tx, ISDLOCK_PROTO_VERSION); } else { // we don't have the TX yet, so we only filter based on txid. Later when that TX arrives, we will re-announce // with the TX taken into account. - connman.RelayInvFiltered(inv, islock->txid, is_det ? ISDLOCK_PROTO_VERSION : MIN_PEER_PROTO_VERSION); + connman.RelayInvFiltered(inv, islock->txid, ISDLOCK_PROTO_VERSION); } ResolveBlockConflicts(hash, *islock); @@ -1309,7 +1274,7 @@ void CInstantSendManager::TruncateRecoveredSigsForInputs(const llmq::CInstantSen for (const auto& in : islock.inputs) { auto inputRequestId = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in)); WITH_LOCK(cs_inputReqests, inputRequestIds.erase(inputRequestId)); - sigman.TruncateRecoveredSig(utils::GetInstantSendLLMQType(islock.IsDeterministic()), inputRequestId); + sigman.TruncateRecoveredSig(utils::GetInstantSendLLMQType(true), inputRequestId); } } @@ -1360,7 +1325,7 @@ void CInstantSendManager::HandleFullyConfirmedBlock(const CBlockIndex* pindex) // And we don't need the recovered sig for the ISLOCK anymore, as the block in which it got mined is considered // fully confirmed now - sigman.TruncateRecoveredSig(utils::GetInstantSendLLMQType(islock->IsDeterministic()), islock->GetRequestId()); + sigman.TruncateRecoveredSig(utils::GetInstantSendLLMQType(true), islock->GetRequestId()); } db.RemoveArchivedInstantSendLocks(pindex->nHeight - 100); diff --git a/src/llmq/instantsend.h b/src/llmq/instantsend.h index 777af30f24c462..152c96ff0cd249 100644 --- a/src/llmq/instantsend.h +++ b/src/llmq/instantsend.h @@ -46,24 +46,23 @@ struct CInstantSendLock uint256 cycleHash; CBLSLazySignature sig; - CInstantSendLock() : CInstantSendLock(islock_version) {} + CInstantSendLock() : CInstantSendLock(isdlock_version) {} explicit CInstantSendLock(const uint8_t desiredVersion) : nVersion(desiredVersion) {} SERIALIZE_METHODS(CInstantSendLock, obj) { - if (s.GetVersion() >= ISDLOCK_PROTO_VERSION && obj.IsDeterministic()) { + if (s.GetVersion() >= ISDLOCK_PROTO_VERSION) { READWRITE(obj.nVersion); } READWRITE(obj.inputs); READWRITE(obj.txid); - if (s.GetVersion() >= ISDLOCK_PROTO_VERSION && obj.IsDeterministic()) { + if (s.GetVersion() >= ISDLOCK_PROTO_VERSION) { READWRITE(obj.cycleHash); } READWRITE(obj.sig); } uint256 GetRequestId() const; - bool IsDeterministic() const { return nVersion != islock_version; } bool TriviallyValid() const; }; @@ -293,8 +292,7 @@ class CInstantSendManager : public CRecoveredSigsListener void TrySignInstantSendLock(const CTransaction& tx) LOCKS_EXCLUDED(cs_creating); void ProcessMessageInstantSendLock(const CNode& pfrom, const CInstantSendLockPtr& islock); - bool ProcessPendingInstantSendLocks(); - bool ProcessPendingInstantSendLocks(bool deterministic) LOCKS_EXCLUDED(cs_pendingLocks); + bool ProcessPendingInstantSendLocks() LOCKS_EXCLUDED(cs_pendingLocks); std::unordered_set ProcessPendingInstantSendLocks(const Consensus::LLMQParams& llmq_params, int signOffset, diff --git a/src/llmq/snapshot.cpp b/src/llmq/snapshot.cpp index c5509d3ef43840..49ab16182209d8 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -134,7 +134,7 @@ bool BuildQuorumRotationInfo(const CGetQuorumRotationInfo& request, CQuorumRotat } //Quorum rotation is enabled only for InstantSend atm. - Consensus::LLMQType llmqType = utils::GetInstantSendLLMQType(qman, blockIndex); + Consensus::LLMQType llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend; // Since the returned quorums are in reversed order, the most recent one is at index 0 const auto& llmq_params_opt = GetLLMQParams(llmqType); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index e017cb14eb3940..97cc99ea84248f 100755 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1053,7 +1053,6 @@ std::chrono::microseconds GetObjectInterval(int invType) return std::chrono::seconds{15}; case MSG_CLSIG: return std::chrono::seconds{5}; - case MSG_ISLOCK: case MSG_ISDLOCK: return std::chrono::seconds{10}; default: @@ -1879,7 +1878,6 @@ bool PeerManagerImpl::AlreadyHave(const CInv& inv) return m_llmq_ctx->sigman->AlreadyHave(inv); case MSG_CLSIG: return m_llmq_ctx->clhandler->AlreadyHave(inv); - case MSG_ISLOCK: case MSG_ISDLOCK: return m_llmq_ctx->isman->AlreadyHave(inv); } @@ -2042,7 +2040,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, const CChainParams& chai for (PairType &pair : merkleBlock.vMatchedTxn) { auto islock = isman.GetInstantSendLockByTxid(pair.second); if (islock != nullptr) { - connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::ISLOCK, *islock)); + connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::ISDLOCK, *islock)); } } } @@ -2258,10 +2256,10 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic } } - if (!push && (inv.type == MSG_ISLOCK || inv.type == MSG_ISDLOCK)) { + if (!push && inv.type == MSG_ISDLOCK) { llmq::CInstantSendLock o; if (m_llmq_ctx->isman->GetInstantSendLockByHash(inv.hash, o)) { - const auto msg_type = inv.type == MSG_ISLOCK ? NetMsgType::ISLOCK : NetMsgType::ISDLOCK; + const auto msg_type = NetMsgType::ISDLOCK; m_connman.PushMessage(&pfrom, msgMaker.Make(msg_type, o)); push = true; } @@ -3281,7 +3279,7 @@ void PeerManagerImpl::ProcessMessage( pfrom.fDisconnect = true; return; } else if (!fAlreadyHave) { - if (fBlocksOnly && (inv.type == MSG_ISLOCK || inv.type == MSG_ISDLOCK)) { + if (fBlocksOnly && inv.type == MSG_ISDLOCK) { if (pfrom.GetRecvVersion() <= ADDRV2_PROTO_VERSION) { // It's ok to receive these invs, we just ignore them // and do not request corresponding objects. @@ -4985,8 +4983,8 @@ bool PeerManagerImpl::SendMessages(CNode* pto) const auto islock = m_llmq_ctx->isman->GetInstantSendLockByTxid(hash); if (islock == nullptr) continue; - if (pto->nVersion < ISDLOCK_PROTO_VERSION && islock->IsDeterministic()) continue; - queueAndMaybePushInv(CInv(islock->IsDeterministic() ? MSG_ISDLOCK : MSG_ISLOCK, ::SerializeHash(*islock))); + if (pto->nVersion < ISDLOCK_PROTO_VERSION) continue; + queueAndMaybePushInv(CInv(MSG_ISDLOCK, ::SerializeHash(*islock))); } // Send an inv for the best ChainLock we have @@ -5068,7 +5066,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto) if (pto->m_tx_relay->filterInventoryKnown.contains(inv.hash)) { continue; } - if (!fSendIS && (inv.type == MSG_ISLOCK || inv.type == MSG_ISDLOCK)) { + if (!fSendIS && inv.type == MSG_ISDLOCK) { continue; } queueAndMaybePushInv(inv); diff --git a/src/protocol.cpp b/src/protocol.cpp index c03db8e98f4a00..fa711992da6b43 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -298,7 +298,6 @@ const char* CInv::GetCommandInternal() const case MSG_QUORUM_PREMATURE_COMMITMENT: return NetMsgType::QPCOMMITMENT; case MSG_QUORUM_RECOVERED_SIG: return NetMsgType::QSIGREC; case MSG_CLSIG: return NetMsgType::CLSIG; - case MSG_ISLOCK: return NetMsgType::ISLOCK; case MSG_ISDLOCK: return NetMsgType::ISDLOCK; default: return nullptr; diff --git a/src/protocol.h b/src/protocol.h index 266382dccda815..64bd2382f4fc1e 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -287,7 +287,6 @@ extern const char* QSIGSHARE; extern const char* QGETDATA; extern const char* QDATA; extern const char* CLSIG; -extern const char* ISLOCK; extern const char* ISDLOCK; extern const char* MNAUTH; extern const char* GETHEADERS2; @@ -525,7 +524,7 @@ enum GetDataMsg { /* MSG_QUORUM_DEBUG_STATUS = 27, */ // was shortly used on testnet/devnet/regtest MSG_QUORUM_RECOVERED_SIG = 28, MSG_CLSIG = 29, - MSG_ISLOCK = 30, + /* MSG_ISLOCK = 30, */ // Non-deterministic InstantSend and not used anymore MSG_ISDLOCK = 31, }; diff --git a/src/test/evo_instantsend_tests.cpp b/src/test/evo_instantsend_tests.cpp deleted file mode 100644 index 960204e31da09e..00000000000000 --- a/src/test/evo_instantsend_tests.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2022 The Dash Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include - -#include - -#include - -BOOST_FIXTURE_TEST_SUITE(evo_instantsend_tests, BasicTestingSetup) - -BOOST_AUTO_TEST_CASE(instantsend_CInstantSendLock_tests) -{ - - enum { - DET = true, - NON_DET = false - }; - - { - llmq::CInstantSendLock lock; - BOOST_CHECK_EQUAL(lock.IsDeterministic(), NON_DET); - } - - std::vector> version_det_pair = { - {llmq::CInstantSendLock::isdlock_version, DET}, - {llmq::CInstantSendLock::islock_version, NON_DET}, - {2, DET}, - {100, DET}, - {std::numeric_limits::max(), DET}, - }; - - for (const auto& [version, det] : version_det_pair) { - llmq::CInstantSendLock lock(version); - BOOST_CHECK_EQUAL(lock.IsDeterministic(), det); - } -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/functional/feature_llmq_chainlocks.py b/test/functional/feature_llmq_chainlocks.py index 24f30f8069f440..deb9c1dc74e002 100755 --- a/test/functional/feature_llmq_chainlocks.py +++ b/test/functional/feature_llmq_chainlocks.py @@ -18,7 +18,7 @@ class LLMQChainLocksTest(DashTestFramework): def set_test_params(self): - self.set_dash_test_params(4, 3, fast_dip3_enforcement=True) + self.set_dash_test_params(5, 4, fast_dip3_enforcement=True) def run_test(self): @@ -46,9 +46,14 @@ def run_test(self): self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) self.wait_for_sporks_same() - self.log.info("Mining 4 quorums") - for i in range(4): - self.mine_quorum() + self.move_to_next_cycle() + self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) + self.mine_cycle_quorum(llmq_type_name="llmq_test_dip0024", llmq_type=103) + self.log.info("Mine single block, wait for chainlock") self.nodes[0].generate(1) diff --git a/test/functional/feature_llmq_evo.py b/test/functional/feature_llmq_evo.py index 13086fd4cf8332..025dc9f36ba584 100755 --- a/test/functional/feature_llmq_evo.py +++ b/test/functional/feature_llmq_evo.py @@ -64,14 +64,13 @@ def run_test(self): self.activate_dip8() self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) + self.nodes[0].sporkupdate("SPORK_2_INSTANTSEND_ENABLED", 1) self.wait_for_sporks_same() expectedUpdated = [mn.proTxHash for mn in self.mninfo] b_0 = self.nodes[0].getbestblockhash() self.test_getmnlistdiff(null_hash, b_0, {}, [], expectedUpdated) - self.mine_quorum(llmq_type_name='llmq_test', llmq_type=100) - self.log.info("Test that EvoNodes registration is rejected before v19") self.test_evo_is_rejected_before_v19() @@ -80,6 +79,9 @@ def run_test(self): self.activate_v19(expected_activation_height=900) self.log.info("Activated v19 at height:" + str(self.nodes[0].getblockcount())) + self.nodes[0].sporkupdate("SPORK_2_INSTANTSEND_ENABLED", 0) + self.wait_for_sporks_same() + self.move_to_next_cycle() self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) self.move_to_next_cycle() @@ -87,7 +89,7 @@ def run_test(self): self.move_to_next_cycle() self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) - (quorum_info_i_0, quorum_info_i_1) = self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) + self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) evo_protxhash_list = list() for i in range(5): @@ -218,12 +220,10 @@ def test_evo_is_rejected_before_v19(self): collateral_amount = 4000 outputs = {collateral_address: collateral_amount, funds_address: 1} collateral_txid = self.nodes[0].sendmany("", outputs) - self.wait_for_instantlock(collateral_txid, self.nodes[0]) - tip = self.nodes[0].generate(1)[0] + self.nodes[0].generate(8) self.sync_all(self.nodes) - rawtx = self.nodes[0].getrawtransaction(collateral_txid, 1, tip) - assert_equal(rawtx['confirmations'], 1) + rawtx = self.nodes[0].getrawtransaction(collateral_txid, 1) collateral_vout = 0 for txout in rawtx['vout']: if txout['value'] == Decimal(collateral_amount): diff --git a/test/functional/feature_llmq_is_cl_conflicts.py b/test/functional/feature_llmq_is_cl_conflicts.py index a8c42d619f40f5..7d683e4a59e9b0 100755 --- a/test/functional/feature_llmq_is_cl_conflicts.py +++ b/test/functional/feature_llmq_is_cl_conflicts.py @@ -33,11 +33,11 @@ def send_clsig(self, clsig): inv = msg_inv([CInv(29, hash)]) self.send_message(inv) - def send_islock(self, islock, deterministic=False): - hash = uint256_from_str(hash256(islock.serialize())) - self.islocks[hash] = islock + def send_isdlock(self, isdlock): + hash = uint256_from_str(hash256(isdlock.serialize())) + self.islocks[hash] = isdlock - inv = msg_inv([CInv(31 if deterministic else 30, hash)]) + inv = msg_inv([CInv(31, hash)]) self.send_message(inv) def on_getdata(self, message): @@ -62,7 +62,16 @@ def run_test(self): self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) self.wait_for_sporks_same() - self.mine_quorum() + self.activate_v19(expected_activation_height=900) + self.log.info("Activated v19 at height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) + + self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) # mine single block, wait for chainlock self.nodes[0].generate(1) @@ -71,16 +80,16 @@ def run_test(self): self.test_chainlock_overrides_islock(False) self.test_chainlock_overrides_islock(True, False) self.test_chainlock_overrides_islock(True, True) - self.test_chainlock_overrides_islock_overrides_nonchainlock(False) - self.activate_dip0024() - self.log.info("Activated DIP0024 at height:" + str(self.nodes[0].getblockcount())) - self.test_chainlock_overrides_islock_overrides_nonchainlock(False) + self.test_chainlock_overrides_islock_overrides_nonchainlock() + #self.activate_dip0024() + #self.log.info("Activated DIP0024 at height:" + str(self.nodes[0].getblockcount())) + self.test_chainlock_overrides_islock_overrides_nonchainlock() # At this point, we need to move forward 3 cycles (3 x 24 blocks) so the first 3 quarters can be created (without DKG sessions) self.move_to_next_cycle() self.move_to_next_cycle() self.move_to_next_cycle() self.mine_cycle_quorum() - self.test_chainlock_overrides_islock_overrides_nonchainlock(True) + self.test_chainlock_overrides_islock_overrides_nonchainlock() def test_chainlock_overrides_islock(self, test_block_conflict, mine_confllicting=False): if not test_block_conflict: @@ -201,7 +210,7 @@ def test_chainlock_overrides_islock(self, test_block_conflict, mine_confllicting assert rawtx['instantlock'] assert not rawtx['instantlock_internal'] - def test_chainlock_overrides_islock_overrides_nonchainlock(self, deterministic): + def test_chainlock_overrides_islock_overrides_nonchainlock(self): # create two raw TXs, they will conflict with each other rawtx1 = self.create_raw_tx(self.nodes[0], self.nodes[0], 1, 1, 100)['hex'] rawtx2 = self.create_raw_tx(self.nodes[0], self.nodes[0], 1, 1, 100)['hex'] @@ -210,7 +219,7 @@ def test_chainlock_overrides_islock_overrides_nonchainlock(self, deterministic): rawtx2_txid = hash256(hex_str_to_bytes(rawtx2))[::-1].hex() # Create an ISLOCK but don't broadcast it yet - islock = self.create_islock(rawtx2, deterministic) + isdlock = self.create_isdlock(rawtx2) # Ensure spork uniqueness in multiple function runs self.bump_mocktime(1) @@ -242,13 +251,13 @@ def test_chainlock_overrides_islock_overrides_nonchainlock(self, deterministic): # Send the ISLOCK, which should result in the last 2 blocks to be disconnected, # even though the nodes don't know the locked transaction yet - self.test_node.send_islock(islock, deterministic) + self.test_node.send_isdlock(isdlock) for node in self.nodes: wait_until(lambda: node.getbestblockhash() == good_tip, timeout=10, sleep=0.5) # islock for tx2 is incomplete, tx1 should return in mempool now that blocks are disconnected assert rawtx1_txid in set(node.getrawmempool()) - # Should drop tx1 and accept tx2 because there is an islock waiting for it + # Should drop tx1 and accept tx2 because there is an isdlock waiting for it self.nodes[0].sendrawtransaction(rawtx2) # bump mocktime to force tx relay self.bump_mocktime(60) diff --git a/test/functional/feature_llmq_is_migration.py b/test/functional/feature_llmq_is_migration.py deleted file mode 100755 index 1d1f8e1e5a8582..00000000000000 --- a/test/functional/feature_llmq_is_migration.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2020-2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -import time - -from test_framework.messages import CTransaction, FromHex, hash256, ser_compact_size, ser_string -from test_framework.test_framework import DashTestFramework -from test_framework.util import wait_until - -''' -feature_llmq_is_migration.py - -Test IS LLMQ migration with DIP0024 - -''' - -class LLMQISMigrationTest(DashTestFramework): - def set_test_params(self): - # -whitelist is needed to avoid the trickling logic on node0 - self.set_dash_test_params(16, 15, [["-whitelist=127.0.0.1"], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []], fast_dip3_enforcement=True) - self.set_dash_llmq_test_params(4, 4) - - def get_request_id(self, tx_hex): - tx = FromHex(CTransaction(), tx_hex) - - request_id_buf = ser_string(b"islock") + ser_compact_size(len(tx.vin)) - for txin in tx.vin: - request_id_buf += txin.prevout.serialize() - return hash256(request_id_buf)[::-1].hex() - - def run_test(self): - - for i in range(len(self.nodes)): - if i != 1: - self.connect_nodes(i, 0) - - self.activate_dip8() - - node = self.nodes[0] - node.sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) - node.sporkupdate("SPORK_2_INSTANTSEND_ENABLED", 0) - self.wait_for_sporks_same() - - self.mine_quorum() - self.mine_quorum() - - self.log.info(self.nodes[0].quorum("list")) - - txid1 = node.sendtoaddress(node.getnewaddress(), 1) - self.wait_for_instantlock(txid1, node) - - request_id = self.get_request_id(self.nodes[0].getrawtransaction(txid1)) - wait_until(lambda: node.quorum("hasrecsig", 104, request_id, txid1)) - - rec_sig = node.quorum("getrecsig", 104, request_id, txid1)['sig'] - assert node.verifyislock(request_id, txid1, rec_sig) - - self.activate_dip0024() - self.log.info("Activated DIP0024 at height:" + str(self.nodes[0].getblockcount())) - - q_list = self.nodes[0].quorum("list") - self.log.info(q_list) - assert len(q_list['llmq_test']) == 2 - assert len(q_list['llmq_test_instantsend']) == 2 - assert len(q_list['llmq_test_v17']) == 0 - assert len(q_list['llmq_test_dip0024']) == 0 - - txid1 = node.sendtoaddress(node.getnewaddress(), 1) - self.wait_for_instantlock(txid1, node) - - - # at this point, DIP0024 is active, but we have old quorums, and they should still create islocks! - - txid3 = node.sendtoaddress(node.getnewaddress(), 1) - self.wait_for_instantlock(txid3, node) - - request_id = self.get_request_id(self.nodes[0].getrawtransaction(txid3)) - wait_until(lambda: node.quorum("hasrecsig", 104, request_id, txid3)) - - rec_sig = node.quorum("getrecsig", 104, request_id, txid3)['sig'] - assert node.verifyislock(request_id, txid3, rec_sig) - - - #At this point, we need to move forward 3 cycles (3 x 24 blocks) so the first 3 quarters can be created (without DKG sessions) - #self.log.info("Start at H height:" + str(self.nodes[0].getblockcount())) - self.move_to_next_cycle() - self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) - self.move_to_next_cycle() - self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) - self.move_to_next_cycle() - self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) - - (quorum_info_0_0, quorum_info_0_1) = self.mine_cycle_quorum() - - q_list = self.nodes[0].quorum("list") - self.log.info(q_list) - assert len(q_list['llmq_test']) == 2 - assert 'llmq_test_instantsend' not in q_list - assert len(q_list['llmq_test_v17']) == 1 - assert len(q_list['llmq_test_dip0024']) == 2 - - # Check that the earliest islock is still present - self.wait_for_instantlock(txid1, node) - - txid2 = node.sendtoaddress(node.getnewaddress(), 1) - self.wait_for_instantlock(txid2, node) - - request_id2 = self.get_request_id(self.nodes[0].getrawtransaction(txid2)) - wait_until(lambda: node.quorum("hasrecsig", 103, request_id2, txid2)) - - rec_sig2 = node.quorum("getrecsig", 103, request_id2, txid2)['sig'] - assert node.verifyislock(request_id2, txid2, rec_sig2) - - # Check that original islock quorum type doesn't sign - time.sleep(10) - for n in self.nodes: - assert not n.quorum("hasrecsig", 104, request_id2, txid2) - - -if __name__ == '__main__': - LLMQISMigrationTest().main() diff --git a/test/functional/feature_llmq_is_retroactive.py b/test/functional/feature_llmq_is_retroactive.py index 9f82b1883d966e..132a4da1fe1b4f 100755 --- a/test/functional/feature_llmq_is_retroactive.py +++ b/test/functional/feature_llmq_is_retroactive.py @@ -23,7 +23,7 @@ class LLMQ_IS_RetroactiveSigning(DashTestFramework): def set_test_params(self): # -whitelist is needed to avoid the trickling logic on node0 self.set_dash_test_params(6, 5, [["-whitelist=127.0.0.1"], [], [], [], ["-minrelaytxfee=0.001"], ["-minrelaytxfee=0.001"]], fast_dip3_enforcement=True) - self.set_dash_llmq_test_params(5, 3) + #self.set_dash_llmq_test_params(5, 3) def run_test(self): self.activate_dip8() @@ -33,8 +33,16 @@ def run_test(self): self.nodes[0].sporkupdate("SPORK_2_INSTANTSEND_ENABLED", 1) self.wait_for_sporks_same() - self.mine_quorum() - self.mine_quorum() + self.activate_v19(expected_activation_height=900) + self.log.info("Activated v19 at height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) + + self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) # Make sure that all nodes are chainlocked at the same height before starting actual tests self.wait_for_chainlocked_block_all_nodes(self.nodes[0].getbestblockhash(), timeout=30) @@ -75,10 +83,10 @@ def run_test(self): # otherwise it might announce the TX to node 3 when reconnecting self.wait_for_tx(txid, self.nodes[1]) self.wait_for_tx(txid, self.nodes[2]) - self.reconnect_isolated_node(3, 0) + self.reconnect_isolated_node(2, 0) # Make sure nodes actually try re-connecting quorum connections self.bump_mocktime(30) - self.wait_for_mnauth(self.nodes[3], 2) + self.wait_for_mnauth(self.nodes[3], 3) # node 3 fully reconnected but the TX wasn't relayed to it, so there should be no IS lock self.wait_for_instantlock(txid, self.nodes[0], False, 5) # push the tx directly via rpc diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py index 34df46f6c818da..7b840d65c463c5 100755 --- a/test/functional/feature_notifications.py +++ b/test/functional/feature_notifications.py @@ -27,7 +27,7 @@ def notify_outputname(walletname, txid): class NotificationsTest(DashTestFramework): def set_test_params(self): - self.set_dash_test_params(5, 3, fast_dip3_enforcement=True) + self.set_dash_test_params(6, 4, fast_dip3_enforcement=True) def setup_network(self): self.wallet = ''.join(chr(i) for i in range(FILE_CHAR_START, FILE_CHAR_END) if chr(i) not in FILE_CHARS_DISALLOWED) @@ -102,11 +102,21 @@ def run_test(self): self.log.info("test -chainlocknotify") + self.activate_v19(expected_activation_height=900) + self.log.info("Activated v19 at height:" + str(self.nodes[0].getblockcount())) + self.activate_dip8() self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) self.nodes[0].sporkupdate("SPORK_19_CHAINLOCKS_ENABLED", 4070908800) self.wait_for_sporks_same() - self.mine_quorum() + self.move_to_next_cycle() + self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) + + (quorum_info_i_0, quorum_info_i_1) = self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) self.nodes[0].sporkupdate("SPORK_19_CHAINLOCKS_ENABLED", 0) self.wait_for_sporks_same() diff --git a/test/functional/interface_zmq_dash.py b/test/functional/interface_zmq_dash.py index aca7323bc259b6..a1d27b1af452fd 100755 --- a/test/functional/interface_zmq_dash.py +++ b/test/functional/interface_zmq_dash.py @@ -28,7 +28,6 @@ msg_clsig, msg_inv, msg_isdlock, - msg_islock, msg_tx, MSG_TX, MSG_TYPE_MASK, @@ -76,11 +75,11 @@ def __init__(self): self.islocks = {} self.txes = {} - def send_islock(self, islock, deterministic): + def send_islock(self, islock): hash = uint256_from_str(hash256(islock.serialize())) self.islocks[hash] = islock - inv = msg_inv([CInv(31 if deterministic else 30, hash)]) + inv = msg_inv([CInv(31, hash)]) self.send_message(inv) def send_tx(self, tx): @@ -131,35 +130,39 @@ def run_test(self): self.activate_dip8() self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) self.wait_for_sporks_same() - # Create an LLMQ for testing - self.quorum_type = 100 # llmq_test - self.quorum_hash = self.mine_quorum() + self.activate_v19(expected_activation_height=900) + self.log.info("Activated v19 at height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) + + self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) + self.sync_blocks() self.wait_for_chainlocked_block_all_nodes(self.nodes[0].getbestblockhash()) # Wait a moment to avoid subscribing to recovered sig in the test before the one from the chainlock # has been sent which leads to test failure. time.sleep(1) # Test all dash related ZMQ publisher - self.test_recovered_signature_publishers() + #self.test_recovered_signature_publishers() self.test_chainlock_publishers() self.test_governance_publishers() self.test_getzmqnotifications() - self.test_instantsend_publishers(False) - self.activate_dip0024() - self.log.info("Activated DIP0024 at height:" + str(self.nodes[0].getblockcount())) - # Test for CL 8 blocks after dip24 activation because along with dip24, the BLS scheme is activted - self.generate_blocks(8) + self.test_instantsend_publishers() self.wait_for_chainlocked_block_all_nodes(self.nodes[0].getbestblockhash()) - self.test_instantsend_publishers(False) + self.test_instantsend_publishers() # At this point, we need to move forward 3 cycles (3 x 24 blocks) so the first 3 quarters can be created (without DKG sessions) self.move_to_next_cycle() - self.test_instantsend_publishers(False) + self.test_instantsend_publishers() self.move_to_next_cycle() - self.test_instantsend_publishers(False) + self.test_instantsend_publishers() self.move_to_next_cycle() - self.test_instantsend_publishers(False) + self.test_instantsend_publishers() self.mine_cycle_quorum() - self.test_instantsend_publishers(True) + self.test_instantsend_publishers() finally: # Destroy the ZMQ context. self.log.debug("Destroying ZMQ context") @@ -191,7 +194,7 @@ def test_recovered_signature_publishers(self): def validate_recovered_sig(request_id, msg_hash): # Make sure the recovered sig exists by RPC self.wait_for_recovered_sig(request_id, msg_hash) - rpc_recovered_sig = self.mninfo[0].node.quorum('getrecsig', 100, request_id, msg_hash) + rpc_recovered_sig = self.mninfo[0].node.quorum('getrecsig', 103, request_id, msg_hash) # Validate hashrecoveredsig zmq_recovered_sig_hash = self.subscribers[ZMQPublisher.hash_recovered_sig].receive().read(32).hex() assert_equal(zmq_recovered_sig_hash, msg_hash) @@ -268,7 +271,7 @@ def test_chainlock_publishers(self): # Unsubscribe from ChainLock messages self.unsubscribe(chain_lock_publishers) - def test_instantsend_publishers(self, deterministic): + def test_instantsend_publishers(self): import zmq instantsend_publishers = [ ZMQPublisher.hash_tx_lock, @@ -304,7 +307,7 @@ def test_instantsend_publishers(self, deterministic): zmq_tx_lock_tx.deserialize(zmq_tx_lock_sig_stream) assert zmq_tx_lock_tx.is_valid() assert_equal(zmq_tx_lock_tx.hash, rpc_raw_tx_1['txid']) - zmq_tx_lock = msg_isdlock() if deterministic else msg_islock() + zmq_tx_lock = msg_isdlock() zmq_tx_lock.deserialize(zmq_tx_lock_sig_stream) assert_equal(uint256_to_string(zmq_tx_lock.txid), rpc_raw_tx_1['txid']) # Try to send the second transaction. This must throw an RPC error because it conflicts with rpc_raw_tx_1 @@ -327,8 +330,8 @@ def test_instantsend_publishers(self, deterministic): # No islock notifications when tx is not received yet self.nodes[0].generate(1) rpc_raw_tx_3 = self.create_raw_tx(self.nodes[0], self.nodes[0], 1, 1, 100) - islock = self.create_islock(rpc_raw_tx_3['hex'], deterministic) - self.test_node.send_islock(islock, deterministic) + isdlock = self.create_isdlock(rpc_raw_tx_3['hex']) + self.test_node.send_islock(isdlock) # Validate NO hashtxlock time.sleep(1) try: diff --git a/test/functional/p2p_instantsend.py b/test/functional/p2p_instantsend.py index ef255f9bd6eaab..6894d22654bef7 100755 --- a/test/functional/p2p_instantsend.py +++ b/test/functional/p2p_instantsend.py @@ -14,7 +14,7 @@ class InstantSendTest(DashTestFramework): def set_test_params(self): - self.set_dash_test_params(7, 3, fast_dip3_enforcement=True) + self.set_dash_test_params(8, 4, fast_dip3_enforcement=True) # set sender, receiver, isolated nodes self.isolated_idx = 1 self.receiver_idx = 2 @@ -23,7 +23,15 @@ def set_test_params(self): def run_test(self): self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) self.wait_for_sporks_same() - self.mine_quorum() + self.activate_v19(expected_activation_height=900) + self.log.info("Activated v19 at height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) + (quorum_info_i_0, quorum_info_i_1) = self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) self.nodes[self.isolated_idx].createwallet(self.default_wallet_name) self.nodes[self.receiver_idx].createwallet(self.default_wallet_name) self.nodes[self.sender_idx].createwallet(self.default_wallet_name) diff --git a/test/functional/rpc_verifyislock.py b/test/functional/rpc_verifyislock.py index a21f90e20eb485..56bb101a75fedf 100755 --- a/test/functional/rpc_verifyislock.py +++ b/test/functional/rpc_verifyislock.py @@ -18,7 +18,6 @@ class RPCVerifyISLockTest(DashTestFramework): def set_test_params(self): # -whitelist is needed to avoid the trickling logic on node0 self.set_dash_test_params(6, 5, [["-whitelist=127.0.0.1"], [], [], [], [], []], fast_dip3_enforcement=True) - self.set_dash_llmq_test_params(5, 3) def get_request_id(self, tx_hex): tx = FromHex(CTransaction(), tx_hex) @@ -34,15 +33,27 @@ def run_test(self): node.sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) self.wait_for_sporks_same() - self.mine_quorum() + self.activate_v19(expected_activation_height=900) + self.log.info("Activated v19 at height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) + + self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) + self.bump_mocktime(1) + self.nodes[0].generate(8) + self.sync_blocks() txid = node.sendtoaddress(node.getnewaddress(), 1) self.wait_for_instantlock(txid, node) request_id = self.get_request_id(self.nodes[0].getrawtransaction(txid)) - wait_until(lambda: node.quorum("hasrecsig", 104, request_id, txid)) + wait_until(lambda: node.quorum("hasrecsig", 103, request_id, txid)) - rec_sig = node.quorum("getrecsig", 104, request_id, txid)['sig'] + rec_sig = node.quorum("getrecsig", 103, request_id, txid)['sig'] assert node.verifyislock(request_id, txid, rec_sig) # Not mined, should use maxHeight assert not node.verifyislock(request_id, txid, rec_sig, 1) @@ -53,18 +64,14 @@ def run_test(self): # Mined, should ignore higher maxHeight assert node.verifyislock(request_id, txid, rec_sig, node.getblockcount() + 100) - # Mine one more quorum to have a full active set - self.mine_quorum() - # Create an ISLOCK for the oldest quorum i.e. the active quorum which will be moved - # out of the active set when a new quorum appears - selected_hash = None + # Mine one more cycle of rotated quorums + self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) + # Create an ISLOCK using an active quorum which will be replaced when a new cycle happens request_id = None - oldest_quorum_hash = node.quorum("list")["llmq_test_instantsend"][-1] utxos = node.listunspent() fee = 0.001 amount = 1 - # Try all available utxo's until we have one resulting in a request id which selects the - # last active quorum + # Try all available utxo's until we have one valid in_amount for utxo in utxos: in_amount = float(utxo['amount']) if in_amount < amount + fee: @@ -77,21 +84,18 @@ def run_test(self): rawtx = node.createrawtransaction([utxo], outputs) rawtx = node.signrawtransactionwithwallet(rawtx)["hex"] request_id = self.get_request_id(rawtx) - selected_hash = node.quorum('selectquorum', 104, request_id)["quorumHash"] - if selected_hash == oldest_quorum_hash: - break - assert selected_hash == oldest_quorum_hash - # Create the ISLOCK, then mine a quorum to move the signing quorum out of the active set - islock = self.create_islock(rawtx, False) - # Mine one block to trigger the "signHeight + dkgInterval" verification for the ISLOCK - self.mine_quorum() + break + # Create the ISDLOCK, then mine a cycle quorum to move renew active set + isdlock = self.create_isdlock(rawtx) + # Mine one block to trigger the "signHeight + dkgInterval" verification for the ISDLOCK + self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) # Verify the ISLOCK for a transaction that is not yet known by the node rawtx_txid = node.decoderawtransaction(rawtx)["txid"] assert_raises_rpc_error(-5, "No such mempool or blockchain transaction", node.getrawtransaction, rawtx_txid) - assert node.verifyislock(request_id, rawtx_txid, islock.sig.hex(), node.getblockcount()) - # Send the tx and verify the ISLOCK for a now known transaction + assert node.verifyislock(request_id, rawtx_txid, isdlock.sig.hex(), node.getblockcount()) + # Send the tx and verify the ISDLOCK for a now known transaction assert rawtx_txid == node.sendrawtransaction(rawtx) - assert node.verifyislock(request_id, rawtx_txid, islock.sig.hex(), node.getblockcount()) + assert node.verifyislock(request_id, rawtx_txid, isdlock.sig.hex(), node.getblockcount()) if __name__ == '__main__': diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 26793d119d65d6..1458e025af7037 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -2224,31 +2224,6 @@ def __repr__(self): return "msg_clsig(height=%d, blockHash=%064x)" % (self.height, self.blockHash) -class msg_islock: - __slots__ = ("inputs", "txid", "sig",) - command = b"islock" - - def __init__(self, inputs=None, txid=0, sig=b'\x00' * 96): - self.inputs = inputs if inputs is not None else [] - self.txid = txid - self.sig = sig - - def deserialize(self, f): - self.inputs = deser_vector(f, COutPoint) - self.txid = deser_uint256(f) - self.sig = f.read(96) - - def serialize(self): - r = b"" - r += ser_vector(self.inputs) - r += ser_uint256(self.txid) - r += self.sig - return r - - def __repr__(self): - return "msg_islock(inputs=%s, txid=%064x)" % (repr(self.inputs), self.txid) - - class msg_isdlock: __slots__ = ("nVersion", "inputs", "txid", "cycleHash", "sig") command = b"isdlock" diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index 77419279034dda..1f5a1abfcfadef 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -51,7 +51,6 @@ msg_headers, msg_headers2, msg_inv, - msg_islock, msg_isdlock, msg_mempool, msg_mnlistdiff, @@ -116,7 +115,6 @@ b"getmnlistd": msg_getmnlistd, b"getsporks": None, b"govsync": None, - b"islock": msg_islock, b"isdlock": msg_isdlock, b"mnlistdiff": msg_mnlistdiff, b"notfound": msg_notfound, diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 7ab5e47a0c64c0..28e6e35b34d7d6 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -29,7 +29,6 @@ CTransaction, FromHex, hash256, - msg_islock, msg_isdlock, ser_compact_size, ser_string, @@ -1512,7 +1511,7 @@ def check_tx(): if wait_until(check_tx, timeout=timeout, sleep=1, do_assert=expected) and not expected: raise AssertionError("waiting unexpectedly succeeded") - def create_islock(self, hextx, deterministic=False): + def create_isdlock(self, hextx): tx = FromHex(CTransaction(), hextx) tx.rehash() @@ -1524,18 +1523,15 @@ def create_islock(self, hextx, deterministic=False): request_id = hash256(request_id_buf)[::-1].hex() message_hash = tx.hash - llmq_type = 103 if deterministic else 104 + llmq_type = 103 rec_sig = self.get_recovered_sig(request_id, message_hash, llmq_type=llmq_type) - if deterministic: - block_count = self.mninfo[0].node.getblockcount() - cycle_hash = int(self.mninfo[0].node.getblockhash(block_count - (block_count % 24)), 16) - islock = msg_isdlock(1, inputs, tx.sha256, cycle_hash, hex_str_to_bytes(rec_sig['sig'])) - else: - islock = msg_islock(inputs, tx.sha256, hex_str_to_bytes(rec_sig['sig'])) + block_count = self.mninfo[0].node.getblockcount() + cycle_hash = int(self.mninfo[0].node.getblockhash(block_count - (block_count % 24)), 16) + isdlock = msg_isdlock(1, inputs, tx.sha256, cycle_hash, hex_str_to_bytes(rec_sig['sig'])) - return islock + return isdlock def wait_for_instantlock(self, txid, node, expected=True, timeout=60): def check_instantlock(): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index f7cfb49287fe87..9046e54cfc2840 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -116,7 +116,6 @@ 'feature_llmq_evo.py', # NOTE: needs dash_hash to pass 'feature_llmq_simplepose.py', # NOTE: needs dash_hash to pass 'feature_llmq_is_cl_conflicts.py', # NOTE: needs dash_hash to pass - 'feature_llmq_is_migration.py', # NOTE: needs dash_hash to pass 'feature_llmq_is_retroactive.py', # NOTE: needs dash_hash to pass 'feature_llmq_dkgerrors.py', # NOTE: needs dash_hash to pass 'feature_dip4_coinbasemerkleroots.py', # NOTE: needs dash_hash to pass