mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 11:32:46 +01:00
Merge pull request #2594 from codablock/pr_dip3_cleanup_directlyusedmnmgr
Directly use deterministicMNManager instead of compat code in CMasternodeMan
This commit is contained in:
commit
46a6fc33e8
@ -151,6 +151,15 @@ CDeterministicMNCPtr CDeterministicMNList::GetMNByCollateral(const COutPoint& co
|
||||
return GetUniquePropertyMN(collateralOutpoint);
|
||||
}
|
||||
|
||||
CDeterministicMNCPtr CDeterministicMNList::GetValidMNByCollateral(const COutPoint& collateralOutpoint) const
|
||||
{
|
||||
auto dmn = GetMNByCollateral(collateralOutpoint);
|
||||
if (dmn && !IsMNValid(dmn)) {
|
||||
return nullptr;
|
||||
}
|
||||
return dmn;
|
||||
}
|
||||
|
||||
static int CompareByLastPaid_GetHeight(const CDeterministicMN& dmn)
|
||||
{
|
||||
int height = dmn.pdmnState->nLastPaidHeight;
|
||||
@ -826,20 +835,6 @@ CDeterministicMNList CDeterministicMNManager::GetListAtChainTip()
|
||||
return GetListForBlock(tipBlockHash);
|
||||
}
|
||||
|
||||
bool CDeterministicMNManager::HasValidMNCollateralAtChainTip(const COutPoint& outpoint)
|
||||
{
|
||||
auto mnList = GetListAtChainTip();
|
||||
auto dmn = mnList.GetMNByCollateral(outpoint);
|
||||
return dmn && mnList.IsMNValid(dmn);
|
||||
}
|
||||
|
||||
bool CDeterministicMNManager::HasMNCollateralAtChainTip(const COutPoint& outpoint)
|
||||
{
|
||||
auto mnList = GetListAtChainTip();
|
||||
auto dmn = mnList.GetMNByCollateral(outpoint);
|
||||
return dmn != nullptr;
|
||||
}
|
||||
|
||||
bool CDeterministicMNManager::IsProTxWithCollateral(const CTransactionRef& tx, uint32_t n)
|
||||
{
|
||||
if (tx->nVersion != 3 || tx->nType != TRANSACTION_PROVIDER_REGISTER) {
|
||||
|
@ -289,10 +289,23 @@ public:
|
||||
{
|
||||
return GetMN(proTxHash) != nullptr;
|
||||
}
|
||||
bool HasValidMN(const uint256& proTxHash) const
|
||||
{
|
||||
return GetValidMN(proTxHash) != nullptr;
|
||||
}
|
||||
bool HasMNByCollateral(const COutPoint& collateralOutpoint) const
|
||||
{
|
||||
return GetMNByCollateral(collateralOutpoint) != nullptr;
|
||||
}
|
||||
bool HasValidMNByCollateral(const COutPoint& collateralOutpoint) const
|
||||
{
|
||||
return GetValidMNByCollateral(collateralOutpoint) != nullptr;
|
||||
}
|
||||
CDeterministicMNCPtr GetMN(const uint256& proTxHash) const;
|
||||
CDeterministicMNCPtr GetValidMN(const uint256& proTxHash) const;
|
||||
CDeterministicMNCPtr GetMNByOperatorKey(const CBLSPublicKey& pubKey);
|
||||
CDeterministicMNCPtr GetMNByCollateral(const COutPoint& collateralOutpoint) const;
|
||||
CDeterministicMNCPtr GetValidMNByCollateral(const COutPoint& collateralOutpoint) const;
|
||||
CDeterministicMNCPtr GetMNPayee() const;
|
||||
|
||||
/**
|
||||
@ -479,10 +492,6 @@ public:
|
||||
CDeterministicMNList GetListForBlock(const uint256& blockHash);
|
||||
CDeterministicMNList GetListAtChainTip();
|
||||
|
||||
// TODO remove after removal of old non-deterministic lists
|
||||
bool HasValidMNCollateralAtChainTip(const COutPoint& outpoint);
|
||||
bool HasMNCollateralAtChainTip(const COutPoint& outpoint);
|
||||
|
||||
// Test if given TX is a ProRegTx which also contains the collateral at index n
|
||||
bool IsProTxWithCollateral(const CTransactionRef& tx, uint32_t n);
|
||||
|
||||
|
@ -116,14 +116,13 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mnodeman.Has(vote.GetMasternodeOutpoint())) {
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
if (!mnList.HasValidMNByCollateral(vote.GetMasternodeOutpoint())) {
|
||||
std::ostringstream ostr;
|
||||
ostr << "CGovernanceObject::ProcessVote -- Masternode " << vote.GetMasternodeOutpoint().ToStringShort() << " not found";
|
||||
exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_WARNING);
|
||||
if (cmmapOrphanVotes.Insert(vote.GetMasternodeOutpoint(), vote_time_pair_t(vote, GetAdjustedTime() + GOVERNANCE_ORPHAN_EXPIRATION_TIME))) {
|
||||
if (pfrom) {
|
||||
mnodeman.AskForMN(pfrom, vote.GetMasternodeOutpoint(), connman);
|
||||
}
|
||||
LogPrintf("%s\n", ostr.str());
|
||||
} else {
|
||||
LogPrint("gobject", "%s\n", ostr.str());
|
||||
@ -212,9 +211,11 @@ void CGovernanceObject::ClearMasternodeVotes()
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
vote_m_it it = mapCurrentMNVotes.begin();
|
||||
while (it != mapCurrentMNVotes.end()) {
|
||||
if (!mnodeman.Has(it->first)) {
|
||||
if (!mnList.HasValidMNByCollateral(it->first)) {
|
||||
fileVotes.RemoveVotesFromMasternode(it->first);
|
||||
mapCurrentMNVotes.erase(it++);
|
||||
} else {
|
||||
@ -552,9 +553,11 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast
|
||||
return true;
|
||||
}
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
std::string strOutpoint = masternodeOutpoint.ToStringShort();
|
||||
masternode_info_t infoMn;
|
||||
if (!mnodeman.GetMasternodeInfo(masternodeOutpoint, infoMn)) {
|
||||
auto dmn = mnList.GetValidMNByCollateral(masternodeOutpoint);
|
||||
if (!dmn) {
|
||||
CMasternode::CollateralStatus err = CMasternode::CheckCollateral(masternodeOutpoint, CKeyID());
|
||||
if (err == CMasternode::COLLATERAL_UTXO_NOT_FOUND) {
|
||||
strError = "Failed to find Masternode UTXO, missing masternode=" + strOutpoint + "\n";
|
||||
@ -572,16 +575,9 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast
|
||||
}
|
||||
|
||||
// Check that we have a valid MN signature
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
if (!CheckSignature(infoMn.blsPubKeyOperator)) {
|
||||
strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.blsPubKeyOperator.ToString();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!CheckSignature(infoMn.legacyKeyIDOperator)) {
|
||||
strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.legacyKeyIDOperator.ToString();
|
||||
return false;
|
||||
}
|
||||
if (!CheckSignature(dmn->pdmnState->pubKeyOperator)) {
|
||||
strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey = " + dmn->pdmnState->pubKeyOperator.ToString();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -779,7 +775,7 @@ void CGovernanceObject::UpdateSentinelVariables()
|
||||
{
|
||||
// CALCULATE MINIMUM SUPPORT LEVELS REQUIRED
|
||||
|
||||
int nMnCount = mnodeman.CountEnabled();
|
||||
int nMnCount = (int)deterministicMNManager->GetListAtChainTip().GetValidMNsCount();
|
||||
if (nMnCount == 0) return;
|
||||
|
||||
// CALCULATE THE MINUMUM VOTE COUNT REQUIRED FOR FULL SIGNAL
|
||||
@ -812,6 +808,7 @@ void CGovernanceObject::UpdateSentinelVariables()
|
||||
void CGovernanceObject::CheckOrphanVotes(CConnman& connman)
|
||||
{
|
||||
int64_t nNow = GetAdjustedTime();
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
const vote_cmm_t::list_t& listVotes = cmmapOrphanVotes.GetItemList();
|
||||
vote_cmm_t::list_cit it = listVotes.begin();
|
||||
while (it != listVotes.end()) {
|
||||
@ -821,7 +818,7 @@ void CGovernanceObject::CheckOrphanVotes(CConnman& connman)
|
||||
const CGovernanceVote& vote = pairVote.first;
|
||||
if (pairVote.second < nNow) {
|
||||
fRemove = true;
|
||||
} else if (!mnodeman.Has(vote.GetMasternodeOutpoint())) {
|
||||
} else if (!mnList.HasValidMNByCollateral(vote.GetMasternodeOutpoint())) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
@ -256,20 +256,16 @@ bool CGovernanceVote::IsValid(bool useVotingKey) const
|
||||
return false;
|
||||
}
|
||||
|
||||
masternode_info_t infoMn;
|
||||
if (!mnodeman.GetMasternodeInfo(masternodeOutpoint, infoMn)) {
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(masternodeOutpoint);
|
||||
if (!dmn) {
|
||||
LogPrint("gobject", "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", masternodeOutpoint.ToStringShort());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (useVotingKey) {
|
||||
return CheckSignature(infoMn.keyIDVoting);
|
||||
return CheckSignature(dmn->pdmnState->keyIDVoting);
|
||||
} else {
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
return CheckSignature(infoMn.blsPubKeyOperator);
|
||||
} else {
|
||||
return CheckSignature(infoMn.legacyKeyIDOperator);
|
||||
}
|
||||
return CheckSignature(dmn->pdmnState->pubKeyOperator);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -515,12 +515,17 @@ std::vector<CGovernanceVote> CGovernanceManager::GetCurrentVotes(const uint256&
|
||||
if (it == mapObjects.end()) return vecResult;
|
||||
const CGovernanceObject& govobj = it->second;
|
||||
|
||||
CMasternode mn;
|
||||
std::map<COutPoint, CMasternode> mapMasternodes;
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
std::map<COutPoint, CDeterministicMNCPtr> mapMasternodes;
|
||||
if (mnCollateralOutpointFilter.IsNull()) {
|
||||
mapMasternodes = mnodeman.GetFullMasternodeMap();
|
||||
} else if (mnodeman.Get(mnCollateralOutpointFilter, mn)) {
|
||||
mapMasternodes[mnCollateralOutpointFilter] = mn;
|
||||
mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
|
||||
mapMasternodes.emplace(dmn->collateralOutpoint, dmn);
|
||||
});
|
||||
} else {
|
||||
auto dmn = mnList.GetValidMNByCollateral(mnCollateralOutpointFilter);
|
||||
if (dmn) {
|
||||
mapMasternodes.emplace(dmn->collateralOutpoint, dmn);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop thru each MN collateral outpoint and get the votes for the `nParentHash` governance object
|
||||
@ -1074,7 +1079,7 @@ int CGovernanceManager::RequestGovernanceObjectVotes(const std::vector<CNode*>&
|
||||
int nMaxObjRequestsPerNode = 1;
|
||||
size_t nProjectedVotes = 2000;
|
||||
if (Params().NetworkIDString() != CBaseChainParams::MAIN) {
|
||||
nMaxObjRequestsPerNode = std::max(1, int(nProjectedVotes / std::max(1, mnodeman.size())));
|
||||
nMaxObjRequestsPerNode = std::max(1, int(nProjectedVotes / std::max(1, (int)deterministicMNManager->GetListAtChainTip().GetValidMNsCount())));
|
||||
}
|
||||
|
||||
{
|
||||
|
102
src/instantx.cpp
102
src/instantx.cpp
@ -245,8 +245,7 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman)
|
||||
|
||||
int nRank;
|
||||
uint256 quorumModifierHash;
|
||||
int nMinRequiredProtocol = std::max(MIN_INSTANTSEND_PROTO_VERSION, mnpayments.GetMinMasternodePaymentsProto());
|
||||
if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight, nMinRequiredProtocol)) {
|
||||
if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight)) {
|
||||
LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternodeInfo.outpoint.ToStringShort());
|
||||
continue;
|
||||
}
|
||||
@ -469,7 +468,8 @@ void CInstantSend::UpdateVotedOutpoints(const CTxLockVote& vote, CTxLockCandidat
|
||||
txLockCandidate.MarkOutpointAsAttacked(vote.GetOutpoint());
|
||||
it2->second.MarkOutpointAsAttacked(vote.GetOutpoint());
|
||||
// apply maximum PoSe ban score to this masternode i.e. PoSe-ban it instantly
|
||||
mnodeman.PoSeBan(vote.GetMasternodeOutpoint());
|
||||
// TODO Call new PoSe system when it's ready
|
||||
//mnodeman.PoSeBan(vote.GetMasternodeOutpoint());
|
||||
// NOTE: This vote must be relayed further to let all other nodes know about such
|
||||
// misbehaviour of this masternode. This way they should also be able to construct
|
||||
// conflicting lock and PoSe-ban this masternode.
|
||||
@ -1029,22 +1029,25 @@ bool CTxLockRequest::IsSimple() const
|
||||
|
||||
bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const
|
||||
{
|
||||
if (!mnodeman.Has(outpointMasternode)) {
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
if (!mnList.HasValidMNByCollateral(outpointMasternode)) {
|
||||
LogPrint("instantsend", "CTxLockVote::IsValid -- Unknown masternode %s\n", outpointMasternode.ToStringShort());
|
||||
mnodeman.AskForMN(pnode, outpointMasternode, connman);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify that masternodeProTxHash belongs to the same MN referred by the collateral
|
||||
// Only v13 nodes will send us locks with this field set, and only after spork15 activation
|
||||
// This is a leftover from the legacy non-deterministic MN list where we used the collateral to identify MNs
|
||||
// TODO eventually remove the collateral from CTxLockVote
|
||||
if (!masternodeProTxHash.IsNull()) {
|
||||
masternode_info_t mnInfo;
|
||||
if (!mnodeman.GetMasternodeInfo(masternodeProTxHash, mnInfo) || mnInfo.outpoint != outpointMasternode) {
|
||||
auto dmn = mnList.GetValidMN(masternodeProTxHash);
|
||||
if (!dmn || dmn->collateralOutpoint != outpointMasternode) {
|
||||
LogPrint("instantsend", "CTxLockVote::IsValid -- invalid masternodeProTxHash %s\n", masternodeProTxHash.ToString());
|
||||
return false;
|
||||
}
|
||||
} else if (deterministicMNManager->IsDIP3Active()) {
|
||||
LogPrint("instantsend", "CTxLockVote::IsValid -- missing masternodeProTxHash while DIP3 is active\n");
|
||||
} else {
|
||||
LogPrint("instantsend", "CTxLockVote::IsValid -- missing masternodeProTxHash\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1058,8 +1061,7 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const
|
||||
|
||||
int nRank;
|
||||
uint256 expectedQuorumModifierHash;
|
||||
int nMinRequiredProtocol = std::max(MIN_INSTANTSEND_PROTO_VERSION, mnpayments.GetMinMasternodePaymentsProto());
|
||||
if (!mnodeman.GetMasternodeRank(outpointMasternode, nRank, expectedQuorumModifierHash, nLockInputHeight, nMinRequiredProtocol)) {
|
||||
if (!mnodeman.GetMasternodeRank(outpointMasternode, nRank, expectedQuorumModifierHash, nLockInputHeight)) {
|
||||
//can be caused by past versions trying to vote with an invalid protocol
|
||||
LogPrint("instantsend", "CTxLockVote::IsValid -- Can't calculate rank for masternode %s\n", outpointMasternode.ToStringShort());
|
||||
return false;
|
||||
@ -1105,83 +1107,33 @@ bool CTxLockVote::CheckSignature() const
|
||||
{
|
||||
std::string strError;
|
||||
|
||||
masternode_info_t infoMn;
|
||||
|
||||
if (!mnodeman.GetMasternodeInfo(outpointMasternode, infoMn)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: masternode=%s\n", outpointMasternode.ToString());
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(masternodeProTxHash);
|
||||
if (!dmn) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: masternode=%s\n", masternodeProTxHash.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchMasternodeSignature);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(infoMn.blsPubKeyOperator, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, infoMn.legacyKeyIDOperator, vchMasternodeSignature, strError)) {
|
||||
// could be a signature in old format
|
||||
std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
|
||||
if (!CMessageSigner::VerifyMessage(infoMn.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
// nope, not in old format either
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
|
||||
if (!CMessageSigner::VerifyMessage(infoMn.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchMasternodeSignature);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTxLockVote::Sign()
|
||||
{
|
||||
std::string strError;
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
sig.GetBuf(vchMasternodeSignature);
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchMasternodeSignature)) {
|
||||
LogPrintf("CTxLockVote::Sign -- SignHash() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchMasternodeSignature, strError)) {
|
||||
LogPrintf("CTxLockVote::Sign -- VerifyHash() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
|
||||
|
||||
if (!CMessageSigner::SignMessage(strMessage, vchMasternodeSignature, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("CTxLockVote::Sign -- SignMessage() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
LogPrintf("CTxLockVote::Sign -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sig.GetBuf(vchMasternodeSignature);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -641,36 +641,16 @@ bool CMasternodePayments::GetBlockTxOuts(int nBlockHeight, CAmount blockReward,
|
||||
|
||||
// Is this masternode scheduled to get paid soon?
|
||||
// -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 blocks of votes
|
||||
bool CMasternodePayments::IsScheduled(const masternode_info_t& mnInfo, int nNotBlockHeight) const
|
||||
bool CMasternodePayments::IsScheduled(const CDeterministicMNCPtr& dmnIn, int nNotBlockHeight) const
|
||||
{
|
||||
LOCK(cs_mapMasternodeBlocks);
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
auto projectedPayees = deterministicMNManager->GetListAtChainTip().GetProjectedMNPayees(8);
|
||||
for (const auto &dmn : projectedPayees) {
|
||||
if (dmn->collateralOutpoint == mnInfo.outpoint) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!masternodeSync.IsMasternodeListSynced()) return false;
|
||||
|
||||
CScript mnpayee;
|
||||
mnpayee = GetScriptForDestination(mnInfo.keyIDCollateralAddress);
|
||||
|
||||
for(int64_t h = nCachedBlockHeight; h <= nCachedBlockHeight + 8; h++){
|
||||
if(h == nNotBlockHeight) continue;
|
||||
std::vector<CTxOut> voutMasternodePayments;
|
||||
if(GetBlockTxOuts(h, 0, voutMasternodePayments)) {
|
||||
for (const auto& txout : voutMasternodePayments) {
|
||||
if (txout.scriptPubKey == mnpayee)
|
||||
return true;
|
||||
}
|
||||
auto projectedPayees = deterministicMNManager->GetListAtChainTip().GetProjectedMNPayees(8);
|
||||
for (const auto &dmn : projectedPayees) {
|
||||
if (dmn->proTxHash == dmnIn->proTxHash) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1046,7 +1026,7 @@ void CMasternodePayments::CheckBlockVotes(int nBlockHeight)
|
||||
voteHash.ToString());
|
||||
continue;
|
||||
}
|
||||
if (itVote->second.masternodeOutpoint == mn.second.outpoint) {
|
||||
if (itVote->second.masternodeOutpoint == mn.second->collateralOutpoint) {
|
||||
payee = itVote->second.payee;
|
||||
found = true;
|
||||
break;
|
||||
@ -1061,12 +1041,12 @@ void CMasternodePayments::CheckBlockVotes(int nBlockHeight)
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
debugStr += strprintf(" - %s - voted for %s\n",
|
||||
mn.second.outpoint.ToStringShort(), address2.ToString());
|
||||
mn.second->collateralOutpoint.ToStringShort(), address2.ToString());
|
||||
} else {
|
||||
mapMasternodesDidNotVote.emplace(mn.second.outpoint, 0).first->second++;
|
||||
mapMasternodesDidNotVote.emplace(mn.second->collateralOutpoint, 0).first->second++;
|
||||
|
||||
debugStr += strprintf(" - %s - no vote received\n",
|
||||
mn.second.outpoint.ToStringShort());
|
||||
mn.second->collateralOutpoint.ToStringShort());
|
||||
}
|
||||
|
||||
if (++i >= MNPAYMENTS_SIGNATURES_TOTAL) break;
|
||||
|
@ -200,7 +200,7 @@ public:
|
||||
|
||||
bool GetBlockTxOuts(int nBlockHeight, CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet) const;
|
||||
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const;
|
||||
bool IsScheduled(const masternode_info_t& mnInfo, int nNotBlockHeight) const;
|
||||
bool IsScheduled(const CDeterministicMNCPtr& dmn, int nNotBlockHeight) const;
|
||||
|
||||
bool UpdateLastVote(const CMasternodePaymentVote& vote);
|
||||
|
||||
|
@ -42,10 +42,10 @@ struct CompareLastPaidBlock
|
||||
|
||||
struct CompareScoreMN
|
||||
{
|
||||
bool operator()(const std::pair<arith_uint256, const CMasternode*>& t1,
|
||||
const std::pair<arith_uint256, const CMasternode*>& t2) const
|
||||
bool operator()(const std::pair<arith_uint256, const CDeterministicMNCPtr&>& t1,
|
||||
const std::pair<arith_uint256, const CDeterministicMNCPtr&>& t2) const
|
||||
{
|
||||
return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->outpoint < t2.second->outpoint);
|
||||
return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->collateralOutpoint < t2.second->collateralOutpoint);
|
||||
}
|
||||
};
|
||||
|
||||
@ -127,6 +127,16 @@ void CMasternodeMan::AskForMN(CNode* pnode, const COutPoint& outpoint, CConnman&
|
||||
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSEG, outpoint));
|
||||
}
|
||||
|
||||
bool CMasternodeMan::IsValidForMixingTxes(const COutPoint& outpoint)
|
||||
{
|
||||
LOCK(cs);
|
||||
CMasternode* pmn = Find(outpoint);
|
||||
if (!pmn) {
|
||||
return false;
|
||||
}
|
||||
return pmn->IsValidForMixingTxes();
|
||||
}
|
||||
|
||||
bool CMasternodeMan::AllowMixing(const COutPoint &outpoint)
|
||||
{
|
||||
LOCK(cs);
|
||||
@ -153,6 +163,16 @@ bool CMasternodeMan::DisallowMixing(const COutPoint &outpoint)
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t CMasternodeMan::GetLastDsq(const COutPoint& outpoint)
|
||||
{
|
||||
LOCK(cs);
|
||||
CMasternode* pmn = Find(outpoint);
|
||||
if (!pmn) {
|
||||
return 0;
|
||||
}
|
||||
return pmn->nLastDsq;
|
||||
}
|
||||
|
||||
bool CMasternodeMan::PoSeBan(const COutPoint &outpoint)
|
||||
{
|
||||
LOCK(cs);
|
||||
@ -237,9 +257,9 @@ void CMasternodeMan::CheckAndRemove(CConnman& connman)
|
||||
// ask first MNB_RECOVERY_QUORUM_TOTAL masternodes we can connect to and we haven't asked recently
|
||||
for(int i = 0; setRequested.size() < MNB_RECOVERY_QUORUM_TOTAL && i < (int)vecMasternodeRanks.size(); i++) {
|
||||
// avoid banning
|
||||
if(mWeAskedForMasternodeListEntry.count(it->first) && mWeAskedForMasternodeListEntry[it->first].count(vecMasternodeRanks[i].second.addr)) continue;
|
||||
if(mWeAskedForMasternodeListEntry.count(it->first) && mWeAskedForMasternodeListEntry[it->first].count(vecMasternodeRanks[i].second->pdmnState->addr)) continue;
|
||||
// didn't ask recently, ok to ask now
|
||||
CService addr = vecMasternodeRanks[i].second.addr;
|
||||
CService addr = vecMasternodeRanks[i].second->pdmnState->addr;
|
||||
setRequested.insert(addr);
|
||||
listScheduledMnbRequestConnections.push_back(std::make_pair(addr, hash));
|
||||
fAskedForMnbRecovery = true;
|
||||
@ -633,7 +653,7 @@ bool CMasternodeMan::Has(const COutPoint& outpoint)
|
||||
{
|
||||
LOCK(cs);
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
return deterministicMNManager->HasValidMNCollateralAtChainTip(outpoint);
|
||||
return deterministicMNManager->GetListAtChainTip().HasValidMNByCollateral(outpoint);
|
||||
} else {
|
||||
return mapMasternodes.find(outpoint) != mapMasternodes.end();
|
||||
}
|
||||
@ -679,7 +699,7 @@ bool CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool f
|
||||
if(mnpair.second.nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) continue;
|
||||
|
||||
//it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it
|
||||
if(mnpayments.IsScheduled(mnpair.second, nBlockHeight)) continue;
|
||||
//if(mnpayments.IsScheduled(mnpair.second, nBlockHeight)) continue;
|
||||
|
||||
//it's too new, wait for a cycle
|
||||
if(fFilterSigTime && mnpair.second.sigTime + (nMnCount*2.6*60) > GetAdjustedTime()) continue;
|
||||
@ -727,51 +747,6 @@ bool CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool f
|
||||
return mnInfoRet.fInfoValid;
|
||||
}
|
||||
|
||||
masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<COutPoint> &vecToExclude, int nProtocolVersion)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
|
||||
|
||||
int nCountEnabled = CountEnabled(nProtocolVersion);
|
||||
int nCountNotExcluded = nCountEnabled - vecToExclude.size();
|
||||
|
||||
LogPrintf("CMasternodeMan::FindRandomNotInVec -- %d enabled masternodes, %d masternodes to choose from\n", nCountEnabled, nCountNotExcluded);
|
||||
if(nCountNotExcluded < 1) return masternode_info_t();
|
||||
|
||||
// fill a vector of pointers
|
||||
std::vector<const CMasternode*> vpMasternodesShuffled;
|
||||
for (const auto& mnpair : mapMasternodes) {
|
||||
vpMasternodesShuffled.push_back(&mnpair.second);
|
||||
}
|
||||
|
||||
FastRandomContext insecure_rand;
|
||||
// shuffle pointers
|
||||
std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecure_rand);
|
||||
bool fExclude;
|
||||
|
||||
// loop through
|
||||
for (const auto& pmn : vpMasternodesShuffled) {
|
||||
if(pmn->nProtocolVersion < nProtocolVersion || !pmn->IsEnabled()) continue;
|
||||
fExclude = false;
|
||||
for (const auto& outpointToExclude : vecToExclude) {
|
||||
if(pmn->outpoint == outpointToExclude) {
|
||||
fExclude = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(fExclude) continue;
|
||||
if (deterministicMNManager->IsDIP3Active() && !deterministicMNManager->HasValidMNCollateralAtChainTip(pmn->outpoint))
|
||||
continue;
|
||||
// found the one not in vecToExclude
|
||||
LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- found, masternode=%s\n", pmn->outpoint.ToStringShort());
|
||||
return pmn->GetInfo();
|
||||
}
|
||||
|
||||
LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- failed\n");
|
||||
return masternode_info_t();
|
||||
}
|
||||
|
||||
std::map<COutPoint, CMasternode> CMasternodeMan::GetFullMasternodeMap()
|
||||
{
|
||||
LOCK(cs);
|
||||
@ -791,33 +766,18 @@ std::map<COutPoint, CMasternode> CMasternodeMan::GetFullMasternodeMap()
|
||||
}
|
||||
}
|
||||
|
||||
bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeMan::score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol)
|
||||
bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeMan::score_pair_vec_t& vecMasternodeScoresRet)
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
|
||||
vecMasternodeScoresRet.clear();
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto scores = mnList.CalculateScores(nBlockHash);
|
||||
for (const auto& p : scores) {
|
||||
auto* mn = Find(p.second->collateralOutpoint);
|
||||
vecMasternodeScoresRet.emplace_back(p.first, mn);
|
||||
}
|
||||
} else {
|
||||
if (!masternodeSync.IsMasternodeListSynced())
|
||||
return false;
|
||||
|
||||
if (mapMasternodes.empty())
|
||||
return false;
|
||||
|
||||
// calculate scores
|
||||
for (const auto& mnpair : mapMasternodes) {
|
||||
if (mnpair.second.nProtocolVersion >= nMinProtocol) {
|
||||
vecMasternodeScoresRet.push_back(std::make_pair(mnpair.second.CalculateScore(nBlockHash), &mnpair.second));
|
||||
}
|
||||
}
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto scores = mnList.CalculateScores(nBlockHash);
|
||||
for (const auto& p : scores) {
|
||||
vecMasternodeScoresRet.emplace_back(p.first, p.second);
|
||||
}
|
||||
|
||||
sort(vecMasternodeScoresRet.rbegin(), vecMasternodeScoresRet.rend(), CompareScoreMN());
|
||||
return !vecMasternodeScoresRet.empty();
|
||||
}
|
||||
@ -845,13 +805,13 @@ bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet,
|
||||
LOCK(cs);
|
||||
|
||||
score_pair_vec_t vecMasternodeScores;
|
||||
if (!GetMasternodeScores(blockHashRet, vecMasternodeScores, nMinProtocol))
|
||||
if (!GetMasternodeScores(blockHashRet, vecMasternodeScores))
|
||||
return false;
|
||||
|
||||
int nRank = 0;
|
||||
for (const auto& scorePair : vecMasternodeScores) {
|
||||
nRank++;
|
||||
if(scorePair.second->outpoint == outpoint) {
|
||||
if(scorePair.second->collateralOutpoint == outpoint) {
|
||||
nRankRet = nRank;
|
||||
return true;
|
||||
}
|
||||
@ -877,13 +837,13 @@ bool CMasternodeMan::GetMasternodeRanks(CMasternodeMan::rank_pair_vec_t& vecMast
|
||||
LOCK(cs);
|
||||
|
||||
score_pair_vec_t vecMasternodeScores;
|
||||
if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol))
|
||||
if (!GetMasternodeScores(nBlockHash, vecMasternodeScores))
|
||||
return false;
|
||||
|
||||
int nRank = 0;
|
||||
for (const auto& scorePair : vecMasternodeScores) {
|
||||
nRank++;
|
||||
vecMasternodeRanksRet.push_back(std::make_pair(nRank, *scorePair.second));
|
||||
vecMasternodeRanksRet.push_back(std::make_pair(nRank, scorePair.second));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -891,17 +851,17 @@ bool CMasternodeMan::GetMasternodeRanks(CMasternodeMan::rank_pair_vec_t& vecMast
|
||||
|
||||
void CMasternodeMan::ProcessMasternodeConnections(CConnman& connman)
|
||||
{
|
||||
std::vector<masternode_info_t> vecMnInfo; // will be empty when no wallet
|
||||
std::vector<CDeterministicMNCPtr> vecDmns; // will be empty when no wallet
|
||||
#ifdef ENABLE_WALLET
|
||||
privateSendClient.GetMixingMasternodesInfo(vecMnInfo);
|
||||
privateSendClient.GetMixingMasternodesInfo(vecDmns);
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
connman.ForEachNode(CConnman::AllNodes, [&vecMnInfo](CNode* pnode) {
|
||||
connman.ForEachNode(CConnman::AllNodes, [&](CNode* pnode) {
|
||||
if (pnode->fMasternode) {
|
||||
#ifdef ENABLE_WALLET
|
||||
bool fFound = false;
|
||||
for (const auto& mnInfo : vecMnInfo) {
|
||||
if (pnode->addr == mnInfo.addr) {
|
||||
for (const auto& dmn : vecDmns) {
|
||||
if (pnode->addr == dmn->pdmnState->addr) {
|
||||
fFound = true;
|
||||
break;
|
||||
}
|
||||
@ -1213,7 +1173,7 @@ void CMasternodeMan::DoFullVerificationStep(CConnman& connman)
|
||||
(int)MAX_POSE_RANK);
|
||||
return;
|
||||
}
|
||||
if(rankPair.second.outpoint == activeMasternodeInfo.outpoint) {
|
||||
if(rankPair.second->collateralOutpoint == activeMasternodeInfo.outpoint) {
|
||||
nMyRank = rankPair.first;
|
||||
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Found self at rank %d/%d, verifying up to %d masternodes\n",
|
||||
nMyRank, nRanksTotal, (int)MAX_POSE_CONNECTIONS);
|
||||
@ -1231,20 +1191,20 @@ void CMasternodeMan::DoFullVerificationStep(CConnman& connman)
|
||||
|
||||
auto it = vecMasternodeRanks.begin() + nOffset;
|
||||
while(it != vecMasternodeRanks.end()) {
|
||||
if(it->second.IsPoSeVerified() || it->second.IsPoSeBanned()) {
|
||||
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Already %s%s%s masternode %s address %s, skipping...\n",
|
||||
it->second.IsPoSeVerified() ? "verified" : "",
|
||||
it->second.IsPoSeVerified() && it->second.IsPoSeBanned() ? " and " : "",
|
||||
it->second.IsPoSeBanned() ? "banned" : "",
|
||||
it->second.outpoint.ToStringShort(), it->second.addr.ToString());
|
||||
nOffset += MAX_POSE_CONNECTIONS;
|
||||
if(nOffset >= (int)vecMasternodeRanks.size()) break;
|
||||
it += MAX_POSE_CONNECTIONS;
|
||||
continue;
|
||||
}
|
||||
// if(it->second.IsPoSeVerified() || it->second.IsPoSeBanned()) {
|
||||
// LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Already %s%s%s masternode %s address %s, skipping...\n",
|
||||
// it->second.IsPoSeVerified() ? "verified" : "",
|
||||
// it->second.IsPoSeVerified() && it->second.IsPoSeBanned() ? " and " : "",
|
||||
// it->second.IsPoSeBanned() ? "banned" : "",
|
||||
// it->second.outpoint.ToStringShort(), it->second.addr.ToString());
|
||||
// nOffset += MAX_POSE_CONNECTIONS;
|
||||
// if(nOffset >= (int)vecMasternodeRanks.size()) break;
|
||||
// it += MAX_POSE_CONNECTIONS;
|
||||
// continue;
|
||||
// }
|
||||
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Verifying masternode %s rank %d/%d address %s\n",
|
||||
it->second.outpoint.ToStringShort(), it->first, nRanksTotal, it->second.addr.ToString());
|
||||
CAddress addr = CAddress(it->second.addr, NODE_NETWORK);
|
||||
it->second->collateralOutpoint.ToStringShort(), it->first, nRanksTotal, it->second->pdmnState->addr.ToString());
|
||||
CAddress addr = CAddress(it->second->pdmnState->addr, NODE_NETWORK);
|
||||
if(CheckVerifyRequestAddr(addr, connman)) {
|
||||
vAddr.push_back(addr);
|
||||
if((int)vAddr.size() >= MAX_POSE_CONNECTIONS) break;
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "masternode.h"
|
||||
#include "sync.h"
|
||||
|
||||
#include "evo/deterministicmns.h"
|
||||
|
||||
class CMasternodeMan;
|
||||
class CConnman;
|
||||
|
||||
@ -16,9 +18,9 @@ extern CMasternodeMan mnodeman;
|
||||
class CMasternodeMan
|
||||
{
|
||||
public:
|
||||
typedef std::pair<arith_uint256, const CMasternode*> score_pair_t;
|
||||
typedef std::pair<arith_uint256, CDeterministicMNCPtr> score_pair_t;
|
||||
typedef std::vector<score_pair_t> score_pair_vec_t;
|
||||
typedef std::pair<int, const CMasternode> rank_pair_t;
|
||||
typedef std::pair<int, CDeterministicMNCPtr> rank_pair_t;
|
||||
typedef std::vector<rank_pair_t> rank_pair_vec_t;
|
||||
|
||||
private:
|
||||
@ -80,7 +82,7 @@ private:
|
||||
/// Find an entry
|
||||
CMasternode* Find(const COutPoint& outpoint);
|
||||
|
||||
bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol = 0);
|
||||
bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet);
|
||||
|
||||
void SyncSingle(CNode* pnode, const COutPoint& outpoint, CConnman& connman);
|
||||
void SyncAll(CNode* pnode, CConnman& connman);
|
||||
@ -137,8 +139,10 @@ public:
|
||||
void AskForMN(CNode *pnode, const COutPoint& outpoint, CConnman& connman);
|
||||
|
||||
bool PoSeBan(const COutPoint &outpoint);
|
||||
bool IsValidForMixingTxes(const COutPoint &outpoint);
|
||||
bool AllowMixing(const COutPoint &outpoint);
|
||||
bool DisallowMixing(const COutPoint &outpoint);
|
||||
int64_t GetLastDsq(const COutPoint &outpoint);
|
||||
|
||||
/// Check all Masternodes
|
||||
void Check();
|
||||
@ -180,9 +184,6 @@ public:
|
||||
/// Same as above but use current block height
|
||||
bool GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet);
|
||||
|
||||
/// Find a random entry
|
||||
masternode_info_t FindRandomNotInVec(const std::vector<COutPoint> &vecToExclude, int nProtocolVersion = -1);
|
||||
|
||||
std::map<COutPoint, CMasternode> GetFullMasternodeMap();
|
||||
|
||||
bool GetMasternodeRanks(rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight = -1, int nMinProtocol = 0);
|
||||
|
@ -2079,21 +2079,20 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
return true; // not an error
|
||||
}
|
||||
|
||||
CMasternode mn;
|
||||
|
||||
if(!mnodeman.Get(dstx.masternodeOutpoint, mn)) {
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(dstx.masternodeOutpoint);
|
||||
if(!dmn) {
|
||||
LogPrint("privatesend", "DSTX -- Can't find masternode %s to verify %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!mn.IsValidForMixingTxes()) {
|
||||
if(!mnodeman.IsValidForMixingTxes(dstx.masternodeOutpoint)) {
|
||||
LogPrint("privatesend", "DSTX -- Masternode %s is sending too many transactions %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString());
|
||||
return true;
|
||||
// TODO: Not an error? Could it be that someone is relaying old DSTXes
|
||||
// we have no idea about (e.g we were offline)? How to handle them?
|
||||
}
|
||||
|
||||
if (!dstx.CheckSignature(mn.legacyKeyIDOperator, mn.blsPubKeyOperator)) {
|
||||
if (!dstx.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
|
||||
LogPrint("privatesend", "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString());
|
||||
return false;
|
||||
}
|
||||
|
@ -61,12 +61,13 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
|
||||
|
||||
if (dsq.IsExpired()) return;
|
||||
|
||||
masternode_info_t infoMn;
|
||||
if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, infoMn)) return;
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
|
||||
if (!dmn) return;
|
||||
|
||||
if (!dsq.CheckSignature(infoMn.legacyKeyIDOperator, infoMn.blsPubKeyOperator)) {
|
||||
// we probably have outdated info
|
||||
mnodeman.AskForMN(pfrom, dsq.masternodeOutpoint, connman);
|
||||
if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->id, 10);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,9 +75,9 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
|
||||
if (dsq.fReady) {
|
||||
LOCK(cs_deqsessions);
|
||||
for (auto& session : deqSessions) {
|
||||
masternode_info_t mnMixing;
|
||||
if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing.addr == infoMn.addr && session.GetState() == POOL_STATE_QUEUE) {
|
||||
LogPrint("privatesend", "DSQUEUE -- PrivateSend queue (%s) is ready on masternode %s\n", dsq.ToString(), infoMn.addr.ToString());
|
||||
CDeterministicMNCPtr mnMixing;
|
||||
if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing->pdmnState->addr == dmn->pdmnState->addr && session.GetState() == POOL_STATE_QUEUE) {
|
||||
LogPrint("privatesend", "DSQUEUE -- PrivateSend queue (%s) is ready on masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
|
||||
session.SubmitDenominate(connman);
|
||||
return;
|
||||
}
|
||||
@ -89,25 +90,26 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
|
||||
for (const auto& q : vecPrivateSendQueue) {
|
||||
if (q.masternodeOutpoint == dsq.masternodeOutpoint) {
|
||||
// no way same mn can send another "not yet ready" dsq this soon
|
||||
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", infoMn.addr.ToString());
|
||||
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->ToString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int nThreshold = infoMn.nLastDsq + mnodeman.CountMasternodes() / 5;
|
||||
LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", infoMn.nLastDsq, nThreshold, mnodeman.nDsqCount);
|
||||
int64_t nLastDsq = mnodeman.GetLastDsq(dsq.masternodeOutpoint);
|
||||
int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5;
|
||||
LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mnodeman.nDsqCount);
|
||||
//don't allow a few nodes to dominate the queuing process
|
||||
if (infoMn.nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) {
|
||||
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", infoMn.addr.ToString());
|
||||
if (nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) {
|
||||
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->proTxHash.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mnodeman.AllowMixing(dsq.masternodeOutpoint)) return;
|
||||
|
||||
LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), infoMn.addr.ToString());
|
||||
LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
|
||||
for (auto& session : deqSessions) {
|
||||
masternode_info_t mnMixing;
|
||||
if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing.outpoint == dsq.masternodeOutpoint) {
|
||||
CDeterministicMNCPtr mnMixing;
|
||||
if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing->collateralOutpoint == dsq.masternodeOutpoint) {
|
||||
dsq.fTried = true;
|
||||
}
|
||||
}
|
||||
@ -139,8 +141,8 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string&
|
||||
return;
|
||||
}
|
||||
|
||||
if (!infoMixingMasternode.fInfoValid) return;
|
||||
if (infoMixingMasternode.addr != pfrom->addr) {
|
||||
if (!mixingMasternode) return;
|
||||
if (mixingMasternode->pdmnState->addr != pfrom->addr) {
|
||||
//LogPrintf("DSSTATUSUPDATE -- message doesn't match current Masternode: infoMixingMasternode %s addr %s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString());
|
||||
return;
|
||||
}
|
||||
@ -181,8 +183,8 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string&
|
||||
return;
|
||||
}
|
||||
|
||||
if (!infoMixingMasternode.fInfoValid) return;
|
||||
if (infoMixingMasternode.addr != pfrom->addr) {
|
||||
if (!mixingMasternode) return;
|
||||
if (mixingMasternode->pdmnState->addr != pfrom->addr) {
|
||||
//LogPrintf("DSFINALTX -- message doesn't match current Masternode: infoMixingMasternode %s addr %s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString());
|
||||
return;
|
||||
}
|
||||
@ -208,9 +210,9 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string&
|
||||
return;
|
||||
}
|
||||
|
||||
if (!infoMixingMasternode.fInfoValid) return;
|
||||
if (infoMixingMasternode.addr != pfrom->addr) {
|
||||
LogPrint("privatesend", "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString());
|
||||
if (!mixingMasternode) return;
|
||||
if (mixingMasternode->pdmnState->addr != pfrom->addr) {
|
||||
LogPrint("privatesend", "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", mixingMasternode->pdmnState->addr.ToString(), pfrom->addr.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -258,7 +260,7 @@ void CPrivateSendClientSession::SetNull()
|
||||
// Client side
|
||||
nEntriesCount = 0;
|
||||
fLastEntryAccepted = false;
|
||||
infoMixingMasternode = masternode_info_t();
|
||||
mixingMasternode = nullptr;
|
||||
pendingDsaRequest = CPendingDsaRequest();
|
||||
|
||||
CPrivateSendBaseSession::SetNull();
|
||||
@ -368,22 +370,22 @@ std::string CPrivateSendClientManager::GetSessionDenoms()
|
||||
return strSessionDenoms.empty() ? "N/A" : strSessionDenoms;
|
||||
}
|
||||
|
||||
bool CPrivateSendClientSession::GetMixingMasternodeInfo(masternode_info_t& mnInfoRet) const
|
||||
bool CPrivateSendClientSession::GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const
|
||||
{
|
||||
mnInfoRet = infoMixingMasternode.fInfoValid ? infoMixingMasternode : masternode_info_t();
|
||||
return infoMixingMasternode.fInfoValid;
|
||||
ret = mixingMasternode;
|
||||
return ret != nullptr;
|
||||
}
|
||||
|
||||
bool CPrivateSendClientManager::GetMixingMasternodesInfo(std::vector<masternode_info_t>& vecMnInfoRet) const
|
||||
bool CPrivateSendClientManager::GetMixingMasternodesInfo(std::vector<CDeterministicMNCPtr>& vecDmnsRet) const
|
||||
{
|
||||
LOCK(cs_deqsessions);
|
||||
for (const auto& session : deqSessions) {
|
||||
masternode_info_t mnInfo;
|
||||
if (session.GetMixingMasternodeInfo(mnInfo)) {
|
||||
vecMnInfoRet.push_back(mnInfo);
|
||||
CDeterministicMNCPtr dmn;
|
||||
if (session.GetMixingMasternodeInfo(dmn)) {
|
||||
vecDmnsRet.push_back(dmn);
|
||||
}
|
||||
}
|
||||
return !vecMnInfoRet.empty();
|
||||
return !vecDmnsRet.empty();
|
||||
}
|
||||
|
||||
//
|
||||
@ -578,7 +580,7 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr
|
||||
if (!pwalletMain) return false;
|
||||
|
||||
if (fMasternodeMode || pnode == nullptr) return false;
|
||||
if (!infoMixingMasternode.fInfoValid) return false;
|
||||
if (!mixingMasternode) return false;
|
||||
|
||||
finalMutableTransaction = finalTransactionNew;
|
||||
LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- finalMutableTransaction=%s", finalMutableTransaction.ToString());
|
||||
@ -588,7 +590,7 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr
|
||||
sort(finalMutableTransaction.vout.begin(), finalMutableTransaction.vout.end(), CompareOutputBIP69());
|
||||
|
||||
if (finalMutableTransaction.GetHash() != finalTransactionNew.GetHash()) {
|
||||
LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- WARNING! Masternode %s is not BIP69 compliant!\n", infoMixingMasternode.outpoint.ToStringShort());
|
||||
LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- WARNING! Masternode %s is not BIP69 compliant!\n", mixingMasternode->proTxHash.ToString());
|
||||
UnlockCoins();
|
||||
keyHolderStorage.ReturnAll();
|
||||
SetNull();
|
||||
@ -832,7 +834,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mnodeman.size() == 0) {
|
||||
if (deterministicMNManager->GetListAtChainTip().GetValidMNsCount() == 0) {
|
||||
LogPrint("privatesend", "CPrivateSendClientSession::DoAutomaticDenominating -- No Masternodes detected\n");
|
||||
strAutoDenomResult = _("No Masternodes detected.");
|
||||
return false;
|
||||
@ -952,7 +954,7 @@ bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool
|
||||
return false;
|
||||
}
|
||||
|
||||
int nMnCountEnabled = mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION);
|
||||
int nMnCountEnabled = deterministicMNManager->GetListAtChainTip().GetValidMNsCount();
|
||||
|
||||
// If we've used 90% of the Masternode list then drop the oldest first ~30%
|
||||
int nThreshold_high = nMnCountEnabled * 0.9;
|
||||
@ -990,31 +992,65 @@ void CPrivateSendClientManager::AddUsedMasternode(const COutPoint& outpointMn)
|
||||
vecMasternodesUsed.push_back(outpointMn);
|
||||
}
|
||||
|
||||
masternode_info_t CPrivateSendClientManager::GetNotUsedMasternode()
|
||||
CDeterministicMNCPtr CPrivateSendClientManager::GetRandomNotUsedMasternode()
|
||||
{
|
||||
return mnodeman.FindRandomNotInVec(vecMasternodesUsed, MIN_PRIVATESEND_PEER_PROTO_VERSION);
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
int nCountEnabled = mnList.GetValidMNsCount();
|
||||
int nCountNotExcluded = nCountEnabled - vecMasternodesUsed.size();
|
||||
|
||||
LogPrintf("CPrivateSendClientManager::%s -- %d enabled masternodes, %d masternodes to choose from\n", __func__, nCountEnabled, nCountNotExcluded);
|
||||
if(nCountNotExcluded < 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// fill a vector
|
||||
std::vector<CDeterministicMNCPtr> vpMasternodesShuffled;
|
||||
vpMasternodesShuffled.reserve((size_t)nCountEnabled);
|
||||
mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
|
||||
vpMasternodesShuffled.emplace_back(dmn);
|
||||
});
|
||||
|
||||
FastRandomContext insecure_rand;
|
||||
// shuffle pointers
|
||||
std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecure_rand);
|
||||
|
||||
std::set<COutPoint> excludeSet(vecMasternodesUsed.begin(), vecMasternodesUsed.end());
|
||||
|
||||
// loop through
|
||||
for (const auto& dmn : vpMasternodesShuffled) {
|
||||
if (excludeSet.count(dmn->collateralOutpoint)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LogPrint("masternode", "CPrivateSendClientManager::%s -- found, masternode=%s\n", __func__, dmn->collateralOutpoint.ToStringShort());
|
||||
return dmn;
|
||||
}
|
||||
|
||||
LogPrint("masternode", "CPrivateSendClientManager::%s -- failed\n", __func__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman)
|
||||
{
|
||||
if (!pwalletMain) return false;
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
std::vector<CAmount> vecStandardDenoms = CPrivateSend::GetStandardDenominations();
|
||||
// Look through the queues and see if anything matches
|
||||
CPrivateSendQueue dsq;
|
||||
while (privateSendClient.GetQueueItemAndTry(dsq)) {
|
||||
masternode_info_t infoMn;
|
||||
auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
|
||||
|
||||
if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, infoMn)) {
|
||||
if (!dmn) {
|
||||
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- dsq masternode is not in masternode list, masternode=%s\n", dsq.masternodeOutpoint.ToStringShort());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (infoMn.nProtocolVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) continue;
|
||||
|
||||
// skip next mn payments winners
|
||||
if (mnpayments.IsScheduled(infoMn, 0)) {
|
||||
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping winner, masternode=%s\n", infoMn.outpoint.ToStringShort());
|
||||
if (mnpayments.IsScheduled(dmn, 0)) {
|
||||
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString());
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1042,20 +1078,20 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize
|
||||
|
||||
privateSendClient.AddUsedMasternode(dsq.masternodeOutpoint);
|
||||
|
||||
if (connman.IsMasternodeOrDisconnectRequested(infoMn.addr)) {
|
||||
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", infoMn.addr.ToString());
|
||||
if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) {
|
||||
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString());
|
||||
continue;
|
||||
}
|
||||
|
||||
nSessionDenom = dsq.nDenom;
|
||||
infoMixingMasternode = infoMn;
|
||||
pendingDsaRequest = CPendingDsaRequest(infoMn.addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
|
||||
connman.AddPendingMasternode(infoMn.addr);
|
||||
mixingMasternode = dmn;
|
||||
pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
|
||||
connman.AddPendingMasternode(dmn->pdmnState->addr);
|
||||
// TODO: add new state POOL_STATE_CONNECTING and bump MIN_PRIVATESEND_PEER_PROTO_VERSION
|
||||
SetState(POOL_STATE_QUEUE);
|
||||
nTimeLastSuccessfulStep = GetTime();
|
||||
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- pending connection (from queue): nSessionDenom: %d (%s), addr=%s\n",
|
||||
nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), infoMn.addr.ToString());
|
||||
nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), dmn->pdmnState->addr.ToString());
|
||||
strAutoDenomResult = _("Trying to connect...");
|
||||
return true;
|
||||
}
|
||||
@ -1068,7 +1104,7 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc
|
||||
if (!pwalletMain) return false;
|
||||
|
||||
int nTries = 0;
|
||||
int nMnCount = mnodeman.CountMasternodes();
|
||||
int nMnCount = deterministicMNManager->GetListAtChainTip().GetValidMNsCount();
|
||||
|
||||
// ** find the coins we'll use
|
||||
std::vector<CTxIn> vecTxIn;
|
||||
@ -1082,39 +1118,40 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc
|
||||
|
||||
// otherwise, try one randomly
|
||||
while (nTries < 10) {
|
||||
masternode_info_t infoMn = privateSendClient.GetNotUsedMasternode();
|
||||
auto dmn = privateSendClient.GetRandomNotUsedMasternode();
|
||||
|
||||
if (!infoMn.fInfoValid) {
|
||||
if (!dmn) {
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- Can't find random masternode!\n");
|
||||
strAutoDenomResult = _("Can't find random Masternode.");
|
||||
return false;
|
||||
}
|
||||
|
||||
privateSendClient.AddUsedMasternode(infoMn.outpoint);
|
||||
privateSendClient.AddUsedMasternode(dmn->collateralOutpoint);
|
||||
|
||||
// skip next mn payments winners
|
||||
if (mnpayments.IsScheduled(infoMn, 0)) {
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping winner, masternode=%s\n", infoMn.outpoint.ToStringShort());
|
||||
if (mnpayments.IsScheduled(dmn, 0)) {
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString());
|
||||
nTries++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (infoMn.nLastDsq != 0 && infoMn.nLastDsq + nMnCount / 5 > mnodeman.nDsqCount) {
|
||||
int64_t nLastDsq = mnodeman.GetLastDsq(dmn->collateralOutpoint);
|
||||
if (nLastDsq != 0 && nLastDsq + nMnCount / 5 > mnodeman.nDsqCount) {
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- Too early to mix on this masternode!"
|
||||
" masternode=%s addr=%s nLastDsq=%d CountEnabled/5=%d nDsqCount=%d\n",
|
||||
infoMn.outpoint.ToStringShort(), infoMn.addr.ToString(), infoMn.nLastDsq,
|
||||
dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString(), nLastDsq,
|
||||
nMnCount / 5, mnodeman.nDsqCount);
|
||||
nTries++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (connman.IsMasternodeOrDisconnectRequested(infoMn.addr)) {
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", infoMn.addr.ToString());
|
||||
if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) {
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString());
|
||||
nTries++;
|
||||
continue;
|
||||
}
|
||||
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, infoMn.addr.ToString());
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, dmn->pdmnState->addr.ToString());
|
||||
|
||||
std::vector<CAmount> vecAmounts;
|
||||
pwalletMain->ConvertList(vecTxIn, vecAmounts);
|
||||
@ -1123,14 +1160,14 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc
|
||||
nSessionDenom = CPrivateSend::GetDenominationsByAmounts(vecAmounts);
|
||||
}
|
||||
|
||||
infoMixingMasternode = infoMn;
|
||||
connman.AddPendingMasternode(infoMn.addr);
|
||||
pendingDsaRequest = CPendingDsaRequest(infoMn.addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
|
||||
mixingMasternode = dmn;
|
||||
connman.AddPendingMasternode(dmn->pdmnState->addr);
|
||||
pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
|
||||
// TODO: add new state POOL_STATE_CONNECTING and bump MIN_PRIVATESEND_PEER_PROTO_VERSION
|
||||
SetState(POOL_STATE_QUEUE);
|
||||
nTimeLastSuccessfulStep = GetTime();
|
||||
LogPrintf("CPrivateSendClientSession::StartNewQueue -- pending connection, nSessionDenom: %d (%s), addr=%s\n",
|
||||
nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), infoMn.addr.ToString());
|
||||
nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), dmn->pdmnState->addr.ToString());
|
||||
strAutoDenomResult = _("Trying to connect...");
|
||||
return true;
|
||||
}
|
||||
@ -1596,9 +1633,9 @@ bool CPrivateSendClientSession::CreateDenominated(const CompactTallyItem& tallyI
|
||||
|
||||
void CPrivateSendClientSession::RelayIn(const CPrivateSendEntry& entry, CConnman& connman)
|
||||
{
|
||||
if (!infoMixingMasternode.fInfoValid) return;
|
||||
if (!mixingMasternode) return;
|
||||
|
||||
connman.ForNode(infoMixingMasternode.addr, [&entry, &connman](CNode* pnode) {
|
||||
connman.ForNode(mixingMasternode->pdmnState->addr, [&entry, &connman](CNode* pnode) {
|
||||
LogPrintf("CPrivateSendClientSession::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToString());
|
||||
CNetMsgMaker msgMaker(pnode->GetSendVersion());
|
||||
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSVIN, entry));
|
||||
|
@ -10,8 +10,11 @@
|
||||
#include "privatesend.h"
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
#include "evo/deterministicmns.h"
|
||||
|
||||
class CPrivateSendClientManager;
|
||||
class CConnman;
|
||||
class CNode;
|
||||
|
||||
static const int DENOMS_COUNT_MAX = 100;
|
||||
|
||||
@ -92,7 +95,7 @@ private:
|
||||
std::string strLastMessage;
|
||||
std::string strAutoDenomResult;
|
||||
|
||||
masternode_info_t infoMixingMasternode;
|
||||
CDeterministicMNCPtr mixingMasternode;
|
||||
CMutableTransaction txMyCollateral; // client side collateral
|
||||
CPendingDsaRequest pendingDsaRequest;
|
||||
|
||||
@ -139,7 +142,7 @@ public:
|
||||
fLastEntryAccepted(false),
|
||||
strLastMessage(),
|
||||
strAutoDenomResult(),
|
||||
infoMixingMasternode(),
|
||||
mixingMasternode(),
|
||||
txMyCollateral(),
|
||||
pendingDsaRequest(),
|
||||
keyHolderStorage()
|
||||
@ -154,7 +157,7 @@ public:
|
||||
|
||||
std::string GetStatus(bool fWaitForBlock);
|
||||
|
||||
bool GetMixingMasternodeInfo(masternode_info_t& mnInfoRet) const;
|
||||
bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const;
|
||||
|
||||
/// Passively run mixing in the background according to the configuration in settings
|
||||
bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false);
|
||||
@ -235,7 +238,7 @@ public:
|
||||
std::string GetStatuses();
|
||||
std::string GetSessionDenoms();
|
||||
|
||||
bool GetMixingMasternodesInfo(std::vector<masternode_info_t>& vecMnInfoRet) const;
|
||||
bool GetMixingMasternodesInfo(std::vector<CDeterministicMNCPtr>& vecDmnsRet) const;
|
||||
|
||||
/// Passively run mixing in the background according to the configuration in settings
|
||||
bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false);
|
||||
@ -245,7 +248,7 @@ public:
|
||||
void ProcessPendingDsaRequest(CConnman& connman);
|
||||
|
||||
void AddUsedMasternode(const COutPoint& outpointMn);
|
||||
masternode_info_t GetNotUsedMasternode();
|
||||
CDeterministicMNCPtr GetRandomNotUsedMasternode();
|
||||
|
||||
void UpdatedSuccessBlock();
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "init.h"
|
||||
#include "masternode-sync.h"
|
||||
#include "masternodeman.h"
|
||||
#include "net_processing.h"
|
||||
#include "netmessagemaker.h"
|
||||
#include "script/interpreter.h"
|
||||
#include "txmempool.h"
|
||||
@ -44,8 +45,9 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
|
||||
LogPrint("privatesend", "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CPrivateSend::GetDenominationsToString(dsa.nDenom), dsa.txCollateral.ToString());
|
||||
|
||||
masternode_info_t mnInfo;
|
||||
if (!mnodeman.GetMasternodeInfo(activeMasternodeInfo.outpoint, mnInfo)) {
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint);
|
||||
if (!dmn) {
|
||||
PushStatus(pfrom, STATUS_REJECTED, ERR_MN_LIST, connman);
|
||||
return;
|
||||
}
|
||||
@ -65,7 +67,8 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
}
|
||||
}
|
||||
|
||||
if (mnInfo.nLastDsq != 0 && mnInfo.nLastDsq + mnodeman.CountMasternodes() / 5 > mnodeman.nDsqCount) {
|
||||
int64_t nLastDsq = mnodeman.GetLastDsq(dmn->collateralOutpoint);
|
||||
if (nLastDsq != 0 && nLastDsq + mnList.GetValidMNsCount() / 5 > mnodeman.nDsqCount) {
|
||||
LogPrintf("DSACCEPT -- last dsq too recent, must wait: addr=%s\n", pfrom->addr.ToString());
|
||||
PushStatus(pfrom, STATUS_REJECTED, ERR_RECENT, connman);
|
||||
return;
|
||||
@ -111,12 +114,13 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
|
||||
if (dsq.IsExpired()) return;
|
||||
|
||||
masternode_info_t mnInfo;
|
||||
if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, mnInfo)) return;
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
|
||||
if (!dmn) return;
|
||||
|
||||
if (!dsq.CheckSignature(mnInfo.legacyKeyIDOperator, mnInfo.blsPubKeyOperator)) {
|
||||
// we probably have outdated info
|
||||
mnodeman.AskForMN(pfrom, dsq.masternodeOutpoint, connman);
|
||||
if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->id, 10);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -124,21 +128,22 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
for (const auto& q : vecPrivateSendQueue) {
|
||||
if (q.masternodeOutpoint == dsq.masternodeOutpoint) {
|
||||
// no way same mn can send another "not yet ready" dsq this soon
|
||||
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", mnInfo.addr.ToString());
|
||||
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->addr.ToString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int nThreshold = mnInfo.nLastDsq + mnodeman.CountMasternodes() / 5;
|
||||
LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", mnInfo.nLastDsq, nThreshold, mnodeman.nDsqCount);
|
||||
int64_t nLastDsq = mnodeman.GetLastDsq(dmn->collateralOutpoint);
|
||||
int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5;
|
||||
LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mnodeman.nDsqCount);
|
||||
//don't allow a few nodes to dominate the queuing process
|
||||
if (mnInfo.nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) {
|
||||
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", mnInfo.addr.ToString());
|
||||
if (nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) {
|
||||
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->pdmnState->addr.ToString());
|
||||
return;
|
||||
}
|
||||
mnodeman.AllowMixing(dsq.masternodeOutpoint);
|
||||
|
||||
LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), mnInfo.addr.ToString());
|
||||
LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
|
||||
vecPrivateSendQueue.push_back(dsq);
|
||||
dsq.Relay(connman);
|
||||
}
|
||||
|
@ -50,77 +50,26 @@ bool CPrivateSendQueue::Sign()
|
||||
{
|
||||
if (!fMasternodeMode) return false;
|
||||
|
||||
std::string strError = "";
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
sig.GetBuf(vchSig);
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) {
|
||||
LogPrintf("CPrivateSendQueue::Sign -- SignHash() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) {
|
||||
LogPrintf("CPrivateSendQueue::Sign -- VerifyHash() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = CTxIn(masternodeOutpoint).ToString() +
|
||||
std::to_string(nDenom) +
|
||||
std::to_string(nTime) +
|
||||
std::to_string(fReady);
|
||||
|
||||
if (!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("CPrivateSendQueue::Sign -- SignMessage() failed, %s\n", ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) {
|
||||
LogPrintf("CPrivateSendQueue::Sign -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
uint256 hash = GetSignatureHash();
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
sig.GetBuf(vchSig);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPrivateSendQueue::CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const
|
||||
bool CPrivateSendQueue::CheckSignature(const CBLSPublicKey& blsPubKey) const
|
||||
{
|
||||
std::string strError = "";
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchSig);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
|
||||
// we don't care about queues with old signature format
|
||||
LogPrintf("CPrivateSendQueue::CheckSignature -- VerifyHash() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = CTxIn(masternodeOutpoint).ToString() +
|
||||
std::to_string(nDenom) +
|
||||
std::to_string(nTime) +
|
||||
std::to_string(fReady);
|
||||
|
||||
if (!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
|
||||
LogPrintf("CPrivateSendQueue::CheckSignature -- Got bad Masternode queue signature: %s; error: %s\n", ToString(), strError);
|
||||
return false;
|
||||
}
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchSig);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -145,73 +94,28 @@ bool CPrivateSendBroadcastTx::Sign()
|
||||
{
|
||||
if (!fMasternodeMode) return false;
|
||||
|
||||
std::string strError = "";
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
sig.GetBuf(vchSig);
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) {
|
||||
LogPrintf("CPrivateSendBroadcastTx::Sign -- SignHash() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) {
|
||||
LogPrintf("CPrivateSendBroadcastTx::Sign -- VerifyHash() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = tx->GetHash().ToString() + std::to_string(sigTime);
|
||||
|
||||
if (!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("CPrivateSendBroadcastTx::Sign -- SignMessage() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) {
|
||||
LogPrintf("CPrivateSendBroadcastTx::Sign -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
sig.GetBuf(vchSig);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPrivateSendBroadcastTx::CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const
|
||||
bool CPrivateSendBroadcastTx::CheckSignature(const CBLSPublicKey& blsPubKey) const
|
||||
{
|
||||
std::string strError = "";
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchSig);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
|
||||
// we don't care about dstxes with old signature format
|
||||
LogPrintf("CPrivateSendBroadcastTx::CheckSignature -- VerifyHash() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = tx->GetHash().ToString() + std::to_string(sigTime);
|
||||
|
||||
if (!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) {
|
||||
LogPrintf("CPrivateSendBroadcastTx::CheckSignature -- Got bad dstx signature, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchSig);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -225,7 +225,7 @@ public:
|
||||
*/
|
||||
bool Sign();
|
||||
/// Check if we have a valid Masternode address
|
||||
bool CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const;
|
||||
bool CheckSignature(const CBLSPublicKey& blsPubKey) const;
|
||||
|
||||
bool Relay(CConnman& connman);
|
||||
|
||||
@ -306,7 +306,7 @@ public:
|
||||
uint256 GetSignatureHash() const;
|
||||
|
||||
bool Sign();
|
||||
bool CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const;
|
||||
bool CheckSignature(const CBLSPublicKey& blsPubKey) const;
|
||||
|
||||
void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; }
|
||||
bool IsExpired(int nHeight);
|
||||
|
@ -83,10 +83,10 @@ int ClientModel::getNumConnections(unsigned int flags) const
|
||||
QString ClientModel::getMasternodeCountString() const
|
||||
{
|
||||
// return tr("Total: %1 (PS compatible: %2 / Enabled: %3) (IPv4: %4, IPv6: %5, TOR: %6)").arg(QString::number((int)mnodeman.size()))
|
||||
return tr("Total: %1 (PS compatible: %2 / Enabled: %3)")
|
||||
.arg(QString::number((int)mnodeman.CountMasternodes(0)))
|
||||
.arg(QString::number((int)mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)))
|
||||
.arg(QString::number((int)mnodeman.CountEnabled()));
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
return tr("Total: %1 (Enabled: %2)")
|
||||
.arg(QString::number((int)mnList.GetAllMNsCount()))
|
||||
.arg(QString::number((int)mnList.GetValidMNsCount()));
|
||||
// .arg(QString::number((int)mnodeman.CountByIP(NET_IPV4)))
|
||||
// .arg(QString::number((int)mnodeman.CountByIP(NET_IPV6)))
|
||||
// .arg(QString::number((int)mnodeman.CountByIP(NET_TOR)));
|
||||
|
@ -261,7 +261,8 @@ UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Must wait for client to sync with masternode network. Try again in a minute or so.");
|
||||
}
|
||||
|
||||
bool fMnFound = mnodeman.Has(activeMasternodeInfo.outpoint);
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
bool fMnFound = mnList.HasValidMNByCollateral(activeMasternodeInfo.outpoint);
|
||||
|
||||
DBG( std::cout << "gobject: submit activeMasternodeInfo.keyIDOperator = " << activeMasternodeInfo.legacyKeyIDOperator.ToString()
|
||||
<< ", outpoint = " << activeMasternodeInfo.outpoint.ToStringShort()
|
||||
@ -412,10 +413,9 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request)
|
||||
UniValue statusObj(UniValue::VOBJ);
|
||||
UniValue returnObj(UniValue::VOBJ);
|
||||
|
||||
CMasternode mn;
|
||||
bool fMnFound = mnodeman.Get(activeMasternodeInfo.outpoint, mn);
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(activeMasternodeInfo.outpoint);
|
||||
|
||||
if (!fMnFound) {
|
||||
if (!dmn) {
|
||||
nFailed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
statusObj.push_back(Pair("errorMessage", "Can't find masternode by collateral output"));
|
||||
@ -425,19 +425,16 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request)
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
CGovernanceVote vote(mn.outpoint, hash, eVoteSignal, eVoteOutcome);
|
||||
CGovernanceVote vote(dmn->collateralOutpoint, hash, eVoteSignal, eVoteOutcome);
|
||||
|
||||
bool signSuccess = false;
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && eVoteSignal == VOTE_SIGNAL_FUNDING) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf for proposals when deterministic masternodes are active");
|
||||
}
|
||||
if (activeMasternodeInfo.blsKeyOperator) {
|
||||
signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator);
|
||||
}
|
||||
} else {
|
||||
signSuccess = vote.Sign(activeMasternodeInfo.legacyKeyOperator, activeMasternodeInfo.legacyKeyIDOperator);
|
||||
if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && eVoteSignal == VOTE_SIGNAL_FUNDING) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf for proposals");
|
||||
}
|
||||
if (activeMasternodeInfo.blsKeyOperator) {
|
||||
signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator);
|
||||
}
|
||||
|
||||
if (!signSuccess) {
|
||||
nFailed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
@ -466,9 +463,9 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request)
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
UniValue VoteWithMasternodeList(const std::vector<CMasternodeConfig::CMasternodeEntry>& entries,
|
||||
const uint256& hash, vote_signal_enum_t eVoteSignal,
|
||||
vote_outcome_enum_t eVoteOutcome)
|
||||
UniValue VoteWithMasternodes(const std::map<uint256, CKey>& keys,
|
||||
const uint256& hash, vote_signal_enum_t eVoteSignal,
|
||||
vote_outcome_enum_t eVoteOutcome)
|
||||
{
|
||||
int govObjType;
|
||||
{
|
||||
@ -483,59 +480,31 @@ UniValue VoteWithMasternodeList(const std::vector<CMasternodeConfig::CMasternode
|
||||
int nSuccessful = 0;
|
||||
int nFailed = 0;
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
UniValue resultsObj(UniValue::VOBJ);
|
||||
|
||||
for (const auto& mne : entries) {
|
||||
CPubKey pubKeyOperator;
|
||||
CKey keyOperator;
|
||||
for (const auto& p : keys) {
|
||||
const auto& proTxHash = p.first;
|
||||
const auto& key = p.second;
|
||||
|
||||
UniValue statusObj(UniValue::VOBJ);
|
||||
|
||||
if (!CMessageSigner::GetKeysFromSecret(mne.getPrivKey(), keyOperator, pubKeyOperator)) {
|
||||
auto dmn = mnList.GetValidMN(proTxHash);
|
||||
if (!dmn) {
|
||||
nFailed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
statusObj.push_back(Pair("errorMessage", "Masternode signing error, could not set key correctly"));
|
||||
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
||||
statusObj.push_back(Pair("errorMessage", "Can't find masternode by proTxHash"));
|
||||
resultsObj.push_back(Pair(proTxHash.ToString(), statusObj));
|
||||
continue;
|
||||
}
|
||||
|
||||
uint256 nTxHash;
|
||||
nTxHash.SetHex(mne.getTxHash());
|
||||
|
||||
int nOutputIndex = 0;
|
||||
if (!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
COutPoint outpoint(nTxHash, nOutputIndex);
|
||||
|
||||
CMasternode mn;
|
||||
bool fMnFound = mnodeman.Get(outpoint, mn);
|
||||
|
||||
if (!fMnFound) {
|
||||
nFailed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
statusObj.push_back(Pair("errorMessage", "Can't find masternode by collateral output"));
|
||||
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && mn.keyIDVoting != pubKeyOperator.GetID()) {
|
||||
nFailed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
statusObj.push_back(Pair("errorMessage", "Can't vote on proposal when key does not match voting key"));
|
||||
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
CGovernanceVote vote(mn.outpoint, hash, eVoteSignal, eVoteOutcome);
|
||||
if (!vote.Sign(keyOperator, pubKeyOperator.GetID())) {
|
||||
CGovernanceVote vote(dmn->collateralOutpoint, hash, eVoteSignal, eVoteOutcome);
|
||||
if (!vote.Sign(key, key.GetPubKey().GetID())) {
|
||||
nFailed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
statusObj.push_back(Pair("errorMessage", "Failure to sign."));
|
||||
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
||||
resultsObj.push_back(Pair(proTxHash.ToString(), statusObj));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -549,7 +518,7 @@ UniValue VoteWithMasternodeList(const std::vector<CMasternodeConfig::CMasternode
|
||||
statusObj.push_back(Pair("errorMessage", exception.GetMessage()));
|
||||
}
|
||||
|
||||
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
||||
resultsObj.push_back(Pair(proTxHash.ToString(), statusObj));
|
||||
}
|
||||
|
||||
UniValue returnObj(UniValue::VOBJ);
|
||||
@ -559,11 +528,12 @@ UniValue VoteWithMasternodeList(const std::vector<CMasternodeConfig::CMasternode
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
void gobject_vote_many_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"gobject vote-many <governance-hash> <vote> <vote-outcome>\n"
|
||||
"Vote on a governance object by all masternodes (using masternode.conf setup)\n"
|
||||
"Vote on a governance object by all masternodes for which the voting key is present in the local wallet\n"
|
||||
"\nArguments:\n"
|
||||
"1. governance-hash (string, required) hash of the governance object\n"
|
||||
"2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
|
||||
@ -592,66 +562,33 @@ UniValue gobject_vote_many(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
|
||||
}
|
||||
|
||||
std::vector<CMasternodeConfig::CMasternodeEntry> entries = masternodeConfig.getEntries();
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
// This is a hack to maintain code-level backwards compatibility with masternode.conf and the deterministic masternodes.
|
||||
// Deterministic masternode keys are managed inside the wallet instead of masternode.conf
|
||||
// This allows voting on proposals when you have the MN voting key in your wallet
|
||||
// We can remove this when we remove support for masternode.conf and only support wallet based masternode
|
||||
// management
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
if (!pwalletMain) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-many not supported when wallet is disabled.");
|
||||
}
|
||||
entries.clear();
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
|
||||
bool found = false;
|
||||
for (const auto &mne : entries) {
|
||||
uint256 nTxHash;
|
||||
nTxHash.SetHex(mne.getTxHash());
|
||||
|
||||
int nOutputIndex = 0;
|
||||
if(!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nTxHash == dmn->collateralOutpoint.hash && (uint32_t)nOutputIndex == dmn->collateralOutpoint.n) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
CKey ownerKey;
|
||||
if (pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, ownerKey)) {
|
||||
CBitcoinSecret secret(ownerKey);
|
||||
CMasternodeConfig::CMasternodeEntry mne(dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringIPPort(false), secret.ToString(), dmn->collateralOutpoint.hash.ToString(), itostr(dmn->collateralOutpoint.n));
|
||||
entries.push_back(mne);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
#else
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
if (!pwalletMain) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-many not supported when wallet is disabled.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return VoteWithMasternodeList(entries, hash, eVoteSignal, eVoteOutcome);
|
||||
std::map<uint256, CKey> votingKeys;
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
|
||||
CKey votingKey;
|
||||
if (pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
|
||||
votingKeys.emplace(dmn->proTxHash, votingKey);
|
||||
}
|
||||
});
|
||||
|
||||
return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome);
|
||||
}
|
||||
|
||||
void gobject_vote_alias_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"gobject vote-alias <governance-hash> <vote> <vote-outcome> <alias-name>\n"
|
||||
"Vote on a governance object by masternode alias (using masternode.conf setup)\n"
|
||||
"Vote on a governance object by masternode's voting key (if present in local wallet)\n"
|
||||
"\nArguments:\n"
|
||||
"1. governance-hash (string, required) hash of the governance object\n"
|
||||
"2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
|
||||
"3. vote-outcome (string, required) vote outcome, possible values: [yes|no|abstain]\n"
|
||||
"4. alias-name (string, required) masternode alias or proTxHash after DIP3 activation"
|
||||
"4. protx-hash (string, required) masternode's proTxHash"
|
||||
);
|
||||
}
|
||||
|
||||
@ -676,41 +613,27 @@ UniValue gobject_vote_alias(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
|
||||
}
|
||||
|
||||
std::vector<CMasternodeConfig::CMasternodeEntry> entries;
|
||||
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
#ifdef ENABLE_WALLET
|
||||
if (!pwalletMain) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled");
|
||||
}
|
||||
|
||||
uint256 proTxHash = ParseHashV(request.params[4], "alias-name");
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash);
|
||||
if (!dmn) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or unknown proTxHash");
|
||||
}
|
||||
|
||||
CKey votingKey;
|
||||
if (!pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Voting ekey %s not known by wallet", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString()));
|
||||
}
|
||||
|
||||
CBitcoinSecret secret(votingKey);
|
||||
CMasternodeConfig::CMasternodeEntry mne(dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringIPPort(false), secret.ToString(), dmn->collateralOutpoint.hash.ToString(), itostr(dmn->collateralOutpoint.n));
|
||||
entries.push_back(mne);
|
||||
#else
|
||||
if (!pwalletMain) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled");
|
||||
#endif
|
||||
} else {
|
||||
std::string strAlias = request.params[4].get_str();
|
||||
for (const auto& mne : masternodeConfig.getEntries()) {
|
||||
if (strAlias == mne.getAlias())
|
||||
entries.push_back(mne);
|
||||
}
|
||||
}
|
||||
|
||||
return VoteWithMasternodeList(entries, hash, eVoteSignal, eVoteOutcome);
|
||||
uint256 proTxHash = ParseHashV(request.params[4], "protx-hash");
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash);
|
||||
if (!dmn) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or unknown proTxHash");
|
||||
}
|
||||
|
||||
CKey votingKey;
|
||||
if (!pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Voting key %s not known by wallet", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString()));
|
||||
}
|
||||
|
||||
std::map<uint256, CKey> votingKeys;
|
||||
votingKeys.emplace(proTxHash, votingKey);
|
||||
|
||||
return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome);
|
||||
}
|
||||
#endif
|
||||
|
||||
UniValue ListObjects(const std::string& strCachedSignal, const std::string& strType, int nStartTime)
|
||||
{
|
||||
@ -1063,10 +986,12 @@ UniValue gobject(const JSONRPCRequest& request)
|
||||
return gobject_submit(request);
|
||||
} else if (strCommand == "vote-conf") {
|
||||
return gobject_vote_conf(request);
|
||||
#ifdef ENABLE_WALLET
|
||||
} else if (strCommand == "vote-many") {
|
||||
return gobject_vote_many(request);
|
||||
} else if (strCommand == "vote-alias") {
|
||||
return gobject_vote_alias(request);
|
||||
#endif
|
||||
} else if (strCommand == "list") {
|
||||
// USERS CAN QUERY THE SYSTEM FOR A LIST OF VARIOUS GOVERNANCE ITEMS
|
||||
return gobject_list(request);
|
||||
@ -1133,10 +1058,9 @@ UniValue voteraw(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
|
||||
}
|
||||
|
||||
CMasternode mn;
|
||||
bool fMnFound = mnodeman.Get(outpoint, mn);
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(outpoint);
|
||||
|
||||
if (!fMnFound) {
|
||||
if (!dmn) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to find masternode in list : " + outpoint.ToStringShort());
|
||||
}
|
||||
|
||||
|
@ -99,13 +99,13 @@ UniValue getpoolinfo(const JSONRPCRequest& request)
|
||||
// obj.push_back(Pair("entries", pprivateSendBase->GetEntriesCount()));
|
||||
obj.push_back(Pair("status", privateSendClient.GetStatuses()));
|
||||
|
||||
std::vector<masternode_info_t> vecMnInfo;
|
||||
if (privateSendClient.GetMixingMasternodesInfo(vecMnInfo)) {
|
||||
std::vector<CDeterministicMNCPtr> vecDmns;
|
||||
if (privateSendClient.GetMixingMasternodesInfo(vecDmns)) {
|
||||
UniValue pools(UniValue::VARR);
|
||||
for (const auto& mnInfo : vecMnInfo) {
|
||||
for (const auto& dmn : vecDmns) {
|
||||
UniValue pool(UniValue::VOBJ);
|
||||
pool.push_back(Pair("outpoint", mnInfo.outpoint.ToStringShort()));
|
||||
pool.push_back(Pair("addr", mnInfo.addr.ToString()));
|
||||
pool.push_back(Pair("outpoint", dmn->collateralOutpoint.ToStringShort()));
|
||||
pool.push_back(Pair("addr", dmn->pdmnState->addr.ToString()));
|
||||
pools.push_back(pool);
|
||||
}
|
||||
obj.push_back(Pair("pools", pools));
|
||||
@ -136,26 +136,21 @@ void masternode_list_help()
|
||||
"2. \"filter\" (string, optional) Filter results. Partial match by outpoint by default in all modes,\n"
|
||||
" additional matches in some modes are also available\n"
|
||||
"\nAvailable modes:\n"
|
||||
" activeseconds - Print number of seconds masternode recognized by the network as enabled\n"
|
||||
" (since latest issued \"masternode start/start-many/start-alias\")\n"
|
||||
" addr - Print ip address associated with a masternode (can be additionally filtered, partial match)\n"
|
||||
" daemon - Print daemon version of a masternode (can be additionally filtered, exact match)\n"
|
||||
" full - Print info in format 'status protocol payee lastseen activeseconds lastpaidtime lastpaidblock IP'\n"
|
||||
" full - Print info in format 'status payee lastpaidtime lastpaidblock IP'\n"
|
||||
" (can be additionally filtered, partial match)\n"
|
||||
" info - Print info in format 'status protocol payee lastseen activeseconds sentinelversion sentinelstate IP'\n"
|
||||
" info - Print info in format 'status payee IP'\n"
|
||||
" (can be additionally filtered, partial match)\n"
|
||||
" json - Print info in JSON format (can be additionally filtered, partial match)\n"
|
||||
" keyIDOwner - Print the masternode owner key id\n"
|
||||
" keyIDVoting - Print the masternode voting key id\n"
|
||||
" lastpaidblock - Print the last block height a node was paid on the network\n"
|
||||
" lastpaidtime - Print the last time a node was paid on the network\n"
|
||||
" lastseen - Print timestamp of when a masternode was last seen on the network\n"
|
||||
" payee - Print Dash address associated with a masternode (can be additionally filtered,\n"
|
||||
" partial match)\n"
|
||||
" protocol - Print protocol of a masternode (can be additionally filtered, exact match)\n"
|
||||
" keyid - Print the masternode (not collateral) key id\n"
|
||||
" rank - Print rank of a masternode based on current block\n"
|
||||
" sentinel - Print sentinel version of a masternode (can be additionally filtered, exact match)\n"
|
||||
" status - Print masternode status: PRE_ENABLED / ENABLED / EXPIRED / SENTINEL_PING_EXPIRED / NEW_START_REQUIRED /\n"
|
||||
" UPDATE_REQUIRED / POSE_BAN / OUTPOINT_SPENT (can be additionally filtered, partial match)\n"
|
||||
" pubKeyOperator - Print the masternode operator public key\n"
|
||||
" status - Print masternode status: ENABLED / POSE_BAN / OUTPOINT_SPENT\n"
|
||||
" (can be additionally filtered, partial match)\n"
|
||||
);
|
||||
}
|
||||
|
||||
@ -224,25 +219,15 @@ UniValue masternode_count(const JSONRPCRequest& request)
|
||||
if (request.fHelp || request.params.size() > 2)
|
||||
masternode_count_help();
|
||||
|
||||
int nCount;
|
||||
int total = mnodeman.CountMasternodes(0);
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
nCount = mnodeman.CountEnabled();
|
||||
} else {
|
||||
masternode_info_t mnInfo;
|
||||
mnodeman.GetNextMasternodeInQueueForPayment(true, nCount, mnInfo);
|
||||
}
|
||||
|
||||
int ps = mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION);
|
||||
int enabled = mnodeman.CountEnabled();
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
int total = mnList.GetAllMNsCount();
|
||||
int enabled = mnList.GetValidMNsCount();
|
||||
|
||||
if (request.params.size() == 1) {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
|
||||
obj.push_back(Pair("total", total));
|
||||
obj.push_back(Pair("ps_compatible", ps));
|
||||
obj.push_back(Pair("enabled", enabled));
|
||||
obj.push_back(Pair("qualify", nCount));
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -252,47 +237,24 @@ UniValue masternode_count(const JSONRPCRequest& request)
|
||||
if (strMode == "total")
|
||||
return total;
|
||||
|
||||
if (strMode == "ps")
|
||||
return ps;
|
||||
|
||||
if (strMode == "enabled")
|
||||
return enabled;
|
||||
|
||||
if (strMode == "qualify")
|
||||
return nCount;
|
||||
|
||||
if (strMode == "all")
|
||||
return strprintf("Total: %d (PS Compatible: %d / Enabled: %d / Qualify: %d)",
|
||||
total, ps, enabled, nCount);
|
||||
return strprintf("Total: %d (Enabled: %d)",
|
||||
total, enabled);
|
||||
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown mode value");
|
||||
}
|
||||
|
||||
UniValue GetNextMasternodeForPayment(int heightShift)
|
||||
{
|
||||
int nCount;
|
||||
int nHeight;
|
||||
masternode_info_t mnInfo;
|
||||
CBlockIndex* pindex = NULL;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pindex = chainActive.Tip();
|
||||
}
|
||||
|
||||
nHeight = pindex->nHeight + heightShift;
|
||||
mnodeman.UpdateLastPaid(pindex);
|
||||
|
||||
CScript payeeScript;
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
auto payee = deterministicMNManager->GetListAtChainTip().GetMNPayee();
|
||||
if (!payee || !mnodeman.GetMasternodeInfo(payee->proTxHash, mnInfo))
|
||||
return "unknown";
|
||||
payeeScript = payee->pdmnState->scriptPayout;
|
||||
} else {
|
||||
if (!mnodeman.GetNextMasternodeInQueueForPayment(nHeight, true, nCount, mnInfo))
|
||||
return "unknown";
|
||||
payeeScript = GetScriptForDestination(mnInfo.keyIDCollateralAddress);
|
||||
}
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto payees = mnList.GetProjectedMNPayees(heightShift);
|
||||
if (payees.empty())
|
||||
return "unknown";
|
||||
auto payee = payees[heightShift - 9];
|
||||
CScript payeeScript = payee->pdmnState->scriptPayout;
|
||||
|
||||
CTxDestination payeeDest;
|
||||
CBitcoinAddress payeeAddr;
|
||||
@ -302,13 +264,11 @@ UniValue GetNextMasternodeForPayment(int heightShift)
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
|
||||
obj.push_back(Pair("height", nHeight));
|
||||
obj.push_back(Pair("IP:port", mnInfo.addr.ToString()));
|
||||
obj.push_back(Pair("protocol", mnInfo.nProtocolVersion));
|
||||
obj.push_back(Pair("outpoint", mnInfo.outpoint.ToStringShort()));
|
||||
obj.push_back(Pair("height", mnList.GetHeight() + heightShift));
|
||||
obj.push_back(Pair("IP:port", payee->pdmnState->addr.ToString()));
|
||||
obj.push_back(Pair("proTxHash", payee->proTxHash.ToString()));
|
||||
obj.push_back(Pair("outpoint", payee->collateralOutpoint.ToStringShort()));
|
||||
obj.push_back(Pair("payee", payeeAddr.IsValid() ? payeeAddr.ToString() : "UNKNOWN"));
|
||||
obj.push_back(Pair("lastseen", mnInfo.nTimeLastPing));
|
||||
obj.push_back(Pair("activeseconds", mnInfo.nTimeLastPing - mnInfo.sigTime));
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -853,11 +813,14 @@ UniValue masternodelist(const JSONRPCRequest& request)
|
||||
if (request.params.size() >= 1) strMode = request.params[0].get_str();
|
||||
if (request.params.size() == 2) strFilter = request.params[1].get_str();
|
||||
|
||||
std::transform(strMode.begin(), strMode.end(), strMode.begin(), ::tolower);
|
||||
|
||||
if (request.fHelp || (
|
||||
strMode != "activeseconds" && strMode != "addr" && strMode != "daemon" && strMode != "full" && strMode != "info" && strMode != "json" &&
|
||||
strMode != "lastseen" && strMode != "lastpaidtime" && strMode != "lastpaidblock" &&
|
||||
strMode != "protocol" && strMode != "payee" && strMode != "pubkey" &&
|
||||
strMode != "rank" && strMode != "sentinel" && strMode != "status"))
|
||||
strMode != "addr" && strMode != "full" && strMode != "info" && strMode != "json" &&
|
||||
strMode != "keyidowner" && strMode != "keyidvoting" &&
|
||||
strMode != "lastpaidtime" && strMode != "lastpaidblock" &&
|
||||
strMode != "payee" && strMode != "pubkeyoperator" &&
|
||||
strMode != "status"))
|
||||
{
|
||||
masternode_list_help();
|
||||
}
|
||||
@ -872,147 +835,108 @@ UniValue masternodelist(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
if (strMode == "rank") {
|
||||
CMasternodeMan::rank_pair_vec_t vMasternodeRanks;
|
||||
mnodeman.GetMasternodeRanks(vMasternodeRanks);
|
||||
for (const auto& rankpair : vMasternodeRanks) {
|
||||
std::string strOutpoint = rankpair.second.outpoint.ToStringShort();
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, rankpair.first));
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmnToStatus = [&](const CDeterministicMNCPtr& dmn) {
|
||||
if (mnList.IsMNValid(dmn)) {
|
||||
return "ENABLED";
|
||||
}
|
||||
} else {
|
||||
std::map<COutPoint, CMasternode> mapMasternodes = mnodeman.GetFullMasternodeMap();
|
||||
for (const auto& mnpair : mapMasternodes) {
|
||||
CMasternode mn = mnpair.second;
|
||||
std::string strOutpoint = mnpair.first.ToStringShort();
|
||||
|
||||
CScript payeeScript;
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(mn.outpoint);
|
||||
if (dmn) {
|
||||
payeeScript = dmn->pdmnState->scriptPayout;
|
||||
}
|
||||
} else {
|
||||
payeeScript = GetScriptForDestination(mn.keyIDCollateralAddress);
|
||||
}
|
||||
|
||||
CTxDestination payeeDest;
|
||||
std::string payeeStr = "UNKOWN";
|
||||
if (ExtractDestination(payeeScript, payeeDest)) {
|
||||
payeeStr = CBitcoinAddress(payeeDest).ToString();
|
||||
}
|
||||
|
||||
if (strMode == "activeseconds") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, (int64_t)(mn.lastPing.sigTime - mn.sigTime)));
|
||||
} else if (strMode == "addr") {
|
||||
std::string strAddress = mn.addr.ToString();
|
||||
if (strFilter !="" && strAddress.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, strAddress));
|
||||
} else if (strMode == "daemon") {
|
||||
std::string strDaemon = mn.lastPing.GetDaemonString();
|
||||
if (strFilter !="" && strDaemon.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, strDaemon));
|
||||
} else if (strMode == "sentinel") {
|
||||
std::string strSentinel = mn.lastPing.GetSentinelString();
|
||||
if (strFilter !="" && strSentinel.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, strSentinel));
|
||||
} else if (strMode == "full") {
|
||||
std::ostringstream streamFull;
|
||||
streamFull << std::setw(18) <<
|
||||
mn.GetStatus() << " " <<
|
||||
mn.nProtocolVersion << " " <<
|
||||
payeeStr << " " <<
|
||||
(int64_t)mn.lastPing.sigTime << " " << std::setw(8) <<
|
||||
(int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " << std::setw(10) <<
|
||||
mn.GetLastPaidTime() << " " << std::setw(6) <<
|
||||
mn.GetLastPaidBlock() << " " <<
|
||||
mn.addr.ToString();
|
||||
std::string strFull = streamFull.str();
|
||||
if (strFilter !="" && strFull.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, strFull));
|
||||
} else if (strMode == "info") {
|
||||
std::ostringstream streamInfo;
|
||||
streamInfo << std::setw(18) <<
|
||||
mn.GetStatus() << " " <<
|
||||
mn.nProtocolVersion << " " <<
|
||||
payeeStr << " " <<
|
||||
(int64_t)mn.lastPing.sigTime << " " << std::setw(8) <<
|
||||
(int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " <<
|
||||
mn.lastPing.GetSentinelString() << " " <<
|
||||
(mn.lastPing.fSentinelIsCurrent ? "current" : "expired") << " " <<
|
||||
mn.addr.ToString();
|
||||
std::string strInfo = streamInfo.str();
|
||||
if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, strInfo));
|
||||
} else if (strMode == "json") {
|
||||
std::ostringstream streamInfo;
|
||||
streamInfo << mn.addr.ToString() << " " <<
|
||||
CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString() << " " <<
|
||||
mn.GetStatus() << " " <<
|
||||
mn.nProtocolVersion << " " <<
|
||||
mn.lastPing.nDaemonVersion << " " <<
|
||||
mn.lastPing.GetSentinelString() << " " <<
|
||||
(mn.lastPing.fSentinelIsCurrent ? "current" : "expired") << " " <<
|
||||
(int64_t)mn.lastPing.sigTime << " " <<
|
||||
(int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " <<
|
||||
mn.GetLastPaidTime() << " " <<
|
||||
mn.GetLastPaidBlock();
|
||||
std::string strInfo = streamInfo.str();
|
||||
if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
UniValue objMN(UniValue::VOBJ);
|
||||
objMN.push_back(Pair("address", mn.addr.ToString()));
|
||||
objMN.push_back(Pair("payee", CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString()));
|
||||
objMN.push_back(Pair("status", mn.GetStatus()));
|
||||
objMN.push_back(Pair("protocol", mn.nProtocolVersion));
|
||||
objMN.push_back(Pair("daemonversion", mn.lastPing.GetDaemonString()));
|
||||
objMN.push_back(Pair("sentinelversion", mn.lastPing.GetSentinelString()));
|
||||
objMN.push_back(Pair("sentinelstate", (mn.lastPing.fSentinelIsCurrent ? "current" : "expired")));
|
||||
objMN.push_back(Pair("lastseen", (int64_t)mn.lastPing.sigTime));
|
||||
objMN.push_back(Pair("activeseconds", (int64_t)(mn.lastPing.sigTime - mn.sigTime)));
|
||||
objMN.push_back(Pair("lastpaidtime", mn.GetLastPaidTime()));
|
||||
objMN.push_back(Pair("lastpaidblock", mn.GetLastPaidBlock()));
|
||||
obj.push_back(Pair(strOutpoint, objMN));
|
||||
} else if (strMode == "lastpaidblock") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, mn.GetLastPaidBlock()));
|
||||
} else if (strMode == "lastpaidtime") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, mn.GetLastPaidTime()));
|
||||
} else if (strMode == "lastseen") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, (int64_t)mn.lastPing.sigTime));
|
||||
} else if (strMode == "payee") {
|
||||
if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, payeeStr));
|
||||
} else if (strMode == "protocol") {
|
||||
if (strFilter !="" && strFilter != strprintf("%d", mn.nProtocolVersion) &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, mn.nProtocolVersion));
|
||||
} else if (strMode == "keyIDOwner") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDOwner)));
|
||||
} else if (strMode == "keyIDOperator") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, HexStr(mn.legacyKeyIDOperator)));
|
||||
} else if (strMode == "keyIDVoting") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDVoting)));
|
||||
} else if (strMode == "status") {
|
||||
std::string strStatus = mn.GetStatus();
|
||||
if (strFilter !="" && strStatus.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, strStatus));
|
||||
}
|
||||
if (mnList.IsMNPoSeBanned(dmn)) {
|
||||
return "POSE_BANNED";
|
||||
}
|
||||
}
|
||||
return "UNKNOWN";
|
||||
};
|
||||
auto dmnToLastPaidTime = [&](const CDeterministicMNCPtr& dmn) {
|
||||
if (dmn->pdmnState->nLastPaidHeight == 0) {
|
||||
return (int)0;
|
||||
}
|
||||
|
||||
LOCK(cs_main);
|
||||
const CBlockIndex* pindex = chainActive[dmn->pdmnState->nLastPaidHeight];
|
||||
return (int)pindex->nTime;
|
||||
};
|
||||
|
||||
mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
|
||||
std::string strOutpoint = dmn->collateralOutpoint.ToStringShort();
|
||||
|
||||
CScript payeeScript = dmn->pdmnState->scriptPayout;
|
||||
CTxDestination payeeDest;
|
||||
std::string payeeStr = "UNKOWN";
|
||||
if (ExtractDestination(payeeScript, payeeDest)) {
|
||||
payeeStr = CBitcoinAddress(payeeDest).ToString();
|
||||
}
|
||||
|
||||
if (strMode == "addr") {
|
||||
std::string strAddress = dmn->pdmnState->addr.ToString(false);
|
||||
if (strFilter !="" && strAddress.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, strAddress));
|
||||
} else if (strMode == "full") {
|
||||
std::ostringstream streamFull;
|
||||
streamFull << std::setw(18) <<
|
||||
dmnToStatus(dmn) << " " <<
|
||||
payeeStr << " " << std::setw(10) <<
|
||||
dmnToLastPaidTime(dmn) << " " << std::setw(6) <<
|
||||
dmn->pdmnState->nLastPaidHeight << " " <<
|
||||
dmn->pdmnState->addr.ToString();
|
||||
std::string strFull = streamFull.str();
|
||||
if (strFilter !="" && strFull.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, strFull));
|
||||
} else if (strMode == "info") {
|
||||
std::ostringstream streamInfo;
|
||||
streamInfo << std::setw(18) <<
|
||||
dmnToStatus(dmn) << " " <<
|
||||
payeeStr << " " <<
|
||||
dmn->pdmnState->addr.ToString();
|
||||
std::string strInfo = streamInfo.str();
|
||||
if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, strInfo));
|
||||
} else if (strMode == "json") {
|
||||
std::ostringstream streamInfo;
|
||||
streamInfo << dmn->pdmnState->addr.ToString() << " " <<
|
||||
CBitcoinAddress(dmn->pdmnState->scriptPayout).ToString() << " " <<
|
||||
dmnToStatus(dmn) << " " <<
|
||||
dmnToLastPaidTime(dmn) << " " <<
|
||||
dmn->pdmnState->nLastPaidHeight;
|
||||
std::string strInfo = streamInfo.str();
|
||||
if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
UniValue objMN(UniValue::VOBJ);
|
||||
objMN.push_back(Pair("address", dmn->pdmnState->addr.ToString()));
|
||||
objMN.push_back(Pair("payee", CBitcoinAddress(dmn->pdmnState->scriptPayout).ToString()));
|
||||
objMN.push_back(Pair("status", dmnToStatus(dmn)));
|
||||
objMN.push_back(Pair("lastpaidtime", dmnToLastPaidTime(dmn)));
|
||||
objMN.push_back(Pair("lastpaidblock", dmn->pdmnState->nLastPaidHeight));
|
||||
obj.push_back(Pair(strOutpoint, objMN));
|
||||
} else if (strMode == "lastpaidblock") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, dmn->pdmnState->nLastPaidHeight));
|
||||
} else if (strMode == "lastpaidtime") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, dmnToLastPaidTime(dmn)));
|
||||
} else if (strMode == "payee") {
|
||||
if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, payeeStr));
|
||||
} else if (strMode == "keyidowner") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, HexStr(dmn->pdmnState->keyIDOwner)));
|
||||
} else if (strMode == "pubkeyoperator") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, dmn->pdmnState->pubKeyOperator.ToString()));
|
||||
} else if (strMode == "keyidvoting") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, HexStr(dmn->pdmnState->keyIDVoting)));
|
||||
} else if (strMode == "status") {
|
||||
std::string strStatus = dmnToStatus(dmn);
|
||||
if (strFilter !="" && strStatus.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, strStatus));
|
||||
}
|
||||
});
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -1828,35 +1828,7 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para
|
||||
ThresholdState state = VersionBitsState(pindexPrev, params, pos, versionbitscache);
|
||||
const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
|
||||
if (vbinfo.check_mn_protocol && state == THRESHOLD_STARTED && fCheckMasternodesUpgraded) {
|
||||
if (deterministicMNManager->IsDIP3Active()) {
|
||||
auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash());
|
||||
auto payee = mnList.GetMNPayee();
|
||||
if (!payee) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
std::vector<CTxOut> voutMasternodePayments;
|
||||
masternode_info_t mnInfo;
|
||||
if (!mnpayments.GetBlockTxOuts(pindexPrev->nHeight + 1, 0, voutMasternodePayments)) {
|
||||
// no votes for this block
|
||||
continue;
|
||||
}
|
||||
bool mnKnown = false;
|
||||
for (const auto& txout : voutMasternodePayments) {
|
||||
if (mnodeman.GetMasternodeInfo(txout.scriptPubKey, mnInfo)) {
|
||||
mnKnown = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!mnKnown) {
|
||||
// unknown masternode
|
||||
continue;
|
||||
}
|
||||
if (mnInfo.nProtocolVersion < DMN_PROTO_VERSION) {
|
||||
// masternode is not upgraded yet
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// TODO implement new logic for MN upgrade checks (e.g. with LLMQ based feature/version voting)
|
||||
}
|
||||
if (state == THRESHOLD_LOCKED_IN || state == THRESHOLD_STARTED) {
|
||||
nVersion |= VersionBitsMask(params, (Consensus::DeploymentPos)i);
|
||||
|
@ -1121,10 +1121,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
}
|
||||
AddToSpends(hash);
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
for(unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
|
||||
if (IsMine(wtx.tx->vout[i]) && !IsSpent(hash, i)) {
|
||||
setWalletUTXO.insert(COutPoint(hash, i));
|
||||
if (deterministicMNManager->IsProTxWithCollateral(wtx.tx, i) || deterministicMNManager->HasMNCollateralAtChainTip(COutPoint(hash, i))) {
|
||||
if (deterministicMNManager->IsProTxWithCollateral(wtx.tx, i) || mnList.HasMNByCollateral(COutPoint(hash, i))) {
|
||||
LockCoin(COutPoint(hash, i));
|
||||
}
|
||||
}
|
||||
@ -3989,11 +3990,13 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
||||
// This avoids accidential spending of collaterals. They can still be unlocked manually if a spend is really intended.
|
||||
void CWallet::AutoLockMasternodeCollaterals()
|
||||
{
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
for (const auto& pair : mapWallet) {
|
||||
for (unsigned int i = 0; i < pair.second.tx->vout.size(); ++i) {
|
||||
if (IsMine(pair.second.tx->vout[i]) && !IsSpent(pair.first, i)) {
|
||||
if (deterministicMNManager->IsProTxWithCollateral(pair.second.tx, i) || deterministicMNManager->HasMNCollateralAtChainTip(COutPoint(pair.first, i))) {
|
||||
if (deterministicMNManager->IsProTxWithCollateral(pair.second.tx, i) || mnList.HasMNByCollateral(COutPoint(pair.first, i))) {
|
||||
LockCoin(COutPoint(pair.first, i));
|
||||
}
|
||||
}
|
||||
@ -4643,11 +4646,13 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
|
||||
|
||||
void CWallet::ListProTxCoins(std::vector<COutPoint>& vOutpts)
|
||||
{
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
AssertLockHeld(cs_wallet);
|
||||
for (const auto &o : setWalletUTXO) {
|
||||
if (mapWallet.count(o.hash)) {
|
||||
const auto &p = mapWallet[o.hash];
|
||||
if (deterministicMNManager->IsProTxWithCollateral(p.tx, o.n) || deterministicMNManager->HasMNCollateralAtChainTip(o)) {
|
||||
if (deterministicMNManager->IsProTxWithCollateral(p.tx, o.n) || mnList.HasMNByCollateral(o)) {
|
||||
vOutpts.emplace_back(o);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user