mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
refactor: remove fMasternodeMode usage from coinjoin logic
This commit is contained in:
parent
27b2e5cd5d
commit
c62a3d5778
@ -31,7 +31,7 @@
|
||||
|
||||
PeerMsgRet CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv)
|
||||
{
|
||||
if (fMasternodeMode) return {};
|
||||
if (m_is_masternode) return {};
|
||||
if (!m_mn_sync.IsBlockchainSynced()) return {};
|
||||
|
||||
if (msg_type == NetMsgType::DSQUEUE) {
|
||||
@ -133,7 +133,7 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataS
|
||||
|
||||
void CCoinJoinClientManager::ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv)
|
||||
{
|
||||
if (fMasternodeMode) return;
|
||||
if (m_is_masternode) return;
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return;
|
||||
if (!m_mn_sync.IsBlockchainSynced()) return;
|
||||
|
||||
@ -156,19 +156,20 @@ void CCoinJoinClientManager::ProcessMessage(CNode& peer, CConnman& connman, cons
|
||||
}
|
||||
|
||||
CCoinJoinClientSession::CCoinJoinClientSession(CWallet& wallet, CoinJoinWalletManager& walletman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman,
|
||||
const CMasternodeSync& mn_sync, const std::unique_ptr<CCoinJoinClientQueueManager>& queueman) :
|
||||
const CMasternodeSync& mn_sync, const std::unique_ptr<CCoinJoinClientQueueManager>& queueman, bool is_masternode) :
|
||||
m_wallet(wallet),
|
||||
m_walletman(walletman),
|
||||
m_manager(*Assert(walletman.Get(wallet.GetName()))),
|
||||
m_dmnman(dmnman),
|
||||
m_mn_metaman(mn_metaman),
|
||||
m_mn_sync(mn_sync),
|
||||
m_queueman(queueman)
|
||||
m_queueman(queueman),
|
||||
m_is_masternode{is_masternode}
|
||||
{}
|
||||
|
||||
void CCoinJoinClientSession::ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv)
|
||||
{
|
||||
if (fMasternodeMode) return;
|
||||
if (m_is_masternode) return;
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return;
|
||||
if (!m_mn_sync.IsBlockchainSynced()) return;
|
||||
|
||||
@ -385,7 +386,7 @@ bool CCoinJoinClientManager::GetMixingMasternodesInfo(std::vector<CDeterministic
|
||||
//
|
||||
bool CCoinJoinClientSession::CheckTimeout()
|
||||
{
|
||||
if (fMasternodeMode) return false;
|
||||
if (m_is_masternode) return false;
|
||||
|
||||
if (nState == POOL_STATE_IDLE) return false;
|
||||
|
||||
@ -422,7 +423,7 @@ bool CCoinJoinClientSession::CheckTimeout()
|
||||
void CCoinJoinClientManager::CheckTimeout()
|
||||
{
|
||||
AssertLockNotHeld(cs_deqsessions);
|
||||
if (fMasternodeMode) return;
|
||||
if (m_is_masternode) return;
|
||||
|
||||
if (!CCoinJoinClientOptions::IsEnabled() || !IsMixing()) return;
|
||||
|
||||
@ -440,7 +441,7 @@ void CCoinJoinClientManager::CheckTimeout()
|
||||
//
|
||||
bool CCoinJoinClientSession::SendDenominate(const std::vector<std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, CConnman& connman)
|
||||
{
|
||||
if (fMasternodeMode) {
|
||||
if (m_is_masternode) {
|
||||
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::SendDenominate -- CoinJoin from a Masternode is not supported currently.\n");
|
||||
return false;
|
||||
}
|
||||
@ -497,7 +498,7 @@ bool CCoinJoinClientSession::SendDenominate(const std::vector<std::pair<CTxDSIn,
|
||||
// Process incoming messages from Masternode updating the progress of mixing
|
||||
void CCoinJoinClientSession::ProcessPoolStateUpdate(CCoinJoinStatusUpdate psssup)
|
||||
{
|
||||
if (fMasternodeMode) return;
|
||||
if (m_is_masternode) return;
|
||||
|
||||
// do not update state when mixing client state is one of these
|
||||
if (nState == POOL_STATE_IDLE || nState == POOL_STATE_ERROR) return;
|
||||
@ -551,7 +552,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con
|
||||
{
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return false;
|
||||
|
||||
if (fMasternodeMode) return false;
|
||||
if (m_is_masternode) return false;
|
||||
if (!mixingMasternode) return false;
|
||||
|
||||
LOCK(m_wallet.cs_wallet);
|
||||
@ -680,7 +681,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTxMemPool& mempool, con
|
||||
// mixing transaction was completed (failed or successful)
|
||||
void CCoinJoinClientSession::CompletedTransaction(PoolMessage nMessageID)
|
||||
{
|
||||
if (fMasternodeMode) return;
|
||||
if (m_is_masternode) return;
|
||||
|
||||
if (nMessageID == MSG_SUCCESS) {
|
||||
m_manager.UpdatedSuccessBlock();
|
||||
@ -697,7 +698,7 @@ void CCoinJoinClientSession::CompletedTransaction(PoolMessage nMessageID)
|
||||
|
||||
void CCoinJoinClientManager::UpdatedSuccessBlock()
|
||||
{
|
||||
if (fMasternodeMode) return;
|
||||
if (m_is_masternode) return;
|
||||
nCachedLastSuccessBlock = nCachedBlockHeight;
|
||||
}
|
||||
|
||||
@ -782,7 +783,7 @@ bool CCoinJoinClientManager::CheckAutomaticBackup()
|
||||
//
|
||||
bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CTxMemPool& mempool, bool fDryRun)
|
||||
{
|
||||
if (fMasternodeMode) return false; // no client-side mixing on masternodes
|
||||
if (m_is_masternode) return false; // no client-side mixing on masternodes
|
||||
if (nState != POOL_STATE_IDLE) return false;
|
||||
|
||||
if (!m_mn_sync.IsBlockchainSynced()) {
|
||||
@ -962,7 +963,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CTxMemPo
|
||||
|
||||
bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, CTxMemPool& mempool, bool fDryRun)
|
||||
{
|
||||
if (fMasternodeMode) return false; // no client-side mixing on masternodes
|
||||
if (m_is_masternode) return false; // no client-side mixing on masternodes
|
||||
if (!CCoinJoinClientOptions::IsEnabled() || !IsMixing()) return false;
|
||||
|
||||
if (!m_mn_sync.IsBlockchainSynced()) {
|
||||
@ -991,7 +992,7 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, CTxMemPo
|
||||
AssertLockNotHeld(cs_deqsessions);
|
||||
LOCK(cs_deqsessions);
|
||||
if (int(deqSessions.size()) < CCoinJoinClientOptions::GetSessions()) {
|
||||
deqSessions.emplace_back(m_wallet, m_walletman, m_dmnman, m_mn_metaman, m_mn_sync, m_queueman);
|
||||
deqSessions.emplace_back(m_wallet, m_walletman, m_dmnman, m_mn_metaman, m_mn_sync, m_queueman, m_is_masternode);
|
||||
}
|
||||
for (auto& session : deqSessions) {
|
||||
if (!CheckAutomaticBackup()) return false;
|
||||
@ -1832,7 +1833,7 @@ void CCoinJoinClientManager::UpdatedBlockTip(const CBlockIndex* pindex)
|
||||
|
||||
void CCoinJoinClientQueueManager::DoMaintenance()
|
||||
{
|
||||
if (fMasternodeMode) return; // no client-side mixing on masternodes
|
||||
if (m_is_masternode) return; // no client-side mixing on masternodes
|
||||
|
||||
if (!m_mn_sync.IsBlockchainSynced() || ShutdownRequested()) return;
|
||||
|
||||
@ -1842,7 +1843,7 @@ void CCoinJoinClientQueueManager::DoMaintenance()
|
||||
void CCoinJoinClientManager::DoMaintenance(CConnman& connman, CTxMemPool& mempool)
|
||||
{
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return;
|
||||
if (fMasternodeMode) return; // no client-side mixing on masternodes
|
||||
if (m_is_masternode) return; // no client-side mixing on masternodes
|
||||
|
||||
if (!m_mn_sync.IsBlockchainSynced() || ShutdownRequested()) return;
|
||||
|
||||
@ -1893,7 +1894,7 @@ void CCoinJoinClientManager::GetJsonInfo(UniValue& obj) const
|
||||
void CoinJoinWalletManager::Add(CWallet& wallet) {
|
||||
m_wallet_manager_map.try_emplace(
|
||||
wallet.GetName(),
|
||||
std::make_unique<CCoinJoinClientManager>(wallet, *this, m_dmnman, m_mn_metaman, m_mn_sync, m_queueman)
|
||||
std::make_unique<CCoinJoinClientManager>(wallet, *this, m_dmnman, m_mn_metaman, m_mn_sync, m_queueman, m_is_masternode)
|
||||
);
|
||||
g_wallet_init_interface.InitCoinJoinSettings(*this);
|
||||
}
|
||||
|
@ -74,8 +74,10 @@ public:
|
||||
|
||||
public:
|
||||
CoinJoinWalletManager(CConnman& connman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool,
|
||||
const CMasternodeSync& mn_sync, const std::unique_ptr<CCoinJoinClientQueueManager>& queueman)
|
||||
: m_connman(connman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mempool(mempool), m_mn_sync(mn_sync), m_queueman(queueman) {}
|
||||
const CMasternodeSync& mn_sync, const std::unique_ptr<CCoinJoinClientQueueManager>& queueman, bool is_masternode)
|
||||
: m_connman(connman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mempool(mempool), m_mn_sync(mn_sync), m_queueman(queueman),
|
||||
m_is_masternode{is_masternode}
|
||||
{}
|
||||
|
||||
~CoinJoinWalletManager() {
|
||||
for (auto& [wallet_name, cj_man] : m_wallet_manager_map) {
|
||||
@ -101,6 +103,7 @@ private:
|
||||
const CMasternodeSync& m_mn_sync;
|
||||
const std::unique_ptr<CCoinJoinClientQueueManager>& m_queueman;
|
||||
|
||||
const bool m_is_masternode;
|
||||
wallet_name_cjman_map m_wallet_manager_map;
|
||||
};
|
||||
|
||||
@ -115,6 +118,9 @@ private:
|
||||
const CMasternodeSync& m_mn_sync;
|
||||
const std::unique_ptr<CCoinJoinClientQueueManager>& m_queueman;
|
||||
|
||||
// Track node type
|
||||
const bool m_is_masternode;
|
||||
|
||||
std::vector<COutPoint> vecOutPointLocked;
|
||||
|
||||
bilingual_str strLastMessage;
|
||||
@ -162,7 +168,7 @@ private:
|
||||
|
||||
public:
|
||||
explicit CCoinJoinClientSession(CWallet& wallet, CoinJoinWalletManager& walletman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman,
|
||||
const CMasternodeSync& mn_sync, const std::unique_ptr<CCoinJoinClientQueueManager>& queueman);
|
||||
const CMasternodeSync& mn_sync, const std::unique_ptr<CCoinJoinClientQueueManager>& queueman, bool is_masternode);
|
||||
|
||||
void ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv);
|
||||
|
||||
@ -197,12 +203,14 @@ private:
|
||||
CDeterministicMNManager& m_dmnman;
|
||||
CMasternodeMetaMan& m_mn_metaman;
|
||||
const CMasternodeSync& m_mn_sync;
|
||||
|
||||
mutable Mutex cs_ProcessDSQueue;
|
||||
const bool m_is_masternode;
|
||||
|
||||
public:
|
||||
explicit CCoinJoinClientQueueManager(CConnman& _connman, CoinJoinWalletManager& walletman, CDeterministicMNManager& dmnman,
|
||||
CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync) :
|
||||
connman(_connman), m_walletman(walletman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync) {};
|
||||
CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync, bool is_masternode) :
|
||||
connman(_connman), m_walletman(walletman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), m_is_masternode{is_masternode} {};
|
||||
|
||||
PeerMsgRet ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue);
|
||||
PeerMsgRet ProcessDSQueue(const CNode& peer, CDataStream& vRecv);
|
||||
@ -221,6 +229,9 @@ private:
|
||||
const CMasternodeSync& m_mn_sync;
|
||||
const std::unique_ptr<CCoinJoinClientQueueManager>& m_queueman;
|
||||
|
||||
// Track node type
|
||||
const bool m_is_masternode;
|
||||
|
||||
// Keep track of the used Masternodes
|
||||
std::vector<COutPoint> vecMasternodesUsed;
|
||||
|
||||
@ -252,8 +263,9 @@ public:
|
||||
|
||||
explicit CCoinJoinClientManager(CWallet& wallet, CoinJoinWalletManager& walletman, CDeterministicMNManager& dmnman,
|
||||
CMasternodeMetaMan& mn_metaman, const CMasternodeSync& mn_sync,
|
||||
const std::unique_ptr<CCoinJoinClientQueueManager>& queueman) :
|
||||
m_wallet(wallet), m_walletman(walletman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), m_queueman(queueman) {}
|
||||
const std::unique_ptr<CCoinJoinClientQueueManager>& queueman, bool is_masternode) :
|
||||
m_wallet(wallet), m_walletman(walletman), m_dmnman(dmnman), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), m_queueman(queueman),
|
||||
m_is_masternode{is_masternode} {}
|
||||
|
||||
void ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_deqsessions);
|
||||
|
||||
|
@ -14,8 +14,8 @@ CJContext::CJContext(CChainState& chainstate, CConnman& connman, CDeterministicM
|
||||
const std::unique_ptr<PeerManager>& peerman, bool relay_txes) :
|
||||
dstxman{std::make_unique<CDSTXManager>()},
|
||||
#ifdef ENABLE_WALLET
|
||||
walletman{std::make_unique<CoinJoinWalletManager>(connman, dmnman, mn_metaman, mempool, mn_sync, queueman)},
|
||||
queueman {relay_txes ? std::make_unique<CCoinJoinClientQueueManager>(connman, *walletman, dmnman, mn_metaman, mn_sync) : nullptr},
|
||||
walletman{std::make_unique<CoinJoinWalletManager>(connman, dmnman, mn_metaman, mempool, mn_sync, queueman, /* is_masternode = */ mn_activeman != nullptr)},
|
||||
queueman {relay_txes ? std::make_unique<CCoinJoinClientQueueManager>(connman, *walletman, dmnman, mn_metaman, mn_sync, /* is_masternode = */ mn_activeman != nullptr) : nullptr},
|
||||
#endif // ENABLE_WALLET
|
||||
server{std::make_unique<CCoinJoinServer>(chainstate, connman, dmnman, *dstxman, mn_metaman, mempool, mn_activeman, mn_sync, peerman)}
|
||||
{}
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
PeerMsgRet CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_type, CDataStream& vRecv)
|
||||
{
|
||||
if (!fMasternodeMode) return {};
|
||||
if (!m_mn_activeman) return {};
|
||||
if (!m_mn_sync.IsBlockchainSynced()) return {};
|
||||
|
||||
if (msg_type == NetMsgType::DSACCEPT) {
|
||||
@ -249,7 +249,7 @@ void CCoinJoinServer::SetNull()
|
||||
//
|
||||
void CCoinJoinServer::CheckPool()
|
||||
{
|
||||
if (!fMasternodeMode) return;
|
||||
if (!m_mn_activeman) return;
|
||||
|
||||
if (int entries = GetEntriesCount(); entries != 0) LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CheckPool -- entries count %lu\n", entries);
|
||||
|
||||
@ -312,9 +312,7 @@ void CCoinJoinServer::CreateFinalTransaction()
|
||||
void CCoinJoinServer::CommitFinalTransaction()
|
||||
{
|
||||
AssertLockNotHeld(cs_coinjoin);
|
||||
if (!fMasternodeMode) return; // check and relay final tx only on masternode
|
||||
|
||||
assert(m_mn_activeman);
|
||||
if (!m_mn_activeman) return; // check and relay final tx only on masternode
|
||||
|
||||
CTransactionRef finalTransaction = WITH_LOCK(cs_coinjoin, return MakeTransactionRef(finalMutableTransaction));
|
||||
uint256 hashTx = finalTransaction->GetHash();
|
||||
@ -377,7 +375,7 @@ void CCoinJoinServer::CommitFinalTransaction()
|
||||
void CCoinJoinServer::ChargeFees() const
|
||||
{
|
||||
AssertLockNotHeld(cs_coinjoin);
|
||||
if (!fMasternodeMode) return;
|
||||
if (!m_mn_activeman) return;
|
||||
|
||||
//we don't need to charge collateral for every offence.
|
||||
if (GetRandInt(100) > 33) return;
|
||||
@ -445,7 +443,7 @@ void CCoinJoinServer::ChargeFees() const
|
||||
*/
|
||||
void CCoinJoinServer::ChargeRandomFees() const
|
||||
{
|
||||
if (!fMasternodeMode) return;
|
||||
if (!m_mn_activeman) return;
|
||||
|
||||
for (const auto& txCollateral : vecSessionCollaterals) {
|
||||
if (GetRandInt(100) > 10) return;
|
||||
@ -467,7 +465,7 @@ void CCoinJoinServer::ConsumeCollateral(const CTransactionRef& txref) const
|
||||
|
||||
bool CCoinJoinServer::HasTimedOut() const
|
||||
{
|
||||
if (!fMasternodeMode) return false;
|
||||
if (!m_mn_activeman) return false;
|
||||
|
||||
if (nState == POOL_STATE_IDLE) return false;
|
||||
|
||||
@ -481,7 +479,7 @@ bool CCoinJoinServer::HasTimedOut() const
|
||||
//
|
||||
void CCoinJoinServer::CheckTimeout()
|
||||
{
|
||||
if (!fMasternodeMode) return;
|
||||
if (!m_mn_activeman) return;
|
||||
|
||||
CheckQueue();
|
||||
|
||||
@ -501,9 +499,7 @@ void CCoinJoinServer::CheckTimeout()
|
||||
*/
|
||||
void CCoinJoinServer::CheckForCompleteQueue()
|
||||
{
|
||||
if (!fMasternodeMode) return;
|
||||
|
||||
assert(m_mn_activeman);
|
||||
if (!m_mn_activeman) return;
|
||||
|
||||
if (nState == POOL_STATE_QUEUE && IsSessionReady()) {
|
||||
SetState(POOL_STATE_ACCEPTING_ENTRIES);
|
||||
@ -570,7 +566,7 @@ bool CCoinJoinServer::IsInputScriptSigValid(const CTxIn& txin) const
|
||||
bool CCoinJoinServer::AddEntry(const CCoinJoinEntry& entry, PoolMessage& nMessageIDRet)
|
||||
{
|
||||
AssertLockNotHeld(cs_coinjoin);
|
||||
if (!fMasternodeMode) return false;
|
||||
if (!m_mn_activeman) return false;
|
||||
|
||||
if (size_t(GetEntriesCount()) >= vecSessionCollaterals.size()) {
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR: entries is full!\n", __func__);
|
||||
@ -679,7 +675,7 @@ bool CCoinJoinServer::IsSignaturesComplete() const
|
||||
|
||||
bool CCoinJoinServer::IsAcceptableDSA(const CCoinJoinAccept& dsa, PoolMessage& nMessageIDRet) const
|
||||
{
|
||||
if (!fMasternodeMode) return false;
|
||||
if (!m_mn_activeman) return false;
|
||||
|
||||
// is denom even something legit?
|
||||
if (!CoinJoin::IsValidDenomination(dsa.nDenom)) {
|
||||
@ -700,9 +696,7 @@ bool CCoinJoinServer::IsAcceptableDSA(const CCoinJoinAccept& dsa, PoolMessage& n
|
||||
|
||||
bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage& nMessageIDRet)
|
||||
{
|
||||
if (!fMasternodeMode || nSessionID != 0) return false;
|
||||
|
||||
assert(m_mn_activeman);
|
||||
if (!m_mn_activeman || nSessionID != 0) return false;
|
||||
|
||||
// new session can only be started in idle mode
|
||||
if (nState != POOL_STATE_IDLE) {
|
||||
@ -744,7 +738,7 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage&
|
||||
|
||||
bool CCoinJoinServer::AddUserToExistingSession(const CCoinJoinAccept& dsa, PoolMessage& nMessageIDRet)
|
||||
{
|
||||
if (!fMasternodeMode || nSessionID == 0 || IsSessionReady()) return false;
|
||||
if (!m_mn_activeman || nSessionID == 0 || IsSessionReady()) return false;
|
||||
|
||||
if (!IsAcceptableDSA(dsa, nMessageIDRet)) {
|
||||
return false;
|
||||
@ -880,7 +874,7 @@ void CCoinJoinServer::RelayCompletedTransaction(PoolMessage nMessageID)
|
||||
|
||||
void CCoinJoinServer::SetState(PoolState nStateNew)
|
||||
{
|
||||
if (!fMasternodeMode) return;
|
||||
if (!m_mn_activeman) return;
|
||||
|
||||
if (nStateNew == POOL_STATE_ERROR) {
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::SetState -- Can't set state to ERROR as a Masternode. \n");
|
||||
@ -894,7 +888,7 @@ void CCoinJoinServer::SetState(PoolState nStateNew)
|
||||
|
||||
void CCoinJoinServer::DoMaintenance()
|
||||
{
|
||||
if (!fMasternodeMode) return; // only run on masternodes
|
||||
if (!m_mn_activeman) return; // only run on masternodes
|
||||
if (!m_mn_sync.IsBlockchainSynced()) return;
|
||||
if (ShutdownRequested()) return;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user