diff --git a/doc/release-notes.md b/doc/release-notes.md index ae9eaf1d91..1444ec5ed9 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -223,6 +223,12 @@ modules were reorganized in separate folders to make navigation through code a b See detailed [set of changes](https://github.com/dashpay/dash/compare/v0.14.0.5...dashpay:v0.15.0.0). +- [`546e69f1a`](https://github.com/dashpay/dash/commit/546e69f1a) Fix CActiveMasternodeManager::GetLocalAddress to prefer IPv4 if multiple local addresses are known (#3304) +- [`e4ef7e8d0`](https://github.com/dashpay/dash/commit/e4ef7e8d0) Drop unused `invSet` in `CDKGSession` (#3303) +- [`da7686c93`](https://github.com/dashpay/dash/commit/da7686c93) Update translations 2020-01-23 (#3302) +- [`6b5d3edae`](https://github.com/dashpay/dash/commit/6b5d3edae) Fix dip4-coinbasemerkleroots.py race condition (#3297) +- [`a8213cadb`](https://github.com/dashpay/dash/commit/a8213cadb) Various fixes for DSTX-es (#3295) +- [`2c26bdf2d`](https://github.com/dashpay/dash/commit/2c26bdf2d) Update release-notes.md - [`1d9adbe63`](https://github.com/dashpay/dash/commit/1d9adbe63) Replace generic CScopedDBTransaction with specialized CEvoDBScopedCommitter (#3292) - [`8fd486c6b`](https://github.com/dashpay/dash/commit/8fd486c6b) Translations 2020-01 (#3192) - [`3c54f6527`](https://github.com/dashpay/dash/commit/3c54f6527) Bump copyright year to 2020 (#3290) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 919c4ca4d4..2fa6e77b5a 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -107,4 +107,5 @@ void CDSNotificationInterface::NotifyMasternodeListChanged(bool undo, const CDet void CDSNotificationInterface::NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) { llmq::quorumInstantSendManager->NotifyChainLock(pindex); + CPrivateSend::NotifyChainLock(pindex); } diff --git a/src/llmq/quorums_dkgsession.cpp b/src/llmq/quorums_dkgsession.cpp index 29ba3ff6ee..b31a3bc0b6 100644 --- a/src/llmq/quorums_dkgsession.cpp +++ b/src/llmq/quorums_dkgsession.cpp @@ -280,7 +280,6 @@ void CDKGSession::ReceiveMessage(const uint256& hash, const CDKGContribution& qc member->contributions.emplace(hash); CInv inv(MSG_QUORUM_CONTRIB, hash); - invSet.emplace(inv); RelayInvToParticipants(inv); quorumDKGDebugManager->UpdateLocalMemberStatus(params.type, member->idx, [&](CDKGDebugMemberStatus& status) { @@ -547,7 +546,6 @@ void CDKGSession::ReceiveMessage(const uint256& hash, const CDKGComplaint& qc, b member->complaints.emplace(hash); CInv inv(MSG_QUORUM_COMPLAINT, hash); - invSet.emplace(inv); RelayInvToParticipants(inv); quorumDKGDebugManager->UpdateLocalMemberStatus(params.type, member->idx, [&](CDKGDebugMemberStatus& status) { @@ -762,7 +760,6 @@ void CDKGSession::ReceiveMessage(const uint256& hash, const CDKGJustification& q // we always relay, even if further verification fails CInv inv(MSG_QUORUM_JUSTIFICATION, hash); - invSet.emplace(inv); RelayInvToParticipants(inv); quorumDKGDebugManager->UpdateLocalMemberStatus(params.type, member->idx, [&](CDKGDebugMemberStatus& status) { @@ -1130,7 +1127,6 @@ void CDKGSession::ReceiveMessage(const uint256& hash, const CDKGPrematureCommitm validCommitments.emplace(hash); CInv inv(MSG_QUORUM_PREMATURE_COMMITMENT, hash); - invSet.emplace(inv); RelayInvToParticipants(inv); quorumDKGDebugManager->UpdateLocalMemberStatus(params.type, member->idx, [&](CDKGDebugMemberStatus& status) { diff --git a/src/llmq/quorums_dkgsession.h b/src/llmq/quorums_dkgsession.h index e13267fe58..9825182e8d 100644 --- a/src/llmq/quorums_dkgsession.h +++ b/src/llmq/quorums_dkgsession.h @@ -274,7 +274,6 @@ private: std::map complaints; std::map justifications; std::map prematureCommitments; - std::set invSet; std::vector pendingContributionVerifications; diff --git a/src/masternode/activemasternode.cpp b/src/masternode/activemasternode.cpp index a8d6e68f64..a3f0390816 100644 --- a/src/masternode/activemasternode.cpp +++ b/src/masternode/activemasternode.cpp @@ -177,8 +177,15 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con bool CActiveMasternodeManager::GetLocalAddress(CService& addrRet) { - // First try to find whatever local address is specified by externalip option - bool fFoundLocal = GetLocal(addrRet) && IsValidNetAddr(addrRet); + // First try to find whatever our own local address is known internally. + // Addresses could be specified via externalip or bind option, discovered via UPnP + // or added by TorController. Use some random dummy IPv4 peer to prefer the one + // reachable via IPv4. + CNetAddr addrDummyPeer; + bool fFoundLocal{false}; + if (LookupHost("8.8.8.8", addrDummyPeer, false)) { + fFoundLocal = GetLocal(addrRet, &addrDummyPeer) && IsValidNetAddr(addrRet); + } if (!fFoundLocal && Params().NetworkIDString() == CBaseChainParams::REGTEST) { if (Lookup("127.0.0.1", addrRet, GetListenPort(), false)) { fFoundLocal = true; diff --git a/src/net.h b/src/net.h index f4d6879034..e6177cea5a 100644 --- a/src/net.h +++ b/src/net.h @@ -999,7 +999,7 @@ public: void PushInventory(const CInv& inv) { LOCK(cs_inventory); - if (inv.type == MSG_TX) { + if (inv.type == MSG_TX || inv.type == MSG_DSTX) { if (!filterInventoryKnown.contains(inv.hash)) { LogPrint(BCLog::NET, "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id); setInventoryTxToSend.insert(inv.hash); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 9f01e5e13e..dfc9fd8b23 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1011,6 +1011,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) switch (inv.type) { case MSG_TX: + case MSG_DSTX: case MSG_LEGACY_TXLOCK_REQUEST: // we treat legacy IX messages as TX messages { assert(recentRejects); @@ -1034,7 +1035,17 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) // and re-request the locked transaction (which did not make it into the mempool // previously due to txn-mempool-conflict rule). This means that we must ignore // recentRejects filter for such locked txes here. - return (recentRejects->contains(inv.hash) && !llmq::quorumInstantSendManager->IsLocked(inv.hash)) || + // We also ignore recentRejects filter for DSTX-es because a malicious peer might + // relay a valid DSTX as a regular TX first which would skip all the specific checks + // but would cause such tx to be rejected by ATMP due to 0 fee. Ignoring it here + // should let DSTX to be propagated by honest peer later. Note, that a malicious + // masternode would not be able to exploit this to spam the network with specially + // crafted invalid DSTX-es and potentially cause high load cheaply, because + // corresponding checks in ProcessMessage won't let it to send DSTX-es too often. + bool fIgnoreRecentRejects = llmq::quorumInstantSendManager->IsLocked(inv.hash) || inv.type == MSG_DSTX; + + return (!fIgnoreRecentRejects && recentRejects->contains(inv.hash)) || + (inv.type == MSG_DSTX && static_cast(CPrivateSend::GetDSTX(inv.hash))) || mempool.exists(inv.hash) || pcoinsTip->HaveCoinInCache(COutPoint(inv.hash, 0)) || // Best effort: only try output 0 and 1 pcoinsTip->HaveCoinInCache(COutPoint(inv.hash, 1)) || @@ -1060,10 +1071,6 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) return sporkManager.GetSporkByHash(inv.hash, spork); } - case MSG_DSTX: { - return static_cast(CPrivateSend::GetDSTX(inv.hash)); - } - case MSG_GOVERNANCE_OBJECT: case MSG_GOVERNANCE_OBJECT_VOTE: return ! governance.ConfirmInventoryRequest(inv); @@ -1274,17 +1281,29 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // Send stream from relay memory bool push = false; - if (inv.type == MSG_TX) { + if (inv.type == MSG_TX || inv.type == MSG_DSTX) { + CPrivateSendBroadcastTx dstx; + if (inv.type == MSG_DSTX) { + dstx = CPrivateSend::GetDSTX(inv.hash); + } auto mi = mapRelay.find(inv.hash); if (mi != mapRelay.end()) { - connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *mi->second)); + if (dstx) { + connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::DSTX, dstx)); + } else { + connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *mi->second)); + } push = true; } else if (pfrom->timeLastMempoolReq) { auto txinfo = mempool.info(inv.hash); // To protect privacy, do not answer getdata using the mempool when // that TX couldn't have been INVed in reply to a MEMPOOL request. if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) { - connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *txinfo.tx)); + if (dstx) { + connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::DSTX, dstx)); + } else { + connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *txinfo.tx)); + } push = true; } } @@ -1298,14 +1317,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!push && inv.type == MSG_DSTX) { - CPrivateSendBroadcastTx dstx = CPrivateSend::GetDSTX(inv.hash); - if(dstx) { - connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::DSTX, dstx)); - push = true; - } - } - if (!push && inv.type == MSG_GOVERNANCE_OBJECT) { LogPrint(BCLog::NET, "ProcessGetData -- MSG_GOVERNANCE_OBJECT: inv = %s\n", inv.ToString()); CDataStream ss(SER_NETWORK, pfrom->GetSendVersion()); @@ -2452,7 +2463,19 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return true; // not an error } - auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(dstx.masternodeOutpoint); + const CBlockIndex* pindex{nullptr}; + CDeterministicMNCPtr dmn{nullptr}; + { + LOCK(cs_main); + pindex = chainActive.Tip(); + } + // It could be that a MN is no longer in the list but its DSTX is not yet mined. + // Try to find a MN up to 24 blocks deep to make sure such dstx-es are relayed and processed correctly. + for (int i = 0; i < 24 && pindex; ++i) { + dmn = deterministicMNManager->GetListForBlock(pindex).GetMNByCollateral(dstx.masternodeOutpoint); + if (dmn) break; + pindex = pindex->pprev; + } if(!dmn) { LogPrint(BCLog::PRIVATESEND, "DSTX -- Can't find masternode %s to verify %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString()); return false; @@ -2523,6 +2546,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr CInv _inv(MSG_TX, txin.prevout.hash); pfrom->AddInventoryKnown(_inv); if (!AlreadyHave(_inv)) pfrom->AskFor(_inv); + // We don't know if the previous tx was a regular or a mixing one, try both + CInv _inv2(MSG_DSTX, txin.prevout.hash); + pfrom->AddInventoryKnown(_inv2); + if (!AlreadyHave(_inv2)) pfrom->AskFor(_inv2); } AddOrphanTx(ptx, pfrom->GetId()); @@ -3785,7 +3812,11 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic& interruptM for (const auto& txinfo : vtxinfo) { const uint256& hash = txinfo.tx->GetHash(); - CInv inv(MSG_TX, hash); + int nInvType = MSG_TX; + if (CPrivateSend::GetDSTX(hash)) { + nInvType = MSG_DSTX; + } + CInv inv(nInvType, hash); pto->setInventoryTxToSend.erase(hash); if (pto->pfilter) { if (!pto->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue; @@ -3851,7 +3882,11 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic& interruptM } if (pto->pfilter && !pto->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue; // Send - vInv.push_back(CInv(MSG_TX, hash)); + int nInvType = MSG_TX; + if (CPrivateSend::GetDSTX(hash)) { + nInvType = MSG_DSTX; + } + vInv.push_back(CInv(nInvType, hash)); nRelayedTransactions++; { // Expire old relay messages diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 1225efe322..71d09aae37 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -603,6 +603,13 @@ void CPrivateSend::UpdatedBlockTip(const CBlockIndex* pindex) } } +void CPrivateSend::NotifyChainLock(const CBlockIndex* pindex) +{ + if (pindex && masternodeSync.IsBlockchainSynced()) { + CheckDSTXes(pindex); + } +} + void CPrivateSend::UpdateDSTXConfirmedHeight(const CTransactionRef& tx, int nHeight) { AssertLockHeld(cs_mapdstx); diff --git a/src/privatesend/privatesend.h b/src/privatesend/privatesend.h index 3f7687964d..8abd4e13ed 100644 --- a/src/privatesend/privatesend.h +++ b/src/privatesend/privatesend.h @@ -465,6 +465,7 @@ public: static CPrivateSendBroadcastTx GetDSTX(const uint256& hash); static void UpdatedBlockTip(const CBlockIndex* pindex); + static void NotifyChainLock(const CBlockIndex* pindex); static void UpdateDSTXConfirmedHeight(const CTransactionRef& tx, int nHeight); static void TransactionAddedToMempool(const CTransactionRef& tx); diff --git a/src/qt/locale/dash_es.ts b/src/qt/locale/dash_es.ts index 563f8e3a59..8192086594 100644 --- a/src/qt/locale/dash_es.ts +++ b/src/qt/locale/dash_es.ts @@ -1326,6 +1326,10 @@ This amount acts as a threshold to turn off PrivateSend once it's reached. Esta cantidad actúa como un límite para desactivar PrivateSend una vez que se alcanza ese límite. + + Target PrivateSend balance + Saldo objetivo de PrivateSend + Automatically open the Dash Core client port on the router. This only works when your router supports UPnP and it is enabled. Abrir automáticamente el puerto del cliente Dash Core en el enrutador. Esto solo funciona cuando su enrutador admite UPnP y está habilitado. @@ -1715,6 +1719,10 @@ https://www.transifex.com/projects/p/dash/ Denominated Denominadas + + Partially mixed + Parcialmente mezclado + Mixed Mezcladas @@ -2801,6 +2809,10 @@ https://www.transifex.com/projects/p/dash/ <b>(%1 of %2 entries displayed)</b> <b>(%1 de %2 registros mostrados)</b> + + PrivateSend funds only + Fondos de PrivateSend solamente + any available funds cualquier fondo disponible @@ -2817,6 +2829,10 @@ https://www.transifex.com/projects/p/dash/ Fee rate: %1 Tasa de comisión: %1 + + This transaction will consume %n input(s) + Esta transacción consumirá %n entradaEsta transacción consumirá %n entradas + Warning: Using PrivateSend with %1 or more inputs can harm your privacy and is not recommended Advertencia: el uso de PrivateSend con %1 o más entradas puede dañar tu privacidad y no se recomienda diff --git a/src/qt/locale/dash_ko.ts b/src/qt/locale/dash_ko.ts index 28389463f3..ea772c3bad 100644 --- a/src/qt/locale/dash_ko.ts +++ b/src/qt/locale/dash_ko.ts @@ -1326,6 +1326,10 @@ This amount acts as a threshold to turn off PrivateSend once it's reached. 이 금액에 도달하는 경우 프라이빗샌드를 끄기 위한 한계점으로 작동합니다. + + Target PrivateSend balance + 타깃 프라이빗샌드 잔고 + Automatically open the Dash Core client port on the router. This only works when your router supports UPnP and it is enabled. 라우터에서 대시 코어 클라이언트를 자동으로 엽니다. 이 기능은 당신의 라우터가 UPnP를 지원하고 해당 기능이 작동하는 경우에만 가능합니다. @@ -1715,6 +1719,10 @@ https://www.transifex.com/projects/p/dash/ Denominated 단위 분할 완료 + + Partially mixed + 부분적으로 믹싱됨 + Mixed 믹싱 완료 @@ -2801,6 +2809,14 @@ https://www.transifex.com/projects/p/dash/ <b>(%1 of %2 entries displayed)</b> <b>(%2 중 %1 입력값 표시됨)</b> + + PrivateSend funds only + 프라이빗샌드 자금만 + + + any available funds + 이용이 가능한 모든 자금 + (PrivateSend transactions have higher fees usually due to no change output being allowed) (프라이빗샌드 거래는 잔돈 아웃풋이 허용되지 않아 보다 높은 수수료가 책정됩니다) @@ -2813,6 +2829,10 @@ https://www.transifex.com/projects/p/dash/ Fee rate: %1 수수료 요율: %1 + + This transaction will consume %n input(s) + 이 거래는 %n 입력값을 소모합니다 + Warning: Using PrivateSend with %1 or more inputs can harm your privacy and is not recommended 경고: %1 혹은 그 이상의 인풋으로 프라이빗샌드를 이용하게 되면 당신의 프라이버시가 침해될 수 있어 권장하지 않습니다. @@ -5040,7 +5060,7 @@ https://www.transifex.com/projects/p/dash/ Inputs vs outputs size mismatch. - 인풋 vs 아웃풋 사이즈가 일치하지 않습니다. + 입력값 vs 출력값 사이즈가 일치하지 않습니다. Invalid -onion address or hostname: '%s' diff --git a/src/qt/locale/dash_ro.ts b/src/qt/locale/dash_ro.ts index 34c068c74a..ca187a059b 100644 --- a/src/qt/locale/dash_ro.ts +++ b/src/qt/locale/dash_ro.ts @@ -4350,6 +4350,10 @@ https://www.transifex.com/projects/p/dash/ Warning: Unknown block versions being mined! It's possible unknown rules are in effect Atentie: se mineaza blocuri cu versiune necunoscuta! Este posibil sa fie in vigoare reguli necunoscute. + + You need to rebuild the database using -reindex to change -timestampindex + Trebuie să reconstruiești baza de date utilizând -reindex pentru a schimba -timestampindex + You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain Trebuie reconstruita intreaga baza de date folosind -reindex pentru a va intoarce la modul non-redus. Aceasta va determina descarcarea din nou a intregului blockchain @@ -4662,6 +4666,14 @@ https://www.transifex.com/projects/p/dash/ You can not start a masternode with wallet enabled. Nu poți porni un masternode cu portofelul activat. + + You need to rebuild the database using -reindex to change -addressindex + Trebuie să reconstruiești baza de date utilizând -reindex pentru a schimba -addressindex + + + You need to rebuild the database using -reindex to change -spentindex + Trebuie să reconstruiești baza de date utilizând -reindex pentru a schimba -spentindex + You need to rebuild the database using -reindex to change -txindex Trebuie să reconstruiești baza de date utilizând -reindex pentru a schimba -txindex diff --git a/src/qt/locale/dash_zh_TW.ts b/src/qt/locale/dash_zh_TW.ts index 1679f099eb..39ae2b64fb 100644 --- a/src/qt/locale/dash_zh_TW.ts +++ b/src/qt/locale/dash_zh_TW.ts @@ -597,6 +597,30 @@ Information 資訊 + + Received and sent multiple transactions + 接收和發送多個交易 + + + Sent multiple transactions + 發送多筆交易 + + + Received multiple transactions + 收到多筆交易 + + + Sent Amount: %1 + + 發送金額: %1 + + + + Received Amount: %1 + + 收到的款項: %1 + + Date: %1 @@ -1065,6 +1089,10 @@ My masternodes only 只顯示我的主節點 + + Service + 服務 + PoSe Score PoSe 評分 @@ -1081,10 +1109,26 @@ Next Payment 下一次付款 + + Payout Address + 獎金位址 + Operator Reward 運營者獎勵 + + Collateral Address + 抵押品位址 + + + Owner Address + 所有者位址 + + + Voting Address + 投票位址 + Copy ProTx Hash 複製 ProTx 哈希 @@ -1274,6 +1318,10 @@ This amount acts as a threshold to turn off PrivateSend once it's reached. 此金額為關閉匿名發送的門檻。 + + Target PrivateSend balance + 目標匿名發送餘額 + Automatically open the Dash Core client port on the router. This only works when your router supports UPnP and it is enabled. 自動在路由器上開放達世幣核心客戶端的通訊埠。只有在你的路由器支援且開啓「通用即插即用」協定(UPnP)時才有作用。 @@ -2749,6 +2797,18 @@ https://www.transifex.com/projects/p/dash/ any available funds 任何可用資金 + + Transaction size: %1 + 交易大小: %1 + + + Fee rate: %1 + 費用率: %1 + + + This transaction will consume %n input(s) + 此交易將消耗 %n 個輸入 + Confirm send coins 確認發送資金 @@ -4058,6 +4118,10 @@ https://www.transifex.com/projects/p/dash/ No compatible Masternode found. 沒有找到相容的主節點。 + + Not enough funds to mix. + 沒有足夠的資金以供混合使用。 + Not in the Masternode list. 不在主節點列表中。 @@ -4350,6 +4414,10 @@ https://www.transifex.com/projects/p/dash/ Warning: Unknown block versions being mined! It's possible unknown rules are in effect 警告 : 正在開採未知版本的區塊。未知的規則可能正在生效 + + You need to rebuild the database using -reindex to change -timestampindex + 您需要使用-reindex來重建數據庫,並更改-timestampindex + You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain 您需要使用-reindex 來重建數據庫以回到未修剪模式。 這將重新下載整個區塊鏈 @@ -4662,6 +4730,14 @@ https://www.transifex.com/projects/p/dash/ You can not start a masternode with wallet enabled. 您無法在啟用了錢包的情況下啟動主節點。 + + You need to rebuild the database using -reindex to change -addressindex + 您需要使用-reindex 來重建數據庫,並更改-addressindex + + + You need to rebuild the database using -reindex to change -spentindex + 您需要使用-reindex 來重建數據庫,並更改-spentindex + You need to rebuild the database using -reindex to change -txindex 改變 -txindex 參數後,必須要用 -reindex 參數來重建資料庫 diff --git a/test/functional/dip4-coinbasemerkleroots.py b/test/functional/dip4-coinbasemerkleroots.py index 0a86f5c466..ffca483df0 100755 --- a/test/functional/dip4-coinbasemerkleroots.py +++ b/test/functional/dip4-coinbasemerkleroots.py @@ -24,13 +24,13 @@ class TestNode(NodeConnCB): self.last_mnlistdiff = message def wait_for_mnlistdiff(self, timeout=30): - self.last_mnlistdiff = None def received_mnlistdiff(): return self.last_mnlistdiff is not None return wait_until(received_mnlistdiff, timeout=timeout) def getmnlistdiff(self, baseBlockHash, blockHash): msg = msg_getmnlistd(baseBlockHash, blockHash) + self.last_mnlistdiff = None self.send_message(msg) self.wait_for_mnlistdiff() return self.last_mnlistdiff