Refactor masternode management (#1611)

* Store masternodes in a map instead of a vector, drop unused functions in CMasternodeMan

* CTxIn vin -> COutPoint outpoint

* do not use CMasternodeMan::Find outside of the class

* update GetMasternodeInfo

* safe version of GetNextMasternodeInQueueForPayment

* fix ProcessMasternodeConnections

* bump CMasternodeMan::SERIALIZATION_VERSION_STRING
This commit is contained in:
UdjinM6 2017-09-11 17:13:48 +03:00 committed by GitHub
parent cd262bf641
commit 05da4557d0
31 changed files with 512 additions and 582 deletions

View File

@ -100,14 +100,14 @@ bool CActiveMasternode::SendMasternodePing()
return false;
}
if(!mnodeman.Has(vin)) {
if(!mnodeman.Has(outpoint)) {
strNotCapableReason = "Masternode not in masternode list";
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::SendMasternodePing -- %s: %s\n", GetStateString(), strNotCapableReason);
return false;
}
CMasternodePing mnp(vin);
CMasternodePing mnp(outpoint);
mnp.nSentinelVersion = nSentinelVersion;
mnp.fSentinelIsCurrent =
(abs(GetAdjustedTime() - nSentinelPingTime) < MASTERNODE_WATCHDOG_MAX_SECONDS);
@ -117,14 +117,14 @@ bool CActiveMasternode::SendMasternodePing()
}
// Update lastPing for our masternode in Masternode list
if(mnodeman.IsMasternodePingedWithin(vin, MASTERNODE_MIN_MNP_SECONDS, mnp.sigTime)) {
if(mnodeman.IsMasternodePingedWithin(outpoint, MASTERNODE_MIN_MNP_SECONDS, mnp.sigTime)) {
LogPrintf("CActiveMasternode::SendMasternodePing -- Too early to send Masternode Ping\n");
return false;
}
mnodeman.SetMasternodeLastPing(vin, mnp);
mnodeman.SetMasternodeLastPing(outpoint, mnp);
LogPrintf("CActiveMasternode::SendMasternodePing -- Relaying ping, collateral=%s\n", vin.ToString());
LogPrintf("CActiveMasternode::SendMasternodePing -- Relaying ping, collateral=%s\n", outpoint.ToStringShort());
mnp.Relay();
return true;
@ -227,7 +227,7 @@ void CActiveMasternode::ManageStateInitial()
CKey keyCollateral;
// If collateral is found switch to LOCAL mode
if(pwalletMain->GetMasternodeVinAndKeys(vin, pubKeyCollateral, keyCollateral)) {
if(pwalletMain->GetMasternodeOutpointAndKeys(outpoint, pubKeyCollateral, keyCollateral)) {
eType = MASTERNODE_LOCAL;
}
@ -240,8 +240,8 @@ void CActiveMasternode::ManageStateRemote()
GetStatus(), GetTypeString(), fPingerEnabled, pubKeyMasternode.GetID().ToString());
mnodeman.CheckMasternode(pubKeyMasternode, true);
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(pubKeyMasternode);
if(infoMn.fInfoValid) {
masternode_info_t infoMn;
if(mnodeman.GetMasternodeInfo(pubKeyMasternode, infoMn)) {
if(infoMn.nProtocolVersion != PROTOCOL_VERSION) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = "Invalid protocol version";
@ -262,7 +262,7 @@ void CActiveMasternode::ManageStateRemote()
}
if(nState != ACTIVE_MASTERNODE_STARTED) {
LogPrintf("CActiveMasternode::ManageStateRemote -- STARTED!\n");
vin = infoMn.vin;
outpoint = infoMn.vin.prevout;
service = infoMn.addr;
fPingerEnabled = true;
nState = ACTIVE_MASTERNODE_STARTED;
@ -286,8 +286,8 @@ void CActiveMasternode::ManageStateLocal()
CPubKey pubKeyCollateral;
CKey keyCollateral;
if(pwalletMain->GetMasternodeVinAndKeys(vin, pubKeyCollateral, keyCollateral)) {
int nPrevoutAge = GetUTXOConfirmations(vin.prevout);
if(pwalletMain->GetMasternodeOutpointAndKeys(outpoint, pubKeyCollateral, keyCollateral)) {
int nPrevoutAge = GetUTXOConfirmations(outpoint);
if(nPrevoutAge < Params().GetConsensus().nMasternodeMinimumConfirmations){
nState = ACTIVE_MASTERNODE_INPUT_TOO_NEW;
strNotCapableReason = strprintf(_("%s - %d confirmations"), GetStatus(), nPrevoutAge);
@ -297,12 +297,12 @@ void CActiveMasternode::ManageStateLocal()
{
LOCK(pwalletMain->cs_wallet);
pwalletMain->LockCoin(vin.prevout);
pwalletMain->LockCoin(outpoint);
}
CMasternodeBroadcast mnb;
std::string strError;
if(!CMasternodeBroadcast::Create(vin, service, keyCollateral, pubKeyCollateral, keyMasternode, pubKeyMasternode, strError, mnb)) {
if(!CMasternodeBroadcast::Create(outpoint, service, keyCollateral, pubKeyCollateral, keyMasternode, pubKeyMasternode, strError, mnb)) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = "Error creating mastenode broadcast: " + strError;
LogPrintf("CActiveMasternode::ManageStateLocal -- %s: %s\n", GetStateString(), strNotCapableReason);
@ -318,7 +318,7 @@ void CActiveMasternode::ManageStateLocal()
mnodeman.NotifyMasternodeUpdates();
//send to all peers
LogPrintf("CActiveMasternode::ManageStateLocal -- Relay broadcast, vin=%s\n", vin.ToString());
LogPrintf("CActiveMasternode::ManageStateLocal -- Relay broadcast, collateral=%s\n", outpoint.ToStringShort());
mnb.Relay();
}
}

View File

@ -50,7 +50,7 @@ public:
CKey keyMasternode;
// Initialized while registering Masternode
CTxIn vin;
COutPoint outpoint;
CService service;
int nState; // should be one of ACTIVE_MASTERNODE_XXXX
@ -62,7 +62,7 @@ public:
fPingerEnabled(false),
pubKeyMasternode(),
keyMasternode(),
vin(),
outpoint(),
service(),
nState(ACTIVE_MASTERNODE_INITIAL)
{}

View File

@ -99,13 +99,13 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
const CGovernanceVote& vote,
CGovernanceException& exception)
{
if(!mnodeman.Has(vote.GetVinMasternode())) {
if(!mnodeman.Has(vote.GetMasternodeOutpoint())) {
std::ostringstream ostr;
ostr << "CGovernanceObject::ProcessVote -- Masternode index not found";
exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_WARNING);
if(mapOrphanVotes.Insert(vote.GetVinMasternode(), vote_time_pair_t(vote, GetAdjustedTime() + GOVERNANCE_ORPHAN_EXPIRATION_TIME))) {
if(mapOrphanVotes.Insert(vote.GetMasternodeOutpoint(), vote_time_pair_t(vote, GetAdjustedTime() + GOVERNANCE_ORPHAN_EXPIRATION_TIME))) {
if(pfrom) {
mnodeman.AskForMN(pfrom, vote.GetVinMasternode());
mnodeman.AskForMN(pfrom, vote.GetMasternodeOutpoint());
}
LogPrintf("%s\n", ostr.str());
}
@ -115,9 +115,9 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
return false;
}
vote_m_it it = mapCurrentMNVotes.find(vote.GetVinMasternode());
vote_m_it it = mapCurrentMNVotes.find(vote.GetMasternodeOutpoint());
if(it == mapCurrentMNVotes.end()) {
it = mapCurrentMNVotes.insert(vote_m_t::value_type(vote.GetVinMasternode(), vote_rec_t())).first;
it = mapCurrentMNVotes.insert(vote_m_t::value_type(vote.GetMasternodeOutpoint(), vote_rec_t())).first;
}
vote_rec_t& recVote = it->second;
vote_signal_enum_t eSignal = vote.GetSignal();
@ -157,7 +157,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
if(nTimeDelta < GOVERNANCE_UPDATE_MIN) {
std::ostringstream ostr;
ostr << "CGovernanceObject::ProcessVote -- Masternode voting too often"
<< ", MN outpoint = " << vote.GetVinMasternode().prevout.ToStringShort()
<< ", MN outpoint = " << vote.GetMasternodeOutpoint().ToStringShort()
<< ", governance object hash = " << GetHash().ToString()
<< ", time delta = " << nTimeDelta;
LogPrint("gobject", "%s\n", ostr.str());
@ -170,7 +170,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
if(!vote.IsValid(true)) {
std::ostringstream ostr;
ostr << "CGovernanceObject::ProcessVote -- Invalid vote"
<< ", MN outpoint = " << vote.GetVinMasternode().prevout.ToStringShort()
<< ", MN outpoint = " << vote.GetMasternodeOutpoint().ToStringShort()
<< ", governance object hash = " << GetHash().ToString()
<< ", vote hash = " << vote.GetHash().ToString();
LogPrintf("%s\n", ostr.str());
@ -178,10 +178,10 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
governance.AddInvalidVote(vote);
return false;
}
if(!mnodeman.AddGovernanceVote(vote.GetVinMasternode(), vote.GetParentHash())) {
if(!mnodeman.AddGovernanceVote(vote.GetMasternodeOutpoint(), vote.GetParentHash())) {
std::ostringstream ostr;
ostr << "CGovernanceObject::ProcessVote -- Unable to add governance vote"
<< ", MN outpoint = " << vote.GetVinMasternode().prevout.ToStringShort()
<< ", MN outpoint = " << vote.GetMasternodeOutpoint().ToStringShort()
<< ", governance object hash = " << GetHash().ToString();
LogPrint("gobject", "%s\n", ostr.str());
exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_PERMANENT_ERROR);
@ -222,9 +222,9 @@ std::string CGovernanceObject::GetSignatureMessage() const
return strMessage;
}
void CGovernanceObject::SetMasternodeInfo(const CTxIn& vin)
void CGovernanceObject::SetMasternodeVin(const COutPoint& outpoint)
{
vinMasternode = vin;
vinMasternode = CTxIn(outpoint);
}
bool CGovernanceObject::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
@ -442,17 +442,17 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast
if(fCheckCollateral) {
if((nObjectType == GOVERNANCE_OBJECT_TRIGGER) || (nObjectType == GOVERNANCE_OBJECT_WATCHDOG)) {
std::string strOutpoint = vinMasternode.prevout.ToStringShort();
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(vinMasternode);
if(!infoMn.fInfoValid) {
masternode_info_t infoMn;
if(!mnodeman.GetMasternodeInfo(vinMasternode.prevout, infoMn)) {
CMasternode::CollateralStatus err = CMasternode::CheckCollateral(GetMasternodeVin());
CMasternode::CollateralStatus err = CMasternode::CheckCollateral(vinMasternode.prevout);
if (err == CMasternode::COLLATERAL_OK) {
fMissingMasternode = true;
strError = "Masternode not found: " + strOutpoint;
} else if (err == CMasternode::COLLATERAL_UTXO_NOT_FOUND) {
strError = "Failed to find Masternode UTXO, missing masternode=" + GetMasternodeVin().prevout.ToStringShort() + "\n";
strError = "Failed to find Masternode UTXO, missing masternode=" + strOutpoint + "\n";
} else if (err == CMasternode::COLLATERAL_INVALID_AMOUNT) {
strError = "Masternode UTXO should have 1000 DASH, missing masternode=" + GetMasternodeVin().prevout.ToStringShort() + "\n";
strError = "Masternode UTXO should have 1000 DASH, missing masternode=" + strOutpoint + "\n";
}
return false;
@ -638,7 +638,7 @@ int CGovernanceObject::GetAbstainCount(vote_signal_enum_t eVoteSignalIn) const
return CountMatchingVotes(eVoteSignalIn, VOTE_OUTCOME_ABSTAIN);
}
bool CGovernanceObject::GetCurrentMNVotes(const CTxIn& mnCollateralOutpoint, vote_rec_t& voteRecord)
bool CGovernanceObject::GetCurrentMNVotes(const COutPoint& mnCollateralOutpoint, vote_rec_t& voteRecord)
{
vote_m_it it = mapCurrentMNVotes.find(mnCollateralOutpoint);
if (it == mapCurrentMNVotes.end()) {
@ -722,13 +722,13 @@ void CGovernanceObject::CheckOrphanVotes()
vote_mcache_t::list_cit it = listVotes.begin();
while(it != listVotes.end()) {
bool fRemove = false;
const CTxIn& key = it->key;
const COutPoint& key = it->key;
const vote_time_pair_t& pairVote = it->value;
const CGovernanceVote& vote = pairVote.first;
if(pairVote.second < nNow) {
fRemove = true;
}
else if(!mnodeman.Has(vote.GetVinMasternode())) {
else if(!mnodeman.Has(vote.GetMasternodeOutpoint())) {
++it;
continue;
}

View File

@ -116,13 +116,13 @@ class CGovernanceObject
friend class CGovernanceTriggerManager;
public: // Types
typedef std::map<CTxIn, vote_rec_t> vote_m_t;
typedef std::map<COutPoint, vote_rec_t> vote_m_t;
typedef vote_m_t::iterator vote_m_it;
typedef vote_m_t::const_iterator vote_m_cit;
typedef CacheMultiMap<CTxIn, vote_time_pair_t> vote_mcache_t;
typedef CacheMultiMap<COutPoint, vote_time_pair_t> vote_mcache_t;
private:
/// critical section to protect the inner data structures
@ -254,7 +254,7 @@ public:
// Signature related functions
void SetMasternodeInfo(const CTxIn& vin);
void SetMasternodeVin(const COutPoint& outpoint);
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
bool CheckSignature(CPubKey& pubKeyMasternode);
@ -293,7 +293,7 @@ public:
int GetNoCount(vote_signal_enum_t eVoteSignalIn) const;
int GetAbstainCount(vote_signal_enum_t eVoteSignalIn) const;
bool GetCurrentMNVotes(const CTxIn& mnCollateralOutpoint, vote_rec_t& voteRecord);
bool GetCurrentMNVotes(const COutPoint& mnCollateralOutpoint, vote_rec_t& voteRecord);
// FUNCTIONS FOR DEALING WITH DATA STRING

View File

@ -212,11 +212,11 @@ CGovernanceVote::CGovernanceVote()
vchSig()
{}
CGovernanceVote::CGovernanceVote(CTxIn vinMasternodeIn, uint256 nParentHashIn, vote_signal_enum_t eVoteSignalIn, vote_outcome_enum_t eVoteOutcomeIn)
CGovernanceVote::CGovernanceVote(COutPoint outpointMasternodeIn, uint256 nParentHashIn, vote_signal_enum_t eVoteSignalIn, vote_outcome_enum_t eVoteOutcomeIn)
: fValid(true),
fSynced(false),
nVoteSignal(eVoteSignalIn),
vinMasternode(vinMasternodeIn),
vinMasternode(outpointMasternodeIn),
nParentHash(nParentHashIn),
nVoteOutcome(eVoteOutcomeIn),
nTime(GetAdjustedTime()),
@ -273,8 +273,8 @@ bool CGovernanceVote::IsValid(bool fSignatureCheck) const
return false;
}
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(vinMasternode);
if(!infoMn.fInfoValid) {
masternode_info_t infoMn;
if(!mnodeman.GetMasternodeInfo(vinMasternode.prevout, infoMn)) {
LogPrint("gobject", "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", vinMasternode.prevout.ToStringShort());
return false;
}

View File

@ -102,7 +102,7 @@ private:
public:
CGovernanceVote();
CGovernanceVote(CTxIn vinMasternodeIn, uint256 nParentHashIn, vote_signal_enum_t eVoteSignalIn, vote_outcome_enum_t eVoteOutcomeIn);
CGovernanceVote(COutPoint outpointMasternodeIn, uint256 nParentHashIn, vote_signal_enum_t eVoteSignalIn, vote_outcome_enum_t eVoteOutcomeIn);
bool IsValid() const { return fValid; }
@ -128,9 +128,7 @@ public:
return CGovernanceVoting::ConvertOutcomeToString(GetOutcome());
}
CTxIn& GetVinMasternode() { return vinMasternode; }
const CTxIn& GetVinMasternode() const { return vinMasternode; }
const COutPoint& GetMasternodeOutpoint() const { return vinMasternode.prevout; }
/**
* GetHash()

View File

@ -53,11 +53,11 @@ std::vector<CGovernanceVote> CGovernanceObjectVoteFile::GetVotes() const
return vecResult;
}
void CGovernanceObjectVoteFile::RemoveVotesFromMasternode(const CTxIn& vinMasternode)
void CGovernanceObjectVoteFile::RemoveVotesFromMasternode(const COutPoint& outpointMasternode)
{
vote_l_it it = listVotes.begin();
while(it != listVotes.end()) {
if(it->GetVinMasternode() == vinMasternode) {
if(it->GetMasternodeOutpoint() == outpointMasternode) {
--nMemoryVotes;
mapVoteIndex.erase(it->GetHash());
listVotes.erase(it++);

View File

@ -72,7 +72,7 @@ public:
CGovernanceObjectVoteFile& operator=(const CGovernanceObjectVoteFile& other);
void RemoveVotesFromMasternode(const CTxIn& vinMasternode);
void RemoveVotesFromMasternode(const COutPoint& outpointMasternode);
ADD_SERIALIZE_METHODS;

View File

@ -580,7 +580,7 @@ std::vector<CGovernanceVote> CGovernanceManager::GetMatchingVotes(const uint256&
return govobj.GetVoteFile().GetVotes();
}
std::vector<CGovernanceVote> CGovernanceManager::GetCurrentVotes(const uint256& nParentHash, const CTxIn& mnCollateralOutpointFilter)
std::vector<CGovernanceVote> CGovernanceManager::GetCurrentVotes(const uint256& nParentHash, const COutPoint& mnCollateralOutpointFilter)
{
LOCK(cs);
std::vector<CGovernanceVote> vecResult;
@ -590,34 +590,27 @@ std::vector<CGovernanceVote> CGovernanceManager::GetCurrentVotes(const uint256&
if(it == mapObjects.end()) return vecResult;
CGovernanceObject& govobj = it->second;
// Compile a list of Masternode collateral outpoints for which to get votes
std::vector<CTxIn> vecMNTxIn;
if (mnCollateralOutpointFilter == CTxIn()) {
std::vector<CMasternode> mnlist = mnodeman.GetFullMasternodeVector();
for (std::vector<CMasternode>::iterator it = mnlist.begin(); it != mnlist.end(); ++it)
{
vecMNTxIn.push_back(it->vin);
}
}
else {
vecMNTxIn.push_back(mnCollateralOutpointFilter);
CMasternode mn;
std::map<COutPoint, CMasternode> mapMasternodes;
if(mnCollateralOutpointFilter == COutPoint()) {
mapMasternodes = mnodeman.GetFullMasternodeMap();
} else if (mnodeman.Get(mnCollateralOutpointFilter, mn)) {
mapMasternodes[mnCollateralOutpointFilter] = mn;
}
// Loop thru each MN collateral outpoint and get the votes for the `nParentHash` governance object
for (std::vector<CTxIn>::iterator it = vecMNTxIn.begin(); it != vecMNTxIn.end(); ++it)
for (auto& mnpair : mapMasternodes)
{
CTxIn &mnCollateralOutpoint = *it;
// get a vote_rec_t from the govobj
vote_rec_t voteRecord;
if (!govobj.GetCurrentMNVotes(mnCollateralOutpoint, voteRecord)) continue;
if (!govobj.GetCurrentMNVotes(mnpair.first, voteRecord)) continue;
for (vote_instance_m_it it3 = voteRecord.mapInstances.begin(); it3 != voteRecord.mapInstances.end(); ++it3) {
int signal = (it3->first);
int outcome = ((it3->second).eOutcome);
int64_t nCreationTime = ((it3->second).nCreationTime);
CGovernanceVote vote = CGovernanceVote(mnCollateralOutpoint, nParentHash, (vote_signal_enum_t)signal, (vote_outcome_enum_t)outcome);
CGovernanceVote vote = CGovernanceVote(mnpair.first, nParentHash, (vote_signal_enum_t)signal, (vote_outcome_enum_t)outcome);
vote.SetTime(nCreationTime);
vecResult.push_back(vote);
@ -940,7 +933,7 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote,
if(mapInvalidVotes.HasKey(nHashVote)) {
std::ostringstream ostr;
ostr << "CGovernanceManager::ProcessVote -- Old invalid vote "
<< ", MN outpoint = " << vote.GetVinMasternode().prevout.ToStringShort()
<< ", MN outpoint = " << vote.GetMasternodeOutpoint().ToStringShort()
<< ", governance object hash = " << vote.GetParentHash().ToString();
LogPrintf("%s\n", ostr.str());
exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_PERMANENT_ERROR, 20);
@ -953,7 +946,7 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote,
if(it == mapObjects.end()) {
std::ostringstream ostr;
ostr << "CGovernanceManager::ProcessVote -- Unknown parent object "
<< ", MN outpoint = " << vote.GetVinMasternode().prevout.ToStringShort()
<< ", MN outpoint = " << vote.GetMasternodeOutpoint().ToStringShort()
<< ", governance object hash = " << vote.GetParentHash().ToString();
exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_WARNING);
if(mapOrphanVotes.Insert(nHashGovobj, vote_time_pair_t(vote, GetAdjustedTime() + GOVERNANCE_ORPHAN_EXPIRATION_TIME))) {
@ -981,7 +974,7 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote,
mapVoteToObject.Insert(nHashVote, &govobj);
if(govobj.GetObjectType() == GOVERNANCE_OBJECT_WATCHDOG) {
mnodeman.UpdateWatchdogVoteTime(vote.GetVinMasternode());
mnodeman.UpdateWatchdogVoteTime(vote.GetMasternodeOutpoint());
LogPrint("gobject", "CGovernanceObject::ProcessVote -- GOVERNANCE_OBJECT_WATCHDOG vote for %s\n", vote.GetParentHash().ToString());
}
}

View File

@ -309,7 +309,7 @@ public:
CGovernanceObject *FindGovernanceObject(const uint256& nHash);
std::vector<CGovernanceVote> GetMatchingVotes(const uint256& nParentHash);
std::vector<CGovernanceVote> GetCurrentVotes(const uint256& nParentHash, const CTxIn& mnCollateralOutpointFilter);
std::vector<CGovernanceVote> GetCurrentVotes(const uint256& nParentHash, const COutPoint& mnCollateralOutpointFilter);
std::vector<CGovernanceObject*> GetAllNewerThan(int64_t nMoreThanTime);
bool IsBudgetPaymentBlock(int nBlockHeight);

View File

@ -175,10 +175,10 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate)
int nLockInputHeight = nPrevoutHeight + 4;
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION);
int n = mnodeman.GetMasternodeRank(activeMasternode.outpoint, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION);
if(n == -1) {
LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternode.vin.prevout.ToStringShort());
LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternode.outpoint.ToStringShort());
++itOutpointLock;
continue;
}
@ -200,7 +200,7 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate)
if(itVoted != mapVotedOutpoints.end()) {
BOOST_FOREACH(const uint256& hash, itVoted->second) {
std::map<uint256, CTxLockCandidate>::iterator it2 = mapTxLockCandidates.find(hash);
if(it2->second.HasMasternodeVoted(itOutpointLock->first, activeMasternode.vin.prevout)) {
if(it2->second.HasMasternodeVoted(itOutpointLock->first, activeMasternode.outpoint)) {
// we already voted for this outpoint to be included either in the same tx or in a competing one,
// skip it anyway
fAlreadyVoted = true;
@ -216,7 +216,7 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate)
}
// we haven't voted for this outpoint yet, let's try to do this now
CTxLockVote vote(txHash, itOutpointLock->first, activeMasternode.vin.prevout);
CTxLockVote vote(txHash, itOutpointLock->first, activeMasternode.outpoint);
if(!vote.Sign()) {
LogPrintf("CInstantSend::Vote -- Failed to sign consensus vote\n");
@ -993,9 +993,9 @@ bool CTxLockRequest::IsTimedOut() const
bool CTxLockVote::IsValid(CNode* pnode) const
{
if(!mnodeman.Has(CTxIn(outpointMasternode))) {
if(!mnodeman.Has(outpointMasternode)) {
LogPrint("instantsend", "CTxLockVote::IsValid -- Unknown masternode %s\n", outpointMasternode.ToStringShort());
mnodeman.AskForMN(pnode, CTxIn(outpointMasternode));
mnodeman.AskForMN(pnode, outpointMasternode);
return false;
}
@ -1022,7 +1022,7 @@ bool CTxLockVote::IsValid(CNode* pnode) const
int nLockInputHeight = nPrevoutHeight + 4;
int n = mnodeman.GetMasternodeRank(CTxIn(outpointMasternode), nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION);
int n = mnodeman.GetMasternodeRank(outpointMasternode, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION);
if(n == -1) {
//can be caused by past versions trying to vote with an invalid protocol
@ -1060,9 +1060,9 @@ bool CTxLockVote::CheckSignature() const
std::string strError;
std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(CTxIn(outpointMasternode));
masternode_info_t infoMn;
if(!infoMn.fInfoValid) {
if(!mnodeman.GetMasternodeInfo(outpointMasternode, infoMn)) {
LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: masternode=%s\n", outpointMasternode.ToString());
return false;
}

View File

@ -271,14 +271,14 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockH
if(!mnpayments.GetBlockPayee(nBlockHeight, payee)) {
// no masternode detected...
int nCount = 0;
CMasternode *winningNode = mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount);
if(!winningNode) {
masternode_info_t mnInfo;
if(!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) {
// ...and we can't calculate it on our own
LogPrintf("CMasternodePayments::FillBlockPayee -- Failed to detect masternode to pay\n");
return;
}
// fill payee with locally calculated winner and hope for the best
payee = GetScriptForDestination(winningNode->pubKeyCollateralAddress.GetID());
payee = GetScriptForDestination(mnInfo.pubKeyCollateralAddress.GetID());
}
// GET MASTERNODE PAYMENT VARIABLES SETUP
@ -373,11 +373,11 @@ void CMasternodePayments::ProcessMessage(CNode* pfrom, std::string& strCommand,
return;
}
masternode_info_t mnInfo = mnodeman.GetMasternodeInfo(vote.vinMasternode);
if(!mnInfo.fInfoValid) {
masternode_info_t mnInfo;
if(!mnodeman.GetMasternodeInfo(vote.vinMasternode.prevout, mnInfo)) {
// mn was not found, so we can't check vote, some info is probably missing
LogPrintf("MASTERNODEPAYMENTVOTE -- masternode is missing %s\n", vote.vinMasternode.prevout.ToStringShort());
mnodeman.AskForMN(pfrom, vote.vinMasternode);
mnodeman.AskForMN(pfrom, vote.vinMasternode.prevout);
return;
}
@ -392,7 +392,7 @@ void CMasternodePayments::ProcessMessage(CNode* pfrom, std::string& strCommand,
}
// Either our info or vote info could be outdated.
// In case our info is outdated, ask for an update,
mnodeman.AskForMN(pfrom, vote.vinMasternode);
mnodeman.AskForMN(pfrom, vote.vinMasternode.prevout);
// but there is nothing we can do if vote info itself is outdated
// (i.e. it was signed by a mn which changed its key),
// so just quit here.
@ -654,13 +654,13 @@ void CMasternodePayments::CheckAndRemove()
bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::string& strError)
{
CMasternode* pmn = mnodeman.Find(vinMasternode);
masternode_info_t mnInfo;
if(!pmn) {
if(!mnodeman.GetMasternodeInfo(vinMasternode.prevout, mnInfo)) {
strError = strprintf("Unknown Masternode: prevout=%s", vinMasternode.prevout.ToStringShort());
// Only ask if we are already synced and still have no idea about that Masternode
if(masternodeSync.IsMasternodeListSynced()) {
mnodeman.AskForMN(pnode, vinMasternode);
mnodeman.AskForMN(pnode, vinMasternode.prevout);
}
return false;
@ -675,8 +675,8 @@ bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::s
nMinRequiredProtocol = MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1;
}
if(pmn->nProtocolVersion < nMinRequiredProtocol) {
strError = strprintf("Masternode protocol is too old: nProtocolVersion=%d, nMinRequiredProtocol=%d", pmn->nProtocolVersion, nMinRequiredProtocol);
if(mnInfo.nProtocolVersion < nMinRequiredProtocol) {
strError = strprintf("Masternode protocol is too old: nProtocolVersion=%d, nMinRequiredProtocol=%d", mnInfo.nProtocolVersion, nMinRequiredProtocol);
return false;
}
@ -684,7 +684,7 @@ bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::s
// Regular clients (miners included) need to verify masternode rank for future block votes only.
if(!fMasterNode && nBlockHeight < nValidationHeight) return true;
int nRank = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 101, nMinRequiredProtocol, false);
int nRank = mnodeman.GetMasternodeRank(vinMasternode.prevout, nBlockHeight - 101, nMinRequiredProtocol, false);
if(nRank == -1) {
LogPrint("mnpayments", "CMasternodePaymentVote::IsValid -- Can't calculate rank for masternode %s\n",
@ -720,7 +720,7 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
// if we have not enough data about masternodes.
if(!masternodeSync.IsMasternodeListSynced()) return false;
int nRank = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 101, GetMinMasternodePaymentsProto(), false);
int nRank = mnodeman.GetMasternodeRank(activeMasternode.outpoint, nBlockHeight - 101, GetMinMasternodePaymentsProto(), false);
if (nRank == -1) {
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock -- Unknown Masternode\n");
@ -735,23 +735,23 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
// LOCATE THE NEXT MASTERNODE WHICH SHOULD BE PAID
LogPrintf("CMasternodePayments::ProcessBlock -- Start: nBlockHeight=%d, masternode=%s\n", nBlockHeight, activeMasternode.vin.prevout.ToStringShort());
LogPrintf("CMasternodePayments::ProcessBlock -- Start: nBlockHeight=%d, masternode=%s\n", nBlockHeight, activeMasternode.outpoint.ToStringShort());
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
int nCount = 0;
CMasternode *pmn = mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount);
masternode_info_t mnInfo;
if (pmn == NULL) {
if (!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) {
LogPrintf("CMasternodePayments::ProcessBlock -- ERROR: Failed to find masternode to pay\n");
return false;
}
LogPrintf("CMasternodePayments::ProcessBlock -- Masternode found by GetNextMasternodeInQueueForPayment(): %s\n", pmn->vin.prevout.ToStringShort());
LogPrintf("CMasternodePayments::ProcessBlock -- Masternode found by GetNextMasternodeInQueueForPayment(): %s\n", mnInfo.vin.prevout.ToStringShort());
CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
CScript payee = GetScriptForDestination(mnInfo.pubKeyCollateralAddress.GetID());
CMasternodePaymentVote voteNew(activeMasternode.vin, nBlockHeight, payee);
CMasternodePaymentVote voteNew(activeMasternode.outpoint, nBlockHeight, payee);
CTxDestination address1;
ExtractDestination(payee, address1);

View File

@ -122,8 +122,8 @@ public:
vchSig()
{}
CMasternodePaymentVote(CTxIn vinMasternode, int nBlockHeight, CScript payee) :
vinMasternode(vinMasternode),
CMasternodePaymentVote(COutPoint outpointMasternode, int nBlockHeight, CScript payee) :
vinMasternode(outpointMasternode),
nBlockHeight(nBlockHeight),
payee(payee),
vchSig()

View File

@ -20,9 +20,9 @@ CMasternode::CMasternode() :
fAllowMixingTx(true)
{}
CMasternode::CMasternode(CService addr, CTxIn vin, CPubKey pubKeyCollateralAddress, CPubKey pubKeyMasternode, int nProtocolVersionIn) :
CMasternode::CMasternode(CService addr, COutPoint outpoint, CPubKey pubKeyCollateralAddress, CPubKey pubKeyMasternode, int nProtocolVersionIn) :
masternode_info_t{ MASTERNODE_ENABLED, nProtocolVersionIn, GetAdjustedTime(),
vin, addr, pubKeyCollateralAddress, pubKeyMasternode},
outpoint, addr, pubKeyCollateralAddress, pubKeyMasternode},
fAllowMixingTx(true)
{}
@ -40,7 +40,7 @@ CMasternode::CMasternode(const CMasternode& other) :
CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
masternode_info_t{ mnb.nActiveState, mnb.nProtocolVersion, mnb.sigTime,
mnb.vin, mnb.addr, mnb.pubKeyCollateralAddress, mnb.pubKeyMasternode,
mnb.vin.prevout, mnb.addr, mnb.pubKeyCollateralAddress, mnb.pubKeyMasternode,
mnb.sigTime /*nTimeLastWatchdogVote*/},
lastPing(mnb.lastPing),
vchSig(mnb.vchSig),
@ -104,26 +104,26 @@ arith_uint256 CMasternode::CalculateScore(const uint256& blockHash)
return (hash3 > hash2 ? hash3 - hash2 : hash2 - hash3);
}
CMasternode::CollateralStatus CMasternode::CheckCollateral(CTxIn vin)
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint)
{
int nHeight;
return CheckCollateral(vin, nHeight);
return CheckCollateral(outpoint, nHeight);
}
CMasternode::CollateralStatus CMasternode::CheckCollateral(CTxIn vin, int& nHeight)
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, int& nHeightRet)
{
AssertLockHeld(cs_main);
CCoins coins;
if(!GetUTXOCoins(vin.prevout, coins)) {
if(!GetUTXOCoins(outpoint, coins)) {
return COLLATERAL_UTXO_NOT_FOUND;
}
if(coins.vout[vin.prevout.n].nValue != 1000 * COIN) {
if(coins.vout[outpoint.n].nValue != 1000 * COIN) {
return COLLATERAL_INVALID_AMOUNT;
}
nHeight = coins.nHeight;
nHeightRet = coins.nHeight;
return COLLATERAL_OK;
}
@ -146,7 +146,7 @@ void CMasternode::Check(bool fForce)
TRY_LOCK(cs_main, lockMain);
if(!lockMain) return;
CollateralStatus err = CheckCollateral(vin);
CollateralStatus err = CheckCollateral(vin.prevout);
if (err == COLLATERAL_UTXO_NOT_FOUND) {
nActiveState = MASTERNODE_OUTPOINT_SPENT;
LogPrint("masternode", "CMasternode::Check -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
@ -349,7 +349,7 @@ void CMasternode::UpdateLastPaid(const CBlockIndex *pindex, int nMaxBlocksToScan
bool CMasternodeBroadcast::Create(std::string strService, std::string strKeyMasternode, std::string strTxHash, std::string strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast &mnbRet, bool fOffline)
{
CTxIn txin;
COutPoint outpoint;
CPubKey pubKeyCollateralAddressNew;
CKey keyCollateralAddressNew;
CPubKey pubKeyMasternodeNew;
@ -369,8 +369,8 @@ bool CMasternodeBroadcast::Create(std::string strService, std::string strKeyMast
if (!CMessageSigner::GetKeysFromSecret(strKeyMasternode, keyMasternodeNew, pubKeyMasternodeNew))
return Log(strprintf("Invalid masternode key %s", strKeyMasternode));
if (!pwalletMain->GetMasternodeVinAndKeys(txin, pubKeyCollateralAddressNew, keyCollateralAddressNew, strTxHash, strOutputIndex))
return Log(strprintf("Could not allocate txin %s:%s for masternode %s", strTxHash, strOutputIndex, strService));
if (!pwalletMain->GetMasternodeOutpointAndKeys(outpoint, pubKeyCollateralAddressNew, keyCollateralAddressNew, strTxHash, strOutputIndex))
return Log(strprintf("Could not allocate outpoint %s:%s for masternode %s", strTxHash, strOutputIndex, strService));
CService service;
if (!Lookup(strService.c_str(), service, 0, false))
@ -382,10 +382,10 @@ bool CMasternodeBroadcast::Create(std::string strService, std::string strKeyMast
} else if (service.GetPort() == mainnetDefaultPort)
return Log(strprintf("Invalid port %u for masternode %s, %d is the only supported on mainnet.", service.GetPort(), strService, mainnetDefaultPort));
return Create(txin, service, keyCollateralAddressNew, pubKeyCollateralAddressNew, keyMasternodeNew, pubKeyMasternodeNew, strErrorRet, mnbRet);
return Create(outpoint, service, keyCollateralAddressNew, pubKeyCollateralAddressNew, keyMasternodeNew, pubKeyMasternodeNew, strErrorRet, mnbRet);
}
bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollateralAddressNew, CPubKey pubKeyCollateralAddressNew, CKey keyMasternodeNew, CPubKey pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet)
bool CMasternodeBroadcast::Create(const COutPoint& outpoint, const CService& service, const CKey& keyCollateralAddressNew, const CPubKey& pubKeyCollateralAddressNew, const CKey& keyMasternodeNew, const CPubKey& pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet)
{
// wait for reindex and/or import to finish
if (fImporting || fReindex) return false;
@ -402,18 +402,18 @@ bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollater
return false;
};
CMasternodePing mnp(txin);
CMasternodePing mnp(outpoint);
if (!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew))
return Log(strprintf("Failed to sign ping, masternode=%s", txin.prevout.ToStringShort()));
return Log(strprintf("Failed to sign ping, masternode=%s", outpoint.ToStringShort()));
mnbRet = CMasternodeBroadcast(service, txin, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION);
mnbRet = CMasternodeBroadcast(service, outpoint, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION);
if (!mnbRet.IsValidNetAddr())
return Log(strprintf("Invalid IP address, masternode=%s", txin.prevout.ToStringShort()));
return Log(strprintf("Invalid IP address, masternode=%s", outpoint.ToStringShort()));
mnbRet.lastPing = mnp;
if (!mnbRet.Sign(keyCollateralAddressNew))
return Log(strprintf("Failed to sign broadcast, masternode=%s", txin.prevout.ToStringShort()));
return Log(strprintf("Failed to sign broadcast, masternode=%s", outpoint.ToStringShort()));
return true;
}
@ -535,7 +535,7 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
{
// we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey)
// so nothing to do here for us
if(fMasterNode && vin.prevout == activeMasternode.vin.prevout && pubKeyMasternode == activeMasternode.pubKeyMasternode) {
if(fMasterNode && vin.prevout == activeMasternode.outpoint && pubKeyMasternode == activeMasternode.pubKeyMasternode) {
return false;
}
@ -554,7 +554,7 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
}
int nHeight;
CollateralStatus err = CheckCollateral(vin, nHeight);
CollateralStatus err = CheckCollateral(vin.prevout, nHeight);
if (err == COLLATERAL_UTXO_NOT_FOUND) {
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
return false;
@ -606,7 +606,7 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
return true;
}
bool CMasternodeBroadcast::Sign(CKey& keyCollateralAddress)
bool CMasternodeBroadcast::Sign(const CKey& keyCollateralAddress)
{
std::string strError;
std::string strMessage;
@ -657,17 +657,17 @@ void CMasternodeBroadcast::Relay()
g_connman->RelayInv(inv);
}
CMasternodePing::CMasternodePing(CTxIn& vinNew)
CMasternodePing::CMasternodePing(const COutPoint& outpoint)
{
LOCK(cs_main);
if (!chainActive.Tip() || chainActive.Height() < 12) return;
vin = vinNew;
vin = CTxIn(outpoint);
blockHash = chainActive[chainActive.Height() - 12]->GetBlockHash();
sigTime = GetAdjustedTime();
}
bool CMasternodePing::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
bool CMasternodePing::Sign(const CKey& keyMasternode, const CPubKey& pubKeyMasternode)
{
std::string strError;
std::string strMasterNodeSignMessage;

View File

@ -41,7 +41,7 @@ public:
CMasternodePing() = default;
CMasternodePing(CTxIn& vinNew);
CMasternodePing(const COutPoint& outpoint);
ADD_SERIALIZE_METHODS;
@ -71,7 +71,7 @@ public:
bool IsExpired() const { return GetAdjustedTime() - sigTime > MASTERNODE_NEW_START_REQUIRED_SECONDS; }
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
bool Sign(const CKey& keyMasternode, const CPubKey& pubKeyMasternode);
bool CheckSignature(CPubKey& pubKeyMasternode, int &nDos);
bool SimpleCheck(int& nDos);
bool CheckAndUpdate(CMasternode* pmn, bool fFromNewBroadcast, int& nDos);
@ -98,11 +98,11 @@ struct masternode_info_t
nActiveState{activeState}, nProtocolVersion{protoVer}, sigTime{sTime} {}
masternode_info_t(int activeState, int protoVer, int64_t sTime,
CTxIn const& vin, CService const& addr,
COutPoint const& outpoint, CService const& addr,
CPubKey const& pkCollAddr, CPubKey const& pkMN,
int64_t tWatchdogV = 0) :
nActiveState{activeState}, nProtocolVersion{protoVer}, sigTime{sTime},
vin{vin}, addr{addr},
vin{outpoint}, addr{addr},
pubKeyCollateralAddress{pkCollAddr}, pubKeyMasternode{pkMN},
nTimeLastWatchdogVote{tWatchdogV} {}
@ -168,7 +168,7 @@ public:
CMasternode();
CMasternode(const CMasternode& other);
CMasternode(const CMasternodeBroadcast& mnb);
CMasternode(CService addrNew, CTxIn vinNew, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int nProtocolVersionIn);
CMasternode(CService addrNew, COutPoint outpointNew, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int nProtocolVersionIn);
ADD_SERIALIZE_METHODS;
@ -202,8 +202,8 @@ public:
bool UpdateFromNewBroadcast(CMasternodeBroadcast& mnb);
static CollateralStatus CheckCollateral(CTxIn vin);
static CollateralStatus CheckCollateral(CTxIn vin, int& nHeight);
static CollateralStatus CheckCollateral(const COutPoint& outpoint);
static CollateralStatus CheckCollateral(const COutPoint& outpoint, int& nHeightRet);
void Check(bool fForce = false);
bool IsBroadcastedWithin(int nSeconds) { return GetAdjustedTime() - sigTime < nSeconds; }
@ -316,8 +316,8 @@ public:
CMasternodeBroadcast() : CMasternode(), fRecovery(false) {}
CMasternodeBroadcast(const CMasternode& mn) : CMasternode(mn), fRecovery(false) {}
CMasternodeBroadcast(CService addrNew, CTxIn vinNew, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int nProtocolVersionIn) :
CMasternode(addrNew, vinNew, pubKeyCollateralAddressNew, pubKeyMasternodeNew, nProtocolVersionIn), fRecovery(false) {}
CMasternodeBroadcast(CService addrNew, COutPoint outpointNew, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int nProtocolVersionIn) :
CMasternode(addrNew, outpointNew, pubKeyCollateralAddressNew, pubKeyMasternodeNew, nProtocolVersionIn), fRecovery(false) {}
ADD_SERIALIZE_METHODS;
@ -343,14 +343,14 @@ public:
}
/// Create Masternode broadcast, needs to be relayed manually after that
static bool Create(CTxIn vin, CService service, CKey keyCollateralAddressNew, CPubKey pubKeyCollateralAddressNew, CKey keyMasternodeNew, CPubKey pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet);
static bool Create(const COutPoint& outpoint, const CService& service, const CKey& keyCollateralAddressNew, const CPubKey& pubKeyCollateralAddressNew, const CKey& keyMasternodeNew, const CPubKey& pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet);
static bool Create(std::string strService, std::string strKey, std::string strTxHash, std::string strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast &mnbRet, bool fOffline = false);
bool SimpleCheck(int& nDos);
bool Update(CMasternode* pmn, int& nDos);
bool CheckOutpoint(int& nDos);
bool Sign(CKey& keyCollateralAddress);
bool Sign(const CKey& keyCollateralAddress);
bool CheckSignature(int& nDos);
void Relay();
};

View File

@ -16,7 +16,7 @@
/** Masternode manager */
CMasternodeMan mnodeman;
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-5";
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-6";
struct CompareLastPaidBlock
{
@ -48,7 +48,7 @@ struct CompareByAddr
CMasternodeMan::CMasternodeMan()
: cs(),
vMasternodes(),
mapMasternodes(),
mAskedUsForMasternodeList(),
mWeAskedForMasternodeList(),
mWeAskedForMasternodeListEntry(),
@ -69,21 +69,21 @@ bool CMasternodeMan::Add(CMasternode &mn)
{
LOCK(cs);
if (Has(mn.vin)) return false;
if (Has(mn.vin.prevout)) return false;
LogPrint("masternode", "CMasternodeMan::Add -- Adding new Masternode: addr=%s, %i now\n", mn.addr.ToString(), size() + 1);
vMasternodes.push_back(mn);
mapMasternodes[mn.vin.prevout] = mn;
fMasternodesAdded = true;
return true;
}
void CMasternodeMan::AskForMN(CNode* pnode, const CTxIn &vin)
void CMasternodeMan::AskForMN(CNode* pnode, const COutPoint& outpoint)
{
if(!pnode) return;
LOCK(cs);
std::map<COutPoint, std::map<CNetAddr, int64_t> >::iterator it1 = mWeAskedForMasternodeListEntry.find(vin.prevout);
std::map<COutPoint, std::map<CNetAddr, int64_t> >::iterator it1 = mWeAskedForMasternodeListEntry.find(outpoint);
if (it1 != mWeAskedForMasternodeListEntry.end()) {
std::map<CNetAddr, int64_t>::iterator it2 = it1->second.find(pnode->addr);
if (it2 != it1->second.end()) {
@ -92,18 +92,44 @@ void CMasternodeMan::AskForMN(CNode* pnode, const CTxIn &vin)
return;
}
// we asked this node for this outpoint but it's ok to ask again already
LogPrintf("CMasternodeMan::AskForMN -- Asking same peer %s for missing masternode entry again: %s\n", pnode->addr.ToString(), vin.prevout.ToStringShort());
LogPrintf("CMasternodeMan::AskForMN -- Asking same peer %s for missing masternode entry again: %s\n", pnode->addr.ToString(), outpoint.ToStringShort());
} else {
// we already asked for this outpoint but not this node
LogPrintf("CMasternodeMan::AskForMN -- Asking new peer %s for missing masternode entry: %s\n", pnode->addr.ToString(), vin.prevout.ToStringShort());
LogPrintf("CMasternodeMan::AskForMN -- Asking new peer %s for missing masternode entry: %s\n", pnode->addr.ToString(), outpoint.ToStringShort());
}
} else {
// we never asked any node for this outpoint
LogPrintf("CMasternodeMan::AskForMN -- Asking peer %s for missing masternode entry for the first time: %s\n", pnode->addr.ToString(), vin.prevout.ToStringShort());
LogPrintf("CMasternodeMan::AskForMN -- Asking peer %s for missing masternode entry for the first time: %s\n", pnode->addr.ToString(), outpoint.ToStringShort());
}
mWeAskedForMasternodeListEntry[vin.prevout][pnode->addr] = GetTime() + DSEG_UPDATE_SECONDS;
mWeAskedForMasternodeListEntry[outpoint][pnode->addr] = GetTime() + DSEG_UPDATE_SECONDS;
g_connman->PushMessage(pnode, NetMsgType::DSEG, vin);
g_connman->PushMessage(pnode, NetMsgType::DSEG, CTxIn(outpoint));
}
bool CMasternodeMan::AllowMixing(const COutPoint &outpoint)
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
if (!pmn) {
return false;
}
nDsqCount++;
pmn->nLastDsq = nDsqCount;
pmn->fAllowMixingTx = true;
return true;
}
bool CMasternodeMan::DisallowMixing(const COutPoint &outpoint)
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
if (!pmn) {
return false;
}
pmn->fAllowMixingTx = false;
return true;
}
void CMasternodeMan::Check()
@ -112,8 +138,8 @@ void CMasternodeMan::Check()
LogPrint("masternode", "CMasternodeMan::Check -- nLastWatchdogVoteTime=%d, IsWatchdogActive()=%d\n", nLastWatchdogVoteTime, IsWatchdogActive());
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
mn.Check();
for (auto& mnpair : mapMasternodes) {
mnpair.second.Check();
}
}
@ -131,29 +157,29 @@ void CMasternodeMan::CheckAndRemove()
Check();
// Remove spent masternodes, prepare structures and make requests to reasure the state of inactive ones
std::vector<CMasternode>::iterator it = vMasternodes.begin();
std::vector<std::pair<int, CMasternode> > vecMasternodeRanks;
// ask for up to MNB_RECOVERY_MAX_ASK_ENTRIES masternode entries at a time
int nAskForMnbRecovery = MNB_RECOVERY_MAX_ASK_ENTRIES;
while(it != vMasternodes.end()) {
CMasternodeBroadcast mnb = CMasternodeBroadcast(*it);
std::map<COutPoint, CMasternode>::iterator it = mapMasternodes.begin();
while (it != mapMasternodes.end()) {
CMasternodeBroadcast mnb = CMasternodeBroadcast(it->second);
uint256 hash = mnb.GetHash();
// If collateral was spent ...
if ((*it).IsOutpointSpent()) {
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing Masternode: %s addr=%s %i now\n", (*it).GetStateString(), (*it).addr.ToString(), size() - 1);
if (it->second.IsOutpointSpent()) {
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing Masternode: %s addr=%s %i now\n", it->second.GetStateString(), it->second.addr.ToString(), size() - 1);
// erase all of the broadcasts we've seen from this txin, ...
mapSeenMasternodeBroadcast.erase(hash);
mWeAskedForMasternodeListEntry.erase((*it).vin.prevout);
mWeAskedForMasternodeListEntry.erase(it->first);
// and finally remove it from the list
it->FlagGovernanceItemsAsDirty();
it = vMasternodes.erase(it);
it->second.FlagGovernanceItemsAsDirty();
mapMasternodes.erase(it++);
fMasternodesRemoved = true;
} else {
bool fAsk = (nAskForMnbRecovery > 0) &&
masternodeSync.IsSynced() &&
it->IsNewStartRequired() &&
it->second.IsNewStartRequired() &&
!IsMnbRecoveryRequested(hash);
if(fAsk) {
// this mn is in a non-recoverable state and we haven't asked other nodes yet
@ -167,7 +193,7 @@ void CMasternodeMan::CheckAndRemove()
// 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->vin.prevout) && mWeAskedForMasternodeListEntry[it->vin.prevout].count(vecMasternodeRanks[i].second.addr)) continue;
if(mWeAskedForMasternodeListEntry.count(it->first) && mWeAskedForMasternodeListEntry[it->first].count(vecMasternodeRanks[i].second.addr)) continue;
// didn't ask recently, ok to ask now
CService addr = vecMasternodeRanks[i].second.addr;
setRequested.insert(addr);
@ -175,7 +201,7 @@ void CMasternodeMan::CheckAndRemove()
fAskedForMnbRecovery = true;
}
if(fAskedForMnbRecovery) {
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Recovery initiated, masternode=%s\n", it->vin.prevout.ToStringShort());
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Recovery initiated, masternode=%s\n", it->first.ToStringShort());
nAskForMnbRecovery--;
}
// wait for mnb recovery replies for MNB_RECOVERY_WAIT_SECONDS seconds
@ -303,7 +329,7 @@ void CMasternodeMan::CheckAndRemove()
void CMasternodeMan::Clear()
{
LOCK(cs);
vMasternodes.clear();
mapMasternodes.clear();
mAskedUsForMasternodeList.clear();
mWeAskedForMasternodeList.clear();
mWeAskedForMasternodeListEntry.clear();
@ -319,8 +345,8 @@ int CMasternodeMan::CountMasternodes(int nProtocolVersion)
int nCount = 0;
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
if(mn.nProtocolVersion < nProtocolVersion) continue;
for (auto& mnpair : mapMasternodes) {
if(mnpair.second.nProtocolVersion < nProtocolVersion) continue;
nCount++;
}
@ -333,8 +359,8 @@ int CMasternodeMan::CountEnabled(int nProtocolVersion)
int nCount = 0;
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
if(mn.nProtocolVersion < nProtocolVersion || !mn.IsEnabled()) continue;
for (auto& mnpair : mapMasternodes) {
if(mnpair.second.nProtocolVersion < nProtocolVersion || !mnpair.second.IsEnabled()) continue;
nCount++;
}
@ -347,10 +373,10 @@ int CMasternodeMan::CountByIP(int nNetworkType)
LOCK(cs);
int nNodeCount = 0;
BOOST_FOREACH(CMasternode& mn, vMasternodes)
if ((nNetworkType == NET_IPV4 && mn.addr.IsIPv4()) ||
(nNetworkType == NET_TOR && mn.addr.IsTor()) ||
(nNetworkType == NET_IPV6 && mn.addr.IsIPv6())) {
for (auto& mnpair : mapMasternodes)
if ((nNetworkType == NET_IPV4 && mnpair.second.addr.IsIPv4()) ||
(nNetworkType == NET_TOR && mnpair.second.addr.IsTor()) ||
(nNetworkType == NET_IPV6 && mnpair.second.addr.IsIPv6())) {
nNodeCount++;
}
@ -379,117 +405,76 @@ void CMasternodeMan::DsegUpdate(CNode* pnode)
LogPrint("masternode", "CMasternodeMan::DsegUpdate -- asked %s for the list\n", pnode->addr.ToString());
}
CMasternode* CMasternodeMan::Find(const CScript &payee)
CMasternode* CMasternodeMan::Find(const COutPoint &outpoint)
{
LOCK(cs);
BOOST_FOREACH(CMasternode& mn, vMasternodes)
{
if(GetScriptForDestination(mn.pubKeyCollateralAddress.GetID()) == payee)
return &mn;
}
return NULL;
auto it = mapMasternodes.find(outpoint);
return it == mapMasternodes.end() ? NULL : &(it->second);
}
CMasternode* CMasternodeMan::Find(const CTxIn &vin)
{
LOCK(cs);
BOOST_FOREACH(CMasternode& mn, vMasternodes)
{
if(mn.vin.prevout == vin.prevout)
return &mn;
}
return NULL;
}
CMasternode* CMasternodeMan::Find(const CPubKey &pubKeyMasternode)
{
LOCK(cs);
BOOST_FOREACH(CMasternode& mn, vMasternodes)
{
if(mn.pubKeyMasternode == pubKeyMasternode)
return &mn;
}
return NULL;
}
bool CMasternodeMan::Get(const CPubKey& pubKeyMasternode, CMasternode& masternode)
bool CMasternodeMan::Get(const COutPoint& outpoint, CMasternode& masternodeRet)
{
// Theses mutexes are recursive so double locking by the same thread is safe.
LOCK(cs);
CMasternode* pMN = Find(pubKeyMasternode);
if(!pMN) {
auto it = mapMasternodes.find(outpoint);
if (it == mapMasternodes.end()) {
return false;
}
masternode = *pMN;
masternodeRet = it->second;
return true;
}
bool CMasternodeMan::Get(const CTxIn& vin, CMasternode& masternode)
bool CMasternodeMan::GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet)
{
// Theses mutexes are recursive so double locking by the same thread is safe.
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
auto it = mapMasternodes.find(outpoint);
if (it == mapMasternodes.end()) {
return false;
}
masternode = *pMN;
mnInfoRet = it->second.GetInfo();
return true;
}
masternode_info_t CMasternodeMan::GetMasternodeInfo(const CTxIn& vin)
bool CMasternodeMan::GetMasternodeInfo(const CPubKey& pubKeyMasternode, masternode_info_t& mnInfoRet)
{
masternode_info_t info;
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
return info;
for (auto& mnpair : mapMasternodes) {
if (mnpair.second.pubKeyMasternode == pubKeyMasternode) {
mnInfoRet = mnpair.second.GetInfo();
return true;
}
}
info = pMN->GetInfo();
return info;
return false;
}
masternode_info_t CMasternodeMan::GetMasternodeInfo(const CPubKey& pubKeyMasternode)
{
masternode_info_t info;
LOCK(cs);
CMasternode* pMN = Find(pubKeyMasternode);
if(!pMN) {
return info;
}
info = pMN->GetInfo();
return info;
}
bool CMasternodeMan::Has(const CTxIn& vin)
bool CMasternodeMan::Has(const COutPoint& outpoint)
{
LOCK(cs);
CMasternode* pMN = Find(vin);
return (pMN != NULL);
return mapMasternodes.find(outpoint) != mapMasternodes.end();
}
//
// Deterministically select the oldest/best masternode to pay on the network
//
CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCount)
bool CMasternodeMan::GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet)
{
return GetNextMasternodeInQueueForPayment(nCachedBlockHeight, fFilterSigTime, nCount);
return GetNextMasternodeInQueueForPayment(nCachedBlockHeight, fFilterSigTime, nCountRet, mnInfoRet);
}
CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCount)
bool CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet)
{
mnInfoRet = masternode_info_t();
nCountRet = 0;
if (!masternodeSync.IsWinnersListSynced()) {
// without winner list we can't reliably find the next winner anyway
nCount = 0;
return NULL;
return false;
}
// Need LOCK2 here to ensure consistent locking order because the GetBlockHash call below locks cs_main
LOCK2(cs_main,cs);
CMasternode *pBestMasternode = NULL;
std::vector<std::pair<int, CMasternode*> > vecMasternodeLastPaid;
/*
@ -497,29 +482,30 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight
*/
int nMnCount = CountEnabled();
BOOST_FOREACH(CMasternode &mn, vMasternodes)
{
if(!mn.IsValidForPayment()) continue;
for (auto& mnpair : mapMasternodes) {
if(!mnpair.second.IsValidForPayment()) continue;
//check protocol version
if(mn.nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) continue;
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(mn, nBlockHeight)) continue;
if(mnpayments.IsScheduled(mnpair.second, nBlockHeight)) continue;
//it's too new, wait for a cycle
if(fFilterSigTime && mn.sigTime + (nMnCount*2.6*60) > GetAdjustedTime()) continue;
if(fFilterSigTime && mnpair.second.sigTime + (nMnCount*2.6*60) > GetAdjustedTime()) continue;
//make sure it has at least as many confirmations as there are masternodes
if(GetUTXOConfirmations(mn.vin.prevout) < nMnCount) continue;
if(GetUTXOConfirmations(mnpair.first) < nMnCount) continue;
vecMasternodeLastPaid.push_back(std::make_pair(mn.GetLastPaidBlock(), &mn));
vecMasternodeLastPaid.push_back(std::make_pair(mnpair.second.GetLastPaidBlock(), &mnpair.second));
}
nCount = (int)vecMasternodeLastPaid.size();
nCountRet = (int)vecMasternodeLastPaid.size();
//when the network is in the process of upgrading, don't penalize nodes that recently restarted
if(fFilterSigTime && nCount < nMnCount/3) return GetNextMasternodeInQueueForPayment(nBlockHeight, false, nCount);
if(fFilterSigTime && nCountRet < nMnCount/3)
return GetNextMasternodeInQueueForPayment(nBlockHeight, false, nCountRet, mnInfoRet);
// Sort them low to high
sort(vecMasternodeLastPaid.begin(), vecMasternodeLastPaid.end(), CompareLastPaidBlock());
@ -527,7 +513,7 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight
uint256 blockHash;
if(!GetBlockHash(blockHash, nBlockHeight - 101)) {
LogPrintf("CMasternode::GetNextMasternodeInQueueForPayment -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", nBlockHeight - 101);
return NULL;
return false;
}
// Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
// -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely
@ -536,6 +522,7 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight
int nTenthNetwork = nMnCount/10;
int nCountTenth = 0;
arith_uint256 nHighest = 0;
CMasternode *pBestMasternode = NULL;
BOOST_FOREACH (PAIRTYPE(int, CMasternode*)& s, vecMasternodeLastPaid){
arith_uint256 nScore = s.second->CalculateScore(blockHash);
if(nScore > nHighest){
@ -545,10 +532,13 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight
nCountTenth++;
if(nCountTenth >= nTenthNetwork) break;
}
return pBestMasternode;
if (pBestMasternode) {
mnInfoRet = pBestMasternode->GetInfo();
}
return mnInfoRet.fInfoValid;
}
masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<CTxIn> &vecToExclude, int nProtocolVersion)
masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<COutPoint> &vecToExclude, int nProtocolVersion)
{
LOCK(cs);
@ -562,8 +552,8 @@ masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<CTxIn> &v
// fill a vector of pointers
std::vector<CMasternode*> vpMasternodesShuffled;
BOOST_FOREACH(CMasternode &mn, vMasternodes) {
vpMasternodesShuffled.push_back(&mn);
for (auto& mnpair : mapMasternodes) {
vpMasternodesShuffled.push_back(&mnpair.second);
}
InsecureRand insecureRand;
@ -575,8 +565,8 @@ masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<CTxIn> &v
BOOST_FOREACH(CMasternode* pmn, vpMasternodesShuffled) {
if(pmn->nProtocolVersion < nProtocolVersion || !pmn->IsEnabled()) continue;
fExclude = false;
BOOST_FOREACH(const CTxIn &txinToExclude, vecToExclude) {
if(pmn->vin.prevout == txinToExclude.prevout) {
BOOST_FOREACH(const COutPoint &outpointToExclude, vecToExclude) {
if(pmn->vin.prevout == outpointToExclude) {
fExclude = true;
break;
}
@ -591,7 +581,7 @@ masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<CTxIn> &v
return masternode_info_t();
}
int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int nBlockHeight, int nMinProtocol, bool fOnlyActive)
int CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int nBlockHeight, int nMinProtocol, bool fOnlyActive)
{
std::vector<std::pair<int64_t, CMasternode*> > vecMasternodeScores;
@ -602,17 +592,17 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int nBlockHeight, int nM
LOCK(cs);
// scan for winner
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
if(mn.nProtocolVersion < nMinProtocol) continue;
for (auto& mnpair : mapMasternodes) {
if(mnpair.second.nProtocolVersion < nMinProtocol) continue;
if(fOnlyActive) {
if(!mn.IsEnabled()) continue;
if(!mnpair.second.IsEnabled()) continue;
}
else {
if(!mn.IsValidForPayment()) continue;
if(!mnpair.second.IsValidForPayment()) continue;
}
int64_t nScore = mn.CalculateScore(blockHash).GetCompact(false);
int64_t nScore = mnpair.second.CalculateScore(blockHash).GetCompact(false);
vecMasternodeScores.push_back(std::make_pair(nScore, &mn));
vecMasternodeScores.push_back(std::make_pair(nScore, &mnpair.second));
}
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
@ -620,7 +610,7 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int nBlockHeight, int nM
int nRank = 0;
BOOST_FOREACH (PAIRTYPE(int64_t, CMasternode*)& scorePair, vecMasternodeScores) {
nRank++;
if(scorePair.second->vin.prevout == vin.prevout) return nRank;
if(scorePair.second->vin.prevout == outpoint) return nRank;
}
return -1;
@ -638,13 +628,13 @@ std::vector<std::pair<int, CMasternode> > CMasternodeMan::GetMasternodeRanks(int
LOCK(cs);
// scan for winner
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
for (auto& mnpair : mapMasternodes) {
if(mn.nProtocolVersion < nMinProtocol || !mn.IsEnabled()) continue;
if(mnpair.second.nProtocolVersion < nMinProtocol || !mnpair.second.IsEnabled()) continue;
int64_t nScore = mn.CalculateScore(blockHash).GetCompact(false);
int64_t nScore = mnpair.second.CalculateScore(blockHash).GetCompact(false);
vecMasternodeScores.push_back(std::make_pair(nScore, &mn));
vecMasternodeScores.push_back(std::make_pair(nScore, &mnpair.second));
}
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
@ -671,14 +661,14 @@ bool CMasternodeMan::GetMasternodeByRank(int nRank, int nBlockHeight, int nMinPr
}
// Fill scores
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
for (auto& mnpair : mapMasternodes) {
if(mn.nProtocolVersion < nMinProtocol) continue;
if(fOnlyActive && !mn.IsEnabled()) continue;
if(mnpair.second.nProtocolVersion < nMinProtocol) continue;
if(fOnlyActive && !mnpair.second.IsEnabled()) continue;
int64_t nScore = mn.CalculateScore(blockHash).GetCompact(false);
int64_t nScore = mnpair.second.CalculateScore(blockHash).GetCompact(false);
vecMasternodeScores.push_back(std::make_pair(nScore, &mn));
vecMasternodeScores.push_back(std::make_pair(nScore, &mnpair.second));
}
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
@ -702,7 +692,8 @@ void CMasternodeMan::ProcessMasternodeConnections()
g_connman->ForEachNode(CConnman::AllNodes, [](CNode* pnode) {
if(pnode->fMasternode) {
if(privateSendClient.infoMixingMasternode.fInfoValid && pnode->addr == privateSendClient.infoMixingMasternode.addr) return true;
if(privateSendClient.infoMixingMasternode.fInfoValid && pnode->addr == privateSendClient.infoMixingMasternode.addr)
return;
LogPrintf("Closing Masternode connection: peer=%d, addr=%s\n", pnode->id, pnode->addr.ToString());
pnode->fDisconnect = true;
}
@ -783,7 +774,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
LogPrint("masternode", "MNPING -- Masternode ping, masternode=%s new\n", mnp.vin.prevout.ToStringShort());
// see if we have this Masternode
CMasternode* pmn = mnodeman.Find(mnp.vin);
CMasternode* pmn = Find(mnp.vin.prevout);
// if masternode uses sentinel ping instead of watchdog
// we shoud update nTimeLastWatchdogVote here if sentinel
@ -807,7 +798,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
// something significant is broken or mn is unknown,
// we might have to ask for a masternode entry once
AskForMN(pfrom, mnp.vin);
AskForMN(pfrom, mnp.vin.prevout);
} else if (strCommand == NetMsgType::DSEG) { //Get Masternode list or specific entry
// Ignore such requests until we are fully synced.
@ -840,23 +831,23 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
int nInvCount = 0;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
if (vin != CTxIn() && vin != mn.vin) continue; // asked for specific vin but we are not there yet
if (mn.addr.IsRFC1918() || mn.addr.IsLocal()) continue; // do not send local network masternode
if (mn.IsUpdateRequired()) continue; // do not send outdated masternodes
for (auto& mnpair : mapMasternodes) {
if (vin != CTxIn() && vin != mnpair.second.vin) continue; // asked for specific vin but we are not there yet
if (mnpair.second.addr.IsRFC1918() || mnpair.second.addr.IsLocal()) continue; // do not send local network masternode
if (mnpair.second.IsUpdateRequired()) continue; // do not send outdated masternodes
LogPrint("masternode", "DSEG -- Sending Masternode entry: masternode=%s addr=%s\n", mn.vin.prevout.ToStringShort(), mn.addr.ToString());
CMasternodeBroadcast mnb = CMasternodeBroadcast(mn);
LogPrint("masternode", "DSEG -- Sending Masternode entry: masternode=%s addr=%s\n", mnpair.first.ToStringShort(), mnpair.second.addr.ToString());
CMasternodeBroadcast mnb = CMasternodeBroadcast(mnpair.second);
uint256 hash = mnb.GetHash();
pfrom->PushInventory(CInv(MSG_MASTERNODE_ANNOUNCE, hash));
pfrom->PushInventory(CInv(MSG_MASTERNODE_PING, mn.lastPing.GetHash()));
pfrom->PushInventory(CInv(MSG_MASTERNODE_PING, mnpair.second.lastPing.GetHash()));
nInvCount++;
if (!mapSeenMasternodeBroadcast.count(hash)) {
mapSeenMasternodeBroadcast.insert(std::make_pair(hash, std::make_pair(GetTime(), mnb)));
}
if (vin == mn.vin) {
if (vin.prevout == mnpair.first) {
LogPrintf("DSEG -- Sent 1 Masternode inv to peer %d\n", pfrom->id);
return;
}
@ -895,7 +886,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
void CMasternodeMan::DoFullVerificationStep()
{
if(activeMasternode.vin == CTxIn()) return;
if(activeMasternode.outpoint == COutPoint()) return;
if(!masternodeSync.IsSynced()) return;
std::vector<std::pair<int, CMasternode> > vecMasternodeRanks = GetMasternodeRanks(nCachedBlockHeight - 1, MIN_POSE_PROTO_VERSION);
@ -917,7 +908,7 @@ void CMasternodeMan::DoFullVerificationStep()
(int)MAX_POSE_RANK);
return;
}
if(it->second.vin == activeMasternode.vin) {
if(it->second.vin.prevout == activeMasternode.outpoint) {
nMyRank = it->first;
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Found self at rank %d/%d, verifying up to %d masternodes\n",
nMyRank, nRanksTotal, (int)MAX_POSE_CONNECTIONS);
@ -935,8 +926,8 @@ void CMasternodeMan::DoFullVerificationStep()
if(nOffset >= (int)vecMasternodeRanks.size()) return;
std::vector<CMasternode*> vSortedByAddr;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
vSortedByAddr.push_back(&mn);
for (auto& mnpair : mapMasternodes) {
vSortedByAddr.push_back(&mnpair.second);
}
sort(vSortedByAddr.begin(), vSortedByAddr.end(), CompareByAddr());
@ -975,7 +966,7 @@ void CMasternodeMan::DoFullVerificationStep()
void CMasternodeMan::CheckSameAddr()
{
if(!masternodeSync.IsSynced() || vMasternodes.empty()) return;
if(!masternodeSync.IsSynced() || mapMasternodes.empty()) return;
std::vector<CMasternode*> vBan;
std::vector<CMasternode*> vSortedByAddr;
@ -986,8 +977,8 @@ void CMasternodeMan::CheckSameAddr()
CMasternode* pprevMasternode = NULL;
CMasternode* pverifiedMasternode = NULL;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
vSortedByAddr.push_back(&mn);
for (auto& mnpair : mapMasternodes) {
vSortedByAddr.push_back(&mnpair.second);
}
sort(vSortedByAddr.begin(), vSortedByAddr.end(), CompareByAddr());
@ -1137,24 +1128,23 @@ void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& m
CMasternode* prealMasternode = NULL;
std::vector<CMasternode*> vpMasternodesToBan;
std::vector<CMasternode>::iterator it = vMasternodes.begin();
std::string strMessage1 = strprintf("%s%d%s", pnode->addr.ToString(false), mnv.nonce, blockHash.ToString());
while(it != vMasternodes.end()) {
if(CAddress(it->addr, NODE_NETWORK) == pnode->addr) {
if(CMessageSigner::VerifyMessage(it->pubKeyMasternode, mnv.vchSig1, strMessage1, strError)) {
for (auto& mnpair : mapMasternodes) {
if(CAddress(mnpair.second.addr, NODE_NETWORK) == pnode->addr) {
if(CMessageSigner::VerifyMessage(mnpair.second.pubKeyMasternode, mnv.vchSig1, strMessage1, strError)) {
// found it!
prealMasternode = &(*it);
if(!it->IsPoSeVerified()) {
it->DecreasePoSeBanScore();
prealMasternode = &mnpair.second;
if(!mnpair.second.IsPoSeVerified()) {
mnpair.second.DecreasePoSeBanScore();
}
netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-done");
// we can only broadcast it if we are an activated masternode
if(activeMasternode.vin == CTxIn()) continue;
if(activeMasternode.outpoint == COutPoint()) continue;
// update ...
mnv.addr = it->addr;
mnv.vin1 = it->vin;
mnv.vin2 = activeMasternode.vin;
mnv.addr = mnpair.second.addr;
mnv.vin1 = mnpair.second.vin;
mnv.vin2 = CTxIn(activeMasternode.outpoint);
std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
mnv.vin1.prevout.ToStringShort(), mnv.vin2.prevout.ToStringShort());
// ... and sign it
@ -1174,10 +1164,9 @@ void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& m
mnv.Relay();
} else {
vpMasternodesToBan.push_back(&(*it));
vpMasternodesToBan.push_back(&mnpair.second);
}
}
++it;
}
// no real masternode found?...
if(!prealMasternode) {
@ -1233,7 +1222,7 @@ void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerif
return;
}
int nRank = GetMasternodeRank(mnv.vin2, mnv.nBlockHeight, MIN_POSE_PROTO_VERSION);
int nRank = GetMasternodeRank(mnv.vin2.prevout, mnv.nBlockHeight, MIN_POSE_PROTO_VERSION);
if (nRank == -1) {
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Can't calculate rank for masternode %s\n",
@ -1254,13 +1243,13 @@ void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerif
std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
mnv.vin1.prevout.ToStringShort(), mnv.vin2.prevout.ToStringShort());
CMasternode* pmn1 = Find(mnv.vin1);
CMasternode* pmn1 = Find(mnv.vin1.prevout);
if(!pmn1) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode1 %s\n", mnv.vin1.prevout.ToStringShort());
return;
}
CMasternode* pmn2 = Find(mnv.vin2);
CMasternode* pmn2 = Find(mnv.vin2.prevout);
if(!pmn2) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode2 %s\n", mnv.vin2.prevout.ToStringShort());
return;
@ -1291,12 +1280,12 @@ void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerif
// increase ban score for everyone else with the same addr
int nCount = 0;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
if(mn.addr != mnv.addr || mn.vin.prevout == mnv.vin1.prevout) continue;
mn.IncreasePoSeBanScore();
for (auto& mnpair : mapMasternodes) {
if(mnpair.second.addr != mnv.addr || mnpair.first == mnv.vin1.prevout) continue;
mnpair.second.IncreasePoSeBanScore();
nCount++;
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- increased PoSe ban score for %s addr %s, new score %d\n",
mn.vin.prevout.ToStringShort(), mn.addr.ToString(), mn.nPoSeBanScore);
mnpair.first.ToStringShort(), mnpair.second.addr.ToString(), mnpair.second.nPoSeBanScore);
}
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- PoSe score incresed for %d fake masternodes, addr %s\n",
nCount, pnode->addr.ToString());
@ -1307,7 +1296,7 @@ std::string CMasternodeMan::ToString() const
{
std::ostringstream info;
info << "Masternodes: " << (int)vMasternodes.size() <<
info << "Masternodes: " << (int)mapMasternodes.size() <<
", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size() <<
", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size() <<
", entries in Masternode list we asked for: " << (int)mWeAskedForMasternodeListEntry.size() <<
@ -1324,7 +1313,7 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb)
LogPrintf("CMasternodeMan::UpdateMasternodeList -- masternode=%s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString());
CMasternode* pmn = Find(mnb.vin);
CMasternode* pmn = Find(mnb.vin.prevout);
if(pmn == NULL) {
if(Add(mnb)) {
masternodeSync.BumpAssetLastTime("CMasternodeMan::UpdateMasternodeList - new");
@ -1390,7 +1379,7 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBr
}
// search Masternode list
CMasternode* pmn = Find(mnb.vin);
CMasternode* pmn = Find(mnb.vin.prevout);
if(pmn) {
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second;
if(!mnb.Update(pmn, nDos)) {
@ -1435,7 +1424,7 @@ void CMasternodeMan::UpdateLastPaid(const CBlockIndex* pindex)
{
LOCK(cs);
if(fLiteMode || !masternodeSync.IsWinnersListSynced() || vMasternodes.empty()) return;
if(fLiteMode || !masternodeSync.IsWinnersListSynced() || mapMasternodes.empty()) return;
static bool IsFirstRun = true;
// Do full scan on first run or if we are not a masternode
@ -1445,34 +1434,21 @@ void CMasternodeMan::UpdateLastPaid(const CBlockIndex* pindex)
// LogPrint("mnpayments", "CMasternodeMan::UpdateLastPaid -- nHeight=%d, nMaxBlocksToScanBack=%d, IsFirstRun=%s\n",
// nCachedBlockHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false");
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
mn.UpdateLastPaid(pindex, nMaxBlocksToScanBack);
for (auto& mnpair: mapMasternodes) {
mnpair.second.UpdateLastPaid(pindex, nMaxBlocksToScanBack);
}
IsFirstRun = false;
}
bool CMasternodeMan::UpdateLastDsq(const CTxIn& vin)
{
masternode_info_t info;
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN)
return false;
pMN->nLastDsq = nDsqCount;
pMN->fAllowMixingTx = true;
return true;
}
void CMasternodeMan::UpdateWatchdogVoteTime(const CTxIn& vin)
void CMasternodeMan::UpdateWatchdogVoteTime(const COutPoint& outpoint)
{
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
CMasternode* pmn = Find(outpoint);
if(!pmn) {
return;
}
pMN->UpdateWatchdogVoteTime();
pmn->UpdateWatchdogVoteTime();
nLastWatchdogVoteTime = GetTime();
}
@ -1483,91 +1459,60 @@ bool CMasternodeMan::IsWatchdogActive()
return (GetTime() - nLastWatchdogVoteTime) <= MASTERNODE_WATCHDOG_MAX_SECONDS;
}
bool CMasternodeMan::AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash)
bool CMasternodeMan::AddGovernanceVote(const COutPoint& outpoint, uint256 nGovernanceObjectHash)
{
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
CMasternode* pmn = Find(outpoint);
if(!pmn) {
return false;
}
pMN->AddGovernanceVote(nGovernanceObjectHash);
pmn->AddGovernanceVote(nGovernanceObjectHash);
return true;
}
void CMasternodeMan::RemoveGovernanceObject(uint256 nGovernanceObjectHash)
{
LOCK(cs);
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
mn.RemoveGovernanceObject(nGovernanceObjectHash);
for(auto& mnpair : mapMasternodes) {
mnpair.second.RemoveGovernanceObject(nGovernanceObjectHash);
}
}
void CMasternodeMan::CheckMasternode(const CTxIn& vin, bool fForce)
{
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
return;
}
pMN->Check(fForce);
}
void CMasternodeMan::CheckMasternode(const CPubKey& pubKeyMasternode, bool fForce)
{
LOCK(cs);
CMasternode* pMN = Find(pubKeyMasternode);
if(!pMN) {
for (auto& mnpair : mapMasternodes) {
if (mnpair.second.pubKeyMasternode == pubKeyMasternode) {
mnpair.second.Check(fForce);
return;
}
}
}
bool CMasternodeMan::IsMasternodePingedWithin(const COutPoint& outpoint, int nSeconds, int64_t nTimeToCheckAt)
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
return pmn ? pmn->IsPingedWithin(nSeconds, nTimeToCheckAt) : false;
}
void CMasternodeMan::SetMasternodeLastPing(const COutPoint& outpoint, const CMasternodePing& mnp)
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
if(!pmn) {
return;
}
pMN->Check(fForce);
}
int CMasternodeMan::GetMasternodeState(const CTxIn& vin)
{
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
return CMasternode::MASTERNODE_NEW_START_REQUIRED;
}
return pMN->nActiveState;
}
int CMasternodeMan::GetMasternodeState(const CPubKey& pubKeyMasternode)
{
LOCK(cs);
CMasternode* pMN = Find(pubKeyMasternode);
if(!pMN) {
return CMasternode::MASTERNODE_NEW_START_REQUIRED;
}
return pMN->nActiveState;
}
bool CMasternodeMan::IsMasternodePingedWithin(const CTxIn& vin, int nSeconds, int64_t nTimeToCheckAt)
{
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
return false;
}
return pMN->IsPingedWithin(nSeconds, nTimeToCheckAt);
}
void CMasternodeMan::SetMasternodeLastPing(const CTxIn& vin, const CMasternodePing& mnp)
{
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
return;
}
pMN->lastPing = mnp;
pmn->lastPing = mnp;
// if masternode uses sentinel ping instead of watchdog
// we shoud update nTimeLastWatchdogVote here if sentinel
// ping flag is actual
if(mnp.fSentinelIsCurrent)
pMN->UpdateWatchdogVoteTime(mnp.sigTime);
if(mnp.fSentinelIsCurrent) {
pmn->UpdateWatchdogVoteTime(mnp.sigTime);
}
mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp));
CMasternodeBroadcast mnb(*pMN);
CMasternodeBroadcast mnb(*pmn);
uint256 hash = mnb.GetHash();
if(mapSeenMasternodeBroadcast.count(hash)) {
mapSeenMasternodeBroadcast[hash].second.lastPing = mnp;

View File

@ -44,7 +44,7 @@ private:
int nCachedBlockHeight;
// map to hold all MNs
std::vector<CMasternode> vMasternodes;
std::map<COutPoint, CMasternode> mapMasternodes;
// who's asked for the Masternode list and the last time
std::map<CNetAddr, int64_t> mAskedUsForMasternodeList;
// who we asked for the Masternode list and the last time
@ -70,6 +70,8 @@ private:
int64_t nLastWatchdogVoteTime;
friend class CMasternodeSync;
/// Find an entry
CMasternode* Find(const COutPoint& outpoint);
public:
// Keep track of all broadcasts I've seen
@ -96,7 +98,7 @@ public:
READWRITE(strVersion);
}
READWRITE(vMasternodes);
READWRITE(mapMasternodes);
READWRITE(mAskedUsForMasternodeList);
READWRITE(mWeAskedForMasternodeList);
READWRITE(mWeAskedForMasternodeListEntry);
@ -118,9 +120,13 @@ public:
bool Add(CMasternode &mn);
/// Ask (source) node for mnb
void AskForMN(CNode *pnode, const CTxIn &vin);
void AskForMN(CNode *pnode, const COutPoint& outpoint);
void AskForMnb(CNode *pnode, const uint256 &hash);
bool PoSeBan(const COutPoint &outpoint);
bool AllowMixing(const COutPoint &outpoint);
bool DisallowMixing(const COutPoint &outpoint);
/// Check all Masternodes
void Check();
@ -142,32 +148,26 @@ public:
void DsegUpdate(CNode* pnode);
/// Find an entry
CMasternode* Find(const CScript &payee);
CMasternode* Find(const CTxIn& vin);
CMasternode* Find(const CPubKey& pubKeyMasternode);
/// Versions of Find that are safe to use from outside the class
bool Get(const CPubKey& pubKeyMasternode, CMasternode& masternode);
bool Get(const CTxIn& vin, CMasternode& masternode);
bool Has(const CTxIn& vin);
bool Get(const COutPoint& outpoint, CMasternode& masternodeRet);
bool Has(const COutPoint& outpoint);
masternode_info_t GetMasternodeInfo(const CTxIn& vin);
bool GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet);
masternode_info_t GetMasternodeInfo(const CPubKey& pubKeyMasternode);
bool GetMasternodeInfo(const CPubKey& pubKeyMasternode, masternode_info_t& mnInfoRet);
/// Find an entry in the masternode list that is next to be paid
CMasternode* GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCount);
bool GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet);
/// Same as above but use current block height
CMasternode* GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCount);
bool GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet);
/// Find a random entry
masternode_info_t FindRandomNotInVec(const std::vector<CTxIn> &vecToExclude, int nProtocolVersion = -1);
masternode_info_t FindRandomNotInVec(const std::vector<COutPoint> &vecToExclude, int nProtocolVersion = -1);
std::vector<CMasternode> GetFullMasternodeVector() { return vMasternodes; }
std::map<COutPoint, CMasternode> GetFullMasternodeMap() { return mapMasternodes; }
std::vector<std::pair<int, CMasternode> > GetMasternodeRanks(int nBlockHeight = -1, int nMinProtocol=0);
int GetMasternodeRank(const CTxIn &vin, int nBlockHeight, int nMinProtocol=0, bool fOnlyActive=true);
int GetMasternodeRank(const COutPoint &outpoint, int nBlockHeight, int nMinProtocol=0, bool fOnlyActive=true);
bool GetMasternodeByRank(int nRank, int nBlockHeight, int nMinProtocol, bool fOnlyActive, masternode_info_t& mnInfoRet);
void ProcessMasternodeConnections();
@ -183,7 +183,7 @@ public:
void ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerification& mnv);
/// Return the number of (unique) Masternodes
int size() { return vMasternodes.size(); }
int size() { return mapMasternodes.size(); }
std::string ToString() const;
@ -194,7 +194,6 @@ public:
bool IsMnbRecoveryRequested(const uint256& hash) { return mMnbRecoveryRequests.count(hash); }
void UpdateLastPaid(const CBlockIndex* pindex);
bool UpdateLastDsq(const CTxIn& vin);
void AddDirtyGovernanceObjectHash(const uint256& nHash)
{
@ -211,18 +210,14 @@ public:
}
bool IsWatchdogActive();
void UpdateWatchdogVoteTime(const CTxIn& vin);
bool AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash);
void UpdateWatchdogVoteTime(const COutPoint& outpoint);
bool AddGovernanceVote(const COutPoint& outpoint, uint256 nGovernanceObjectHash);
void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
void CheckMasternode(const CTxIn& vin, bool fForce = false);
void CheckMasternode(const CPubKey& pubKeyMasternode, bool fForce = false);
void CheckMasternode(const CPubKey& pubKeyMasternode, bool fForce);
int GetMasternodeState(const CTxIn& vin);
int GetMasternodeState(const CPubKey& pubKeyMasternode);
bool IsMasternodePingedWithin(const CTxIn& vin, int nSeconds, int64_t nTimeToCheckAt = -1);
void SetMasternodeLastPing(const CTxIn& vin, const CMasternodePing& mnp);
bool IsMasternodePingedWithin(const COutPoint& outpoint, int nSeconds, int64_t nTimeToCheckAt = -1);
void SetMasternodeLastPing(const COutPoint& outpoint, const CMasternodePing& mnp);
void UpdatedBlockTip(const CBlockIndex *pindex);

View File

@ -1590,27 +1590,28 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true; // not an error
}
CMasternode* pmn = mnodeman.Find(dstx.vin);
if(pmn == NULL) {
CMasternode mn;
if(!mnodeman.Get(dstx.vin.prevout, mn)) {
LogPrint("privatesend", "DSTX -- Can't find masternode %s to verify %s\n", dstx.vin.prevout.ToStringShort(), hashTx.ToString());
return false;
}
if(!pmn->fAllowMixingTx) {
if(!mn.fAllowMixingTx) {
LogPrint("privatesend", "DSTX -- Masternode %s is sending too many transactions %s\n", dstx.vin.prevout.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(pmn->pubKeyMasternode)) {
if(!dstx.CheckSignature(mn.pubKeyMasternode)) {
LogPrint("privatesend", "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString());
return false;
}
LogPrintf("DSTX -- Got Masternode transaction %s\n", hashTx.ToString());
mempool.PrioritiseTransaction(hashTx, hashTx.ToString(), 1000, 0.1*COIN);
pmn->fAllowMixingTx = false;
mnodeman.DisallowMixing(dstx.vin.prevout);
}
LOCK(cs_main);

View File

@ -48,12 +48,12 @@ void CPrivateSendClient::ProcessMessage(CNode* pfrom, std::string& strCommand, C
if(dsq.IsExpired()) return;
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(dsq.vin);
if(!infoMn.fInfoValid) return;
masternode_info_t infoMn;
if(!mnodeman.GetMasternodeInfo(dsq.vin.prevout, infoMn)) return;
if(!dsq.CheckSignature(infoMn.pubKeyMasternode)) {
// we probably have outdated info
mnodeman.AskForMN(pfrom, dsq.vin);
mnodeman.AskForMN(pfrom, dsq.vin.prevout);
return;
}
@ -85,9 +85,8 @@ void CPrivateSendClient::ProcessMessage(CNode* pfrom, std::string& strCommand, C
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", infoMn.addr.ToString());
return;
}
mnodeman.nDsqCount++;
if(!mnodeman.UpdateLastDsq(dsq.vin)) return;
if(!mnodeman.AllowMixing(dsq.vin.prevout)) return;
LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), infoMn.addr.ToString());
if(infoMixingMasternode.fInfoValid && infoMixingMasternode.vin.prevout == dsq.vin.prevout) {
@ -826,9 +825,9 @@ bool CPrivateSendClient::JoinExistingQueue(CAmount nBalanceNeedsAnonymized)
if(dsq.IsExpired()) continue;
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(dsq.vin);
masternode_info_t infoMn;
if(!infoMn.fInfoValid) {
if(!mnodeman.GetMasternodeInfo(dsq.vin.prevout, infoMn)) {
LogPrintf("CPrivateSendClient::JoinExistingQueue -- dsq masternode is not in masternode list, masternode=%s\n", dsq.vin.prevout.ToStringShort());
continue;
}
@ -857,7 +856,7 @@ bool CPrivateSendClient::JoinExistingQueue(CAmount nBalanceNeedsAnonymized)
continue;
}
vecMasternodesUsed.push_back(dsq.vin);
vecMasternodesUsed.push_back(dsq.vin.prevout);
CNode* pnodeFound = NULL;
bool fDisconnect = false;
@ -923,7 +922,7 @@ bool CPrivateSendClient::StartNewQueue(CAmount nValueMin, CAmount nBalanceNeedsA
strAutoDenomResult = _("Can't find random Masternode.");
return false;
}
vecMasternodesUsed.push_back(infoMn.vin);
vecMasternodesUsed.push_back(infoMn.vin.prevout);
if(infoMn.nLastDsq != 0 && infoMn.nLastDsq + nMnCountEnabled/5 > mnodeman.nDsqCount) {
LogPrintf("CPrivateSendClient::StartNewQueue -- Too early to mix on this masternode!"

View File

@ -36,7 +36,7 @@ private:
mutable CCriticalSection cs_darksend;
// Keep track of the used Masternodes
std::vector<CTxIn> vecMasternodesUsed;
std::vector<COutPoint> vecMasternodesUsed;
std::vector<CAmount> vecDenominationsSkipped;
std::vector<COutPoint> vecOutPointLocked;

View File

@ -42,14 +42,14 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, std::string& strCommand, C
LogPrint("privatesend", "DSACCEPT -- nDenom %d (%s) txCollateral %s", nDenom, CPrivateSend::GetDenominationsToString(nDenom), txCollateral.ToString());
CMasternode* pmn = mnodeman.Find(activeMasternode.vin);
if(pmn == NULL) {
masternode_info_t mnInfo;
if(!mnodeman.GetMasternodeInfo(activeMasternode.outpoint, mnInfo)) {
PushStatus(pfrom, STATUS_REJECTED, ERR_MN_LIST);
return;
}
if(vecSessionCollaterals.size() == 0 && pmn->nLastDsq != 0 &&
pmn->nLastDsq + mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)/5 > mnodeman.nDsqCount)
if(vecSessionCollaterals.size() == 0 && mnInfo.nLastDsq != 0 &&
mnInfo.nLastDsq + mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)/5 > mnodeman.nDsqCount)
{
LogPrintf("DSACCEPT -- last dsq too recent, must wait: addr=%s\n", pfrom->addr.ToString());
PushStatus(pfrom, STATUS_REJECTED, ERR_RECENT);
@ -94,12 +94,12 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, std::string& strCommand, C
if(dsq.IsExpired()) return;
CMasternode* pmn = mnodeman.Find(dsq.vin);
if(pmn == NULL) return;
masternode_info_t mnInfo;
if(!mnodeman.GetMasternodeInfo(dsq.vin.prevout, mnInfo)) return;
if(!dsq.CheckSignature(pmn->pubKeyMasternode)) {
if(!dsq.CheckSignature(mnInfo.pubKeyMasternode)) {
// we probably have outdated info
mnodeman.AskForMN(pfrom, dsq.vin);
mnodeman.AskForMN(pfrom, dsq.vin.prevout);
return;
}
@ -107,23 +107,21 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, std::string& strCommand, C
BOOST_FOREACH(CDarksendQueue q, vecDarksendQueue) {
if(q.vin == dsq.vin) {
// 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", pmn->addr.ToString());
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", mnInfo.addr.ToString());
return;
}
}
int nThreshold = pmn->nLastDsq + mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)/5;
LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", pmn->nLastDsq, nThreshold, mnodeman.nDsqCount);
int nThreshold = mnInfo.nLastDsq + mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)/5;
LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", mnInfo.nLastDsq, nThreshold, mnodeman.nDsqCount);
//don't allow a few nodes to dominate the queuing process
if(pmn->nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) {
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", pmn->addr.ToString());
if(mnInfo.nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) {
LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", mnInfo.addr.ToString());
return;
}
mnodeman.nDsqCount++;
pmn->nLastDsq = mnodeman.nDsqCount;
pmn->fAllowMixingTx = true;
mnodeman.AllowMixing(dsq.vin.prevout);
LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), pmn->addr.ToString());
LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), mnInfo.addr.ToString());
vecDarksendQueue.push_back(dsq);
dsq.Relay();
}
@ -358,7 +356,7 @@ void CPrivateSendServer::CommitFinalTransaction()
// create and sign masternode dstx transaction
if(!CPrivateSend::GetDSTX(hashTx)) {
CDarksendBroadcastTx dstxNew(finalTransaction, activeMasternode.vin, GetAdjustedTime());
CDarksendBroadcastTx dstxNew(finalTransaction, activeMasternode.outpoint, GetAdjustedTime());
dstxNew.Sign();
CPrivateSend::AddDSTX(dstxNew);
}
@ -537,7 +535,7 @@ void CPrivateSendServer::CheckForCompleteQueue()
if(nState == POOL_STATE_QUEUE && IsSessionReady()) {
SetState(POOL_STATE_ACCEPTING_ENTRIES);
CDarksendQueue dsq(nSessionDenom, activeMasternode.vin, GetAdjustedTime(), true);
CDarksendQueue dsq(nSessionDenom, activeMasternode.outpoint, GetAdjustedTime(), true);
LogPrint("privatesend", "CPrivateSendServer::CheckForCompleteQueue -- queue is ready, signing and relaying (%s)\n", dsq.ToString());
dsq.Sign();
dsq.Relay();
@ -744,7 +742,7 @@ bool CPrivateSendServer::CreateNewSession(int nDenom, CTransaction txCollateral,
if(!fUnitTest) {
//broadcast that I'm accepting entries, only if it's the first entry through
CDarksendQueue dsq(nDenom, activeMasternode.vin, GetAdjustedTime(), false);
CDarksendQueue dsq(nDenom, activeMasternode.outpoint, GetAdjustedTime(), false);
LogPrint("privatesend", "CPrivateSendServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString());
dsq.Sign();
dsq.Relay();

View File

@ -165,9 +165,9 @@ public:
fTried(false)
{}
CDarksendQueue(int nDenom, CTxIn vin, int64_t nTime, bool fReady) :
CDarksendQueue(int nDenom, COutPoint outpoint, int64_t nTime, bool fReady) :
nDenom(nDenom),
vin(vin),
vin(CTxIn(outpoint)),
nTime(nTime),
fReady(fReady),
vchSig(std::vector<unsigned char>()),
@ -236,10 +236,10 @@ public:
sigTime(0)
{}
CDarksendBroadcastTx(CTransaction tx, CTxIn vin, int64_t sigTime) :
CDarksendBroadcastTx(CTransaction tx, COutPoint outpoint, int64_t sigTime) :
nConfirmedHeight(-1),
tx(tx),
vin(vin),
vin(CTxIn(outpoint)),
vchSig(),
sigTime(sigTime)
{}

View File

@ -438,8 +438,7 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
else {
coinControl->Select(outpt);
CTxIn txin = CTxIn(outpt);
int nRounds = pwalletMain->GetInputPrivateSendRounds(txin);
int nRounds = pwalletMain->GetOutpointPrivateSendRounds(outpt);
if (coinControl->fUsePrivateSend && nRounds < privateSendClient.nPrivateSendRounds) {
QMessageBox::warning(this, windowTitle(),
tr("Non-anonymized input selected. <b>PrivateSend will be disabled.</b><br><br>If you still want to use PrivateSend, please deselect all non-nonymized inputs first and then check PrivateSend checkbox again."),
@ -788,8 +787,8 @@ void CoinControlDialog::updateView()
// PrivateSend rounds
CTxIn txin = CTxIn(out.tx->GetHash(), out.i);
int nRounds = pwalletMain->GetInputPrivateSendRounds(txin);
COutPoint outpoint = COutPoint(out.tx->GetHash(), out.i);
int nRounds = pwalletMain->GetOutpointPrivateSendRounds(outpoint);
if (nRounds >= 0 || fDebug) itemOutput->setText(COLUMN_PRIVATESEND_ROUNDS, strPad(QString::number(nRounds), 11, " "));
else itemOutput->setText(COLUMN_PRIVATESEND_ROUNDS, strPad(QString(tr("n/a")), 11, " "));

View File

@ -135,9 +135,9 @@ void MasternodeList::StartAll(std::string strCommand)
continue;
}
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), nOutputIndex);
COutPoint outpoint = COutPoint(uint256S(mne.getTxHash()), nOutputIndex);
if(strCommand == "start-missing" && mnodeman.Has(txin)) continue;
if(strCommand == "start-missing" && mnodeman.Has(outpoint)) continue;
bool fSuccess = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
@ -166,7 +166,7 @@ void MasternodeList::StartAll(std::string strCommand)
updateMyNodeList(true);
}
void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, masternode_info_t& infoMn)
void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, const COutPoint& outpoint)
{
bool fOldRowFound = false;
int nNewRow = 0;
@ -184,14 +184,17 @@ void MasternodeList::updateMyMasternodeInfo(QString strAlias, QString strAddr, m
ui->tableWidgetMyMasternodes->insertRow(nNewRow);
}
masternode_info_t infoMn;
bool fFound = mnodeman.GetMasternodeInfo(outpoint, infoMn);
QTableWidgetItem *aliasItem = new QTableWidgetItem(strAlias);
QTableWidgetItem *addrItem = new QTableWidgetItem(infoMn.fInfoValid ? QString::fromStdString(infoMn.addr.ToString()) : strAddr);
QTableWidgetItem *protocolItem = new QTableWidgetItem(QString::number(infoMn.fInfoValid ? infoMn.nProtocolVersion : -1));
QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(infoMn.fInfoValid ? CMasternode::StateToString(infoMn.nActiveState) : "MISSING"));
QTableWidgetItem *activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(infoMn.fInfoValid ? (infoMn.nTimeLastPing - infoMn.sigTime) : 0)));
QTableWidgetItem *addrItem = new QTableWidgetItem(fFound ? QString::fromStdString(infoMn.addr.ToString()) : strAddr);
QTableWidgetItem *protocolItem = new QTableWidgetItem(QString::number(fFound ? infoMn.nProtocolVersion : -1));
QTableWidgetItem *statusItem = new QTableWidgetItem(QString::fromStdString(fFound ? CMasternode::StateToString(infoMn.nActiveState) : "MISSING"));
QTableWidgetItem *activeSecondsItem = new QTableWidgetItem(QString::fromStdString(DurationToDHMS(fFound ? (infoMn.nTimeLastPing - infoMn.sigTime) : 0)));
QTableWidgetItem *lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat("%Y-%m-%d %H:%M",
infoMn.fInfoValid ? infoMn.nTimeLastPing + QDateTime::currentDateTime().offsetFromUtc() : 0)));
QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(infoMn.fInfoValid ? CBitcoinAddress(infoMn.pubKeyCollateralAddress.GetID()).ToString() : ""));
fFound ? infoMn.nTimeLastPing + QDateTime::currentDateTime().offsetFromUtc() : 0)));
QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(fFound ? CBitcoinAddress(infoMn.pubKeyCollateralAddress.GetID()).ToString() : ""));
ui->tableWidgetMyMasternodes->setItem(nNewRow, 0, aliasItem);
ui->tableWidgetMyMasternodes->setItem(nNewRow, 1, addrItem);
@ -225,11 +228,7 @@ void MasternodeList::updateMyNodeList(bool fForce)
continue;
}
CTxIn txin = CTxIn(uint256S(mne.getTxHash()), nOutputIndex);
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(txin);
updateMyMasternodeInfo(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), infoMn);
updateMyMasternodeInfo(QString::fromStdString(mne.getAlias()), QString::fromStdString(mne.getIp()), COutPoint(uint256S(mne.getTxHash()), nOutputIndex));
}
ui->tableWidgetMasternodes->setSortingEnabled(true);
@ -263,10 +262,11 @@ void MasternodeList::updateNodeList()
ui->tableWidgetMasternodes->setSortingEnabled(false);
ui->tableWidgetMasternodes->clearContents();
ui->tableWidgetMasternodes->setRowCount(0);
std::vector<CMasternode> vMasternodes = mnodeman.GetFullMasternodeVector();
std::map<COutPoint, CMasternode> mapMasternodes = mnodeman.GetFullMasternodeMap();
BOOST_FOREACH(CMasternode& mn, vMasternodes)
for(auto& mnpair : mapMasternodes)
{
CMasternode mn = mnpair.second;
// populate list
// Address, Protocol, Status, Active Seconds, Last Seen, Pub Key
QTableWidgetItem *addressItem = new QTableWidgetItem(QString::fromStdString(mn.addr.ToString()));

View File

@ -1,7 +1,7 @@
#ifndef MASTERNODELIST_H
#define MASTERNODELIST_H
#include "masternode.h"
#include "primitives/transaction.h"
#include "platformstyle.h"
#include "sync.h"
#include "util.h"
@ -45,7 +45,7 @@ private:
bool fFilterUpdated;
public Q_SLOTS:
void updateMyMasternodeInfo(QString strAlias, QString strAddr, masternode_info_t& infoMn);
void updateMyMasternodeInfo(QString strAlias, QString strAddr, const COutPoint& outpoint);
void updateMyNodeList(bool fForce = false);
void updateNodeList();

View File

@ -92,7 +92,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
{
if(wallet->IsMine(txin)) {
fAllFromMeDenom = fAllFromMeDenom && wallet->IsDenominated(txin);
fAllFromMeDenom = fAllFromMeDenom && wallet->IsDenominated(txin.prevout);
nFromMe++;
}
isminetype mine = wallet->IsMine(txin);

View File

@ -190,11 +190,10 @@ UniValue gobject(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Must wait for client to sync with masternode network. Try again in a minute or so.");
}
CMasternode mn;
bool fMnFound = mnodeman.Get(activeMasternode.vin, mn);
bool fMnFound = mnodeman.Has(activeMasternode.outpoint);
DBG( cout << "gobject: submit activeMasternode.pubKeyMasternode = " << activeMasternode.pubKeyMasternode.GetHash().ToString()
<< ", vin = " << activeMasternode.vin.prevout.ToStringShort()
<< ", outpoint = " << activeMasternode.outpoint.ToStringShort()
<< ", params.size() = " << params.size()
<< ", fMnFound = " << fMnFound << endl; );
@ -239,7 +238,7 @@ UniValue gobject(const UniValue& params, bool fHelp)
if((govobj.GetObjectType() == GOVERNANCE_OBJECT_TRIGGER) ||
(govobj.GetObjectType() == GOVERNANCE_OBJECT_WATCHDOG)) {
if(fMnFound) {
govobj.SetMasternodeInfo(mn.vin);
govobj.SetMasternodeVin(activeMasternode.outpoint);
govobj.Sign(activeMasternode.keyMasternode, activeMasternode.pubKeyMasternode);
}
else {
@ -322,7 +321,7 @@ UniValue gobject(const UniValue& params, bool fHelp)
UniValue returnObj(UniValue::VOBJ);
CMasternode mn;
bool fMnFound = mnodeman.Get(activeMasternode.vin, mn);
bool fMnFound = mnodeman.Get(activeMasternode.outpoint, mn);
if(!fMnFound) {
nFailed++;
@ -334,7 +333,7 @@ UniValue gobject(const UniValue& params, bool fHelp)
return returnObj;
}
CGovernanceVote vote(mn.vin, hash, eVoteSignal, eVoteOutcome);
CGovernanceVote vote(mn.vin.prevout, hash, eVoteSignal, eVoteOutcome);
if(!vote.Sign(activeMasternode.keyMasternode, activeMasternode.pubKeyMasternode)) {
nFailed++;
statusObj.push_back(Pair("result", "failed"));
@ -425,10 +424,10 @@ UniValue gobject(const UniValue& params, bool fHelp)
continue;
}
CTxIn vin(COutPoint(nTxHash, nOutputIndex));
COutPoint outpoint(nTxHash, nOutputIndex);
CMasternode mn;
bool fMnFound = mnodeman.Get(vin, mn);
bool fMnFound = mnodeman.Get(outpoint, mn);
if(!fMnFound) {
nFailed++;
@ -438,7 +437,7 @@ UniValue gobject(const UniValue& params, bool fHelp)
continue;
}
CGovernanceVote vote(mn.vin, hash, eVoteSignal, eVoteOutcome);
CGovernanceVote vote(mn.vin.prevout, hash, eVoteSignal, eVoteOutcome);
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
nFailed++;
statusObj.push_back(Pair("result", "failed"));
@ -546,10 +545,10 @@ UniValue gobject(const UniValue& params, bool fHelp)
continue;
}
CTxIn vin(COutPoint(nTxHash, nOutputIndex));
COutPoint outpoint(nTxHash, nOutputIndex);
CMasternode mn;
bool fMnFound = mnodeman.Get(vin, mn);
bool fMnFound = mnodeman.Get(outpoint, mn);
if(!fMnFound) {
nFailed++;
@ -561,7 +560,7 @@ UniValue gobject(const UniValue& params, bool fHelp)
// CREATE NEW GOVERNANCE OBJECT VOTE WITH OUTCOME/SIGNAL
CGovernanceVote vote(vin, hash, eVoteSignal, eVoteOutcome);
CGovernanceVote vote(outpoint, hash, eVoteSignal, eVoteOutcome);
if(!vote.Sign(keyMasternode, pubKeyMasternode)) {
nFailed++;
statusObj.push_back(Pair("result", "failed"));
@ -799,12 +798,12 @@ UniValue gobject(const UniValue& params, bool fHelp)
uint256 hash = ParseHashV(params[1], "Governance hash");
CTxIn mnCollateralOutpoint;
COutPoint mnCollateralOutpoint;
if (params.size() == 4) {
uint256 txid = ParseHashV(params[2], "Masternode Collateral hash");
std::string strVout = params[3].get_str();
uint32_t vout = boost::lexical_cast<uint32_t>(strVout);
mnCollateralOutpoint = CTxIn(txid, vout);
mnCollateralOutpoint = COutPoint(txid, vout);
}
// FIND OBJECT USER IS LOOKING FOR
@ -844,7 +843,7 @@ UniValue voteraw(const UniValue& params, bool fHelp)
uint256 hashMnTx = ParseHashV(params[0], "mn tx hash");
int nMnTxIndex = params[1].get_int();
CTxIn vin = CTxIn(hashMnTx, nMnTxIndex);
COutPoint outpoint = COutPoint(hashMnTx, nMnTxIndex);
uint256 hashGovObj = ParseHashV(params[2], "Governance hash");
std::string strVoteSignal = params[3].get_str();
@ -872,13 +871,13 @@ UniValue voteraw(const UniValue& params, bool fHelp)
}
CMasternode mn;
bool fMnFound = mnodeman.Get(vin, mn);
bool fMnFound = mnodeman.Get(outpoint, mn);
if(!fMnFound) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to find masternode in list : " + vin.prevout.ToStringShort());
throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to find masternode in list : " + outpoint.ToStringShort());
}
CGovernanceVote vote(vin, hashGovObj, eVoteSignal, eVoteOutcome);
CGovernanceVote vote(outpoint, hashGovObj, eVoteSignal, eVoteOutcome);
vote.SetTime(nTime);
vote.SetSignature(vchSig);

View File

@ -175,7 +175,8 @@ UniValue masternode(const UniValue& params, bool fHelp)
return mnodeman.CountEnabled();
int nCount;
mnodeman.GetNextMasternodeInQueueForPayment(true, nCount);
masternode_info_t mnInfo;
mnodeman.GetNextMasternodeInQueueForPayment(true, nCount, mnInfo);
if (strMode == "qualify")
return nCount;
@ -190,7 +191,7 @@ UniValue masternode(const UniValue& params, bool fHelp)
{
int nCount;
int nHeight;
CMasternode* winner = NULL;
masternode_info_t mnInfo;
CBlockIndex* pindex = NULL;
{
LOCK(cs_main);
@ -198,20 +199,19 @@ UniValue masternode(const UniValue& params, bool fHelp)
}
nHeight = pindex->nHeight + (strCommand == "current" ? 1 : 10);
mnodeman.UpdateLastPaid(pindex);
winner = mnodeman.GetNextMasternodeInQueueForPayment(nHeight, true, nCount);
if(!winner) return "unknown";
if(!mnodeman.GetNextMasternodeInQueueForPayment(nHeight, true, nCount, mnInfo))
return "unknown";
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("height", nHeight));
obj.push_back(Pair("IP:port", winner->addr.ToString()));
obj.push_back(Pair("protocol", (int64_t)winner->nProtocolVersion));
obj.push_back(Pair("vin", winner->vin.prevout.ToStringShort()));
obj.push_back(Pair("payee", CBitcoinAddress(winner->pubKeyCollateralAddress.GetID()).ToString()));
obj.push_back(Pair("lastseen", (winner->lastPing == CMasternodePing()) ? winner->sigTime :
winner->lastPing.sigTime));
obj.push_back(Pair("activeseconds", (winner->lastPing == CMasternodePing()) ? 0 :
(winner->lastPing.sigTime - winner->sigTime)));
obj.push_back(Pair("IP:port", mnInfo.addr.ToString()));
obj.push_back(Pair("protocol", (int64_t)mnInfo.nProtocolVersion));
obj.push_back(Pair("outpoint", mnInfo.vin.prevout.ToStringShort()));
obj.push_back(Pair("payee", CBitcoinAddress(mnInfo.pubKeyCollateralAddress.GetID()).ToString()));
obj.push_back(Pair("lastseen", mnInfo.nTimeLastPing));
obj.push_back(Pair("activeseconds", mnInfo.nTimeLastPing - mnInfo.sigTime));
return obj;
}
@ -220,11 +220,11 @@ UniValue masternode(const UniValue& params, bool fHelp)
if(activeMasternode.nState != ACTIVE_MASTERNODE_INITIAL || !masternodeSync.IsBlockchainSynced())
return activeMasternode.GetStatus();
CTxIn vin;
COutPoint outpoint;
CPubKey pubkey;
CKey key;
if(!pwalletMain || !pwalletMain->GetMasternodeVinAndKeys(vin, pubkey, key))
if(!pwalletMain || !pwalletMain->GetMasternodeOutpointAndKeys(outpoint, pubkey, key))
throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing masternode input, please look at the documentation for instructions on masternode creation");
return activeMasternode.GetStatus();
@ -313,12 +313,13 @@ UniValue masternode(const UniValue& params, bool fHelp)
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
std::string strError;
CTxIn vin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode *pmn = mnodeman.Find(vin);
COutPoint outpoint = COutPoint(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode mn;
bool fFound = mnodeman.Get(outpoint, mn);
CMasternodeBroadcast mnb;
if(strCommand == "start-missing" && pmn) continue;
if(strCommand == "start-disabled" && pmn && pmn->IsEnabled()) continue;
if(strCommand == "start-missing" && fFound) continue;
if(strCommand == "start-disabled" && fFound && mn.IsEnabled()) continue;
bool fResult = CMasternodeBroadcast::Create(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), strError, mnb);
@ -359,10 +360,11 @@ UniValue masternode(const UniValue& params, bool fHelp)
UniValue resultObj(UniValue::VOBJ);
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
CTxIn vin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode *pmn = mnodeman.Find(vin);
COutPoint outpoint = COutPoint(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode mn;
bool fFound = mnodeman.Get(outpoint, mn);
std::string strStatus = pmn ? pmn->GetStatus() : "MISSING";
std::string strStatus = fFound ? mn.GetStatus() : "MISSING";
UniValue mnObj(UniValue::VOBJ);
mnObj.push_back(Pair("alias", mne.getAlias()));
@ -398,11 +400,11 @@ UniValue masternode(const UniValue& params, bool fHelp)
UniValue mnObj(UniValue::VOBJ);
mnObj.push_back(Pair("vin", activeMasternode.vin.ToString()));
mnObj.push_back(Pair("vin", activeMasternode.outpoint.ToStringShort()));
mnObj.push_back(Pair("service", activeMasternode.service.ToString()));
CMasternode mn;
if(mnodeman.Get(activeMasternode.vin, mn)) {
if(mnodeman.Get(activeMasternode.outpoint, mn)) {
mnObj.push_back(Pair("payee", CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString()));
}
@ -509,9 +511,10 @@ UniValue masternodelist(const UniValue& params, bool fHelp)
obj.push_back(Pair(strOutpoint, s.first));
}
} else {
std::vector<CMasternode> vMasternodes = mnodeman.GetFullMasternodeVector();
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
std::string strOutpoint = mn.vin.prevout.ToStringShort();
std::map<COutPoint, CMasternode> mapMasternodes = mnodeman.GetFullMasternodeMap();
for (auto& mnpair : mapMasternodes) {
CMasternode mn = mnpair.second;
std::string strOutpoint = mnpair.first.ToStringShort();
if (strMode == "activeseconds") {
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
obj.push_back(Pair(strOutpoint, (int64_t)(mn.lastPing.sigTime - mn.sigTime)));

View File

@ -2632,7 +2632,7 @@ UniValue listunspent(const UniValue& params, bool fHelp)
}
entry.push_back(Pair("amount",ValueFromAmount(nValue)));
entry.push_back(Pair("confirmations",out.nDepth));
entry.push_back(Pair("ps_rounds", pwalletMain->GetInputPrivateSendRounds(CTxIn(out.tx->GetHash(), out.i))));
entry.push_back(Pair("ps_rounds", pwalletMain->GetOutpointPrivateSendRounds(COutPoint(out.tx->GetHash(), out.i))));
entry.push_back(Pair("spendable", out.fSpendable));
entry.push_back(Pair("solvable", out.fSolvable));
results.push_back(entry);

View File

@ -1233,14 +1233,14 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
}
// Recursively determine the rounds of a given input (How deep is the PrivateSend chain for a given input)
int CWallet::GetRealInputPrivateSendRounds(CTxIn txin, int nRounds) const
int CWallet::GetRealOutpointPrivateSendRounds(const COutPoint& outpoint, int nRounds) const
{
static std::map<uint256, CMutableTransaction> mDenomWtxes;
if(nRounds >= 16) return 15; // 16 rounds max
uint256 hash = txin.prevout.hash;
unsigned int nout = txin.prevout.n;
uint256 hash = outpoint.hash;
unsigned int nout = outpoint.n;
const CWalletTx* wtx = GetWalletTx(hash);
if(wtx != NULL)
@ -1248,7 +1248,7 @@ int CWallet::GetRealInputPrivateSendRounds(CTxIn txin, int nRounds) const
std::map<uint256, CMutableTransaction>::const_iterator mdwi = mDenomWtxes.find(hash);
if (mdwi == mDenomWtxes.end()) {
// not known yet, let's add it
LogPrint("privatesend", "GetRealInputPrivateSendRounds INSERTING %s\n", hash.ToString());
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds INSERTING %s\n", hash.ToString());
mDenomWtxes[hash] = CMutableTransaction(*wtx);
} else if(mDenomWtxes[hash].vout[nout].nRounds != -10) {
// found and it's not an initial value, just return it
@ -1259,20 +1259,20 @@ int CWallet::GetRealInputPrivateSendRounds(CTxIn txin, int nRounds) const
// bounds check
if (nout >= wtx->vout.size()) {
// should never actually hit this
LogPrint("privatesend", "GetRealInputPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, -4);
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, -4);
return -4;
}
if (IsCollateralAmount(wtx->vout[nout].nValue)) {
mDenomWtxes[hash].vout[nout].nRounds = -3;
LogPrint("privatesend", "GetRealInputPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
return mDenomWtxes[hash].vout[nout].nRounds;
}
//make sure the final output is non-denominate
if (!IsDenominatedAmount(wtx->vout[nout].nValue)) { //NOT DENOM
mDenomWtxes[hash].vout[nout].nRounds = -2;
LogPrint("privatesend", "GetRealInputPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
return mDenomWtxes[hash].vout[nout].nRounds;
}
@ -1284,7 +1284,7 @@ int CWallet::GetRealInputPrivateSendRounds(CTxIn txin, int nRounds) const
// this one is denominated but there is another non-denominated output found in the same tx
if (!fAllDenoms) {
mDenomWtxes[hash].vout[nout].nRounds = 0;
LogPrint("privatesend", "GetRealInputPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
return mDenomWtxes[hash].vout[nout].nRounds;
}
@ -1293,7 +1293,7 @@ int CWallet::GetRealInputPrivateSendRounds(CTxIn txin, int nRounds) const
// only denoms here so let's look up
BOOST_FOREACH(CTxIn txinNext, wtx->vin) {
if (IsMine(txinNext)) {
int n = GetRealInputPrivateSendRounds(txinNext, nRounds + 1);
int n = GetRealOutpointPrivateSendRounds(txinNext.prevout, nRounds + 1);
// denom found, find the shortest chain or initially assign nShortest with the first found value
if(n >= 0 && (n < nShortest || nShortest == -10)) {
nShortest = n;
@ -1304,7 +1304,7 @@ int CWallet::GetRealInputPrivateSendRounds(CTxIn txin, int nRounds) const
mDenomWtxes[hash].vout[nout].nRounds = fDenomFound
? (nShortest >= 15 ? 16 : nShortest + 1) // good, we a +1 to the shortest one but only 16 rounds max allowed
: 0; // too bad, we are the fist one in that chain
LogPrint("privatesend", "GetRealInputPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
return mDenomWtxes[hash].vout[nout].nRounds;
}
@ -1312,22 +1312,22 @@ int CWallet::GetRealInputPrivateSendRounds(CTxIn txin, int nRounds) const
}
// respect current settings
int CWallet::GetInputPrivateSendRounds(CTxIn txin) const
int CWallet::GetOutpointPrivateSendRounds(const COutPoint& outpoint) const
{
LOCK(cs_wallet);
int realPrivateSendRounds = GetRealInputPrivateSendRounds(txin, 0);
int realPrivateSendRounds = GetRealOutpointPrivateSendRounds(outpoint, 0);
return realPrivateSendRounds > privateSendClient.nPrivateSendRounds ? privateSendClient.nPrivateSendRounds : realPrivateSendRounds;
}
bool CWallet::IsDenominated(const CTxIn &txin) const
bool CWallet::IsDenominated(const COutPoint& outpoint) const
{
LOCK(cs_wallet);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(outpoint.hash);
if (mi != mapWallet.end()) {
const CWalletTx& prev = (*mi).second;
if (txin.prevout.n < prev.vout.size()) {
return IsDenominatedAmount(prev.vout[txin.prevout.n].nValue);
if (outpoint.n < prev.vout.size()) {
return IsDenominatedAmount(prev.vout[outpoint.n].nValue);
}
}
@ -1952,11 +1952,11 @@ CAmount CWalletTx::GetAnonymizedCredit(bool fUseCache) const
for (unsigned int i = 0; i < vout.size(); i++)
{
const CTxOut &txout = vout[i];
const CTxIn txin = CTxIn(hashTx, i);
const COutPoint outpoint = COutPoint(hashTx, i);
if(pwallet->IsSpent(hashTx, i) || !pwallet->IsDenominated(txin)) continue;
if(pwallet->IsSpent(hashTx, i) || !pwallet->IsDenominated(outpoint)) continue;
const int nRounds = pwallet->GetInputPrivateSendRounds(txin);
const int nRounds = pwallet->GetOutpointPrivateSendRounds(outpoint);
if(nRounds >= privateSendClient.nPrivateSendRounds){
nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
if (!MoneyRange(nCredit))
@ -2206,11 +2206,11 @@ float CWallet::GetAverageAnonymizedRounds() const
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
CTxIn txin = CTxIn(hash, i);
COutPoint outpoint = COutPoint(hash, i);
if(IsSpent(hash, i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(txin)) continue;
if(IsSpent(hash, i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(outpoint)) continue;
nTotal += GetInputPrivateSendRounds(txin);
nTotal += GetOutpointPrivateSendRounds(outpoint);
nCount++;
}
}
@ -2239,12 +2239,12 @@ CAmount CWallet::GetNormalizedAnonymizedBalance() const
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
CTxIn txin = CTxIn(hash, i);
COutPoint outpoint = COutPoint(hash, i);
if(IsSpent(hash, i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(txin)) continue;
if(IsSpent(hash, i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(outpoint)) continue;
if (pcoin->GetDepthInMainChain() < 0) continue;
int nRounds = GetInputPrivateSendRounds(txin);
int nRounds = GetOutpointPrivateSendRounds(outpoint);
nTotal += pcoin->vout[i].nValue * nRounds / privateSendClient.nPrivateSendRounds;
}
}
@ -2643,8 +2643,8 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
continue;
if(nCoinType == ONLY_DENOMINATED) {
CTxIn txin = CTxIn(out.tx->GetHash(),out.i);
int nRounds = GetInputPrivateSendRounds(txin);
COutPoint outpoint = COutPoint(out.tx->GetHash(),out.i);
int nRounds = GetOutpointPrivateSendRounds(outpoint);
// make sure it's actually anonymized
if(nRounds < privateSendClient.nPrivateSendRounds) continue;
}
@ -2666,8 +2666,8 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
{
//make sure it's the denom we're looking for, round the amount up to smallest denom
if(out.tx->vout[out.i].nValue == nDenom && nValueRet + nDenom < nTargetValue + nSmallestDenom) {
CTxIn txin = CTxIn(out.tx->GetHash(),out.i);
int nRounds = GetInputPrivateSendRounds(txin);
COutPoint outpoint = COutPoint(out.tx->GetHash(),out.i);
int nRounds = GetOutpointPrivateSendRounds(outpoint);
// make sure it's actually anonymized
if(nRounds < privateSendClient.nPrivateSendRounds) continue;
nValueRet += nDenom;
@ -2800,7 +2800,7 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
CTxIn txin = CTxIn(out.tx->GetHash(), out.i);
int nRounds = GetInputPrivateSendRounds(txin);
int nRounds = GetOutpointPrivateSendRounds(txin.prevout);
if(nRounds >= nPrivateSendRoundsMax) continue;
if(nRounds < nPrivateSendRoundsMin) continue;
@ -2884,7 +2884,7 @@ bool CWallet::SelectCoinsGrouppedByAddresses(std::vector<CompactTallyItem>& vecT
// otherwise they will just lead to higher fee / lower priority
if(wtx.vout[i].nValue <= nSmallestDenom/10) continue;
// ignore anonymized
if(GetInputPrivateSendRounds(CTxIn(wtx.GetHash(), i)) >= privateSendClient.nPrivateSendRounds) continue;
if(GetOutpointPrivateSendRounds(COutPoint(wtx.GetHash(), i)) >= privateSendClient.nPrivateSendRounds) continue;
}
CompactTallyItem& item = mapTally[address];
@ -2948,7 +2948,7 @@ bool CWallet::SelectCoinsDark(CAmount nValueMin, CAmount nValueMax, std::vector<
if(nValueRet + out.tx->vout[out.i].nValue <= nValueMax){
CTxIn txin = CTxIn(out.tx->GetHash(),out.i);
int nRounds = GetInputPrivateSendRounds(txin);
int nRounds = GetOutpointPrivateSendRounds(txin.prevout);
if(nRounds >= nPrivateSendRoundsMax) continue;
if(nRounds < nPrivateSendRoundsMin) continue;
@ -2981,7 +2981,7 @@ bool CWallet::GetCollateralTxIn(CTxIn& txinRet, CAmount& nValueRet) const
return false;
}
bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey& keyRet, std::string strTxHash, std::string strOutputIndex)
bool CWallet::GetMasternodeOutpointAndKeys(COutPoint& outpointRet, CPubKey& pubKeyRet, CKey& keyRet, std::string strTxHash, std::string strOutputIndex)
{
// wait for reindex and/or import to finish
if (fImporting || fReindex) return false;
@ -2990,12 +2990,12 @@ bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey&
std::vector<COutput> vPossibleCoins;
AvailableCoins(vPossibleCoins, true, NULL, false, ONLY_1000);
if(vPossibleCoins.empty()) {
LogPrintf("CWallet::GetMasternodeVinAndKeys -- Could not locate any valid masternode vin\n");
LogPrintf("CWallet::GetMasternodeOutpointAndKeys -- Could not locate any valid masternode vin\n");
return false;
}
if(strTxHash.empty()) // No output specified, select the first one
return GetVinAndKeysFromOutput(vPossibleCoins[0], txinRet, pubKeyRet, keyRet);
return GetOutpointAndKeysFromOutput(vPossibleCoins[0], outpointRet, pubKeyRet, keyRet);
// Find specific vin
uint256 txHash = uint256S(strTxHash);
@ -3003,20 +3003,20 @@ bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey&
BOOST_FOREACH(COutput& out, vPossibleCoins)
if(out.tx->GetHash() == txHash && out.i == nOutputIndex) // found it!
return GetVinAndKeysFromOutput(out, txinRet, pubKeyRet, keyRet);
return GetOutpointAndKeysFromOutput(out, outpointRet, pubKeyRet, keyRet);
LogPrintf("CWallet::GetMasternodeVinAndKeys -- Could not locate specified masternode vin\n");
LogPrintf("CWallet::GetMasternodeOutpointAndKeys -- Could not locate specified masternode vin\n");
return false;
}
bool CWallet::GetVinAndKeysFromOutput(COutput out, CTxIn& txinRet, CPubKey& pubKeyRet, CKey& keyRet)
bool CWallet::GetOutpointAndKeysFromOutput(const COutput& out, COutPoint& outpointRet, CPubKey& pubKeyRet, CKey& keyRet)
{
// wait for reindex and/or import to finish
if (fImporting || fReindex) return false;
CScript pubScript;
txinRet = CTxIn(out.tx->GetHash(), out.i);
outpointRet = COutPoint(out.tx->GetHash(), out.i);
pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
CTxDestination address1;
@ -3025,12 +3025,12 @@ bool CWallet::GetVinAndKeysFromOutput(COutput out, CTxIn& txinRet, CPubKey& pubK
CKeyID keyID;
if (!address2.GetKeyID(keyID)) {
LogPrintf("CWallet::GetVinAndKeysFromOutput -- Address does not refer to a key\n");
LogPrintf("CWallet::GetOutpointAndKeysFromOutput -- Address does not refer to a key\n");
return false;
}
if (!GetKey(keyID, keyRet)) {
LogPrintf ("CWallet::GetVinAndKeysFromOutput -- Private key for address is not known\n");
LogPrintf ("CWallet::GetOutpointAndKeysFromOutput -- Private key for address is not known\n");
return false;
}
@ -3051,11 +3051,11 @@ int CWallet::CountInputsWithAmount(CAmount nInputAmount)
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
COutput out = COutput(pcoin, i, nDepth, true, true);
CTxIn txin = CTxIn(out.tx->GetHash(), out.i);
COutPoint outpoint = COutPoint(out.tx->GetHash(), out.i);
if(out.tx->vout[out.i].nValue != nInputAmount) continue;
if(!IsDenominatedAmount(pcoin->vout[i].nValue)) continue;
if(IsSpent(out.tx->GetHash(), i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(txin)) continue;
if(IsSpent(out.tx->GetHash(), i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(outpoint)) continue;
nTotal++;
}

View File

@ -775,20 +775,20 @@ public:
bool SelectCoinsGrouppedByAddresses(std::vector<CompactTallyItem>& vecTallyRet, bool fSkipDenominated = true, bool fAnonymizable = true, bool fSkipUnconfirmed = true) const;
/// Get 1000DASH output and keys which can be used for the Masternode
bool GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey& keyRet, std::string strTxHash = "", std::string strOutputIndex = "");
bool GetMasternodeOutpointAndKeys(COutPoint& outpointRet, CPubKey& pubKeyRet, CKey& keyRet, std::string strTxHash = "", std::string strOutputIndex = "");
/// Extract txin information and keys from output
bool GetVinAndKeysFromOutput(COutput out, CTxIn& txinRet, CPubKey& pubKeyRet, CKey& keyRet);
bool GetOutpointAndKeysFromOutput(const COutput& out, COutPoint& outpointRet, CPubKey& pubKeyRet, CKey& keyRet);
bool HasCollateralInputs(bool fOnlyConfirmed = true) const;
bool IsCollateralAmount(CAmount nInputAmount) const;
int CountInputsWithAmount(CAmount nInputAmount);
// get the PrivateSend chain depth for a given input
int GetRealInputPrivateSendRounds(CTxIn txin, int nRounds) const;
int GetRealOutpointPrivateSendRounds(const COutPoint& outpoint, int nRounds) const;
// respect current settings
int GetInputPrivateSendRounds(CTxIn txin) const;
int GetOutpointPrivateSendRounds(const COutPoint& outpoint) const;
bool IsDenominated(const CTxIn &txin) const;
bool IsDenominated(const COutPoint& outpoint) const;
bool IsDenominatedAmount(CAmount nInputAmount) const;
bool IsSpent(const uint256& hash, unsigned int n) const;