void CActiveMasternode::ManageStateLocal(CConnman& connman) { LogPrint("masternode", "CActiveMasternode::ManageStateLocal -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled); if(nState == ACTIVE_MASTERNODE_STARTED) { return; } // Choose coins to use CPubKey pubKeyCollateral; CKey keyCollateral; 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); LogPrintf("CActiveMasternode::ManageStateLocal -- %s: %s\n", GetStateString(), strNotCapableReason); return; } { LOCK(pwalletMain->cs_wallet); pwalletMain->LockCoin(outpoint); } CMasternodeBroadcast mnb; std::string strError; 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); return; } { LOCK(cs_main); // remember the hash of the block where masternode collateral had minimum required confirmations mnb.nCollateralMinConfBlockHash = chainActive[GetUTXOHeight(outpoint) + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]->GetBlockHash(); } fPingerEnabled = true; nState = ACTIVE_MASTERNODE_STARTED; //update to masternode list LogPrintf("CActiveMasternode::ManageStateLocal -- Update Masternode List\n"); mnodeman.UpdateMasternodeList(mnb, connman); mnodeman.NotifyMasternodeUpdates(connman); //send to all peers LogPrintf("CActiveMasternode::ManageStateLocal -- Relay broadcast, collateral=%s\n", outpoint.ToStringShort()); mnb.Relay(connman); } }
void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman) { if(!fMasternodeMode) return; if(!sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED)) return; LOCK2(cs_main, cs_instantsend); uint256 txHash = txLockCandidate.GetHash(); // We should never vote on a Transaction Lock Request that was not (yet) accepted by the mempool if(mapLockRequestAccepted.find(txHash) == mapLockRequestAccepted.end()) return; // check if we need to vote on this candidate's outpoints, // it's possible that we need to vote for several of them std::map<COutPoint, COutPointLock>::iterator itOutpointLock = txLockCandidate.mapOutPointLocks.begin(); while(itOutpointLock != txLockCandidate.mapOutPointLocks.end()) { int nPrevoutHeight = GetUTXOHeight(itOutpointLock->first); if(nPrevoutHeight == -1) { LogPrint("instantsend", "CInstantSend::Vote -- Failed to find UTXO %s\n", itOutpointLock->first.ToStringShort()); return; } int nLockInputHeight = nPrevoutHeight + Params().GetConsensus().nInstantSendConfirmationsRequired - 2; int nRank; if(!mnodeman.GetMasternodeRank(activeMasternode.outpoint, nRank, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION)) { LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternode.outpoint.ToStringShort()); ++itOutpointLock; continue; } int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL; if(nRank > nSignaturesTotal) { LogPrint("instantsend", "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, nRank); ++itOutpointLock; continue; } LogPrint("instantsend", "CInstantSend::Vote -- In the top %d (%d)\n", nSignaturesTotal, nRank); std::map<COutPoint, std::set<uint256> >::iterator itVoted = mapVotedOutpoints.find(itOutpointLock->first); // Check to see if we already voted for this outpoint, // refuse to vote twice or to include the same outpoint in another tx bool fAlreadyVoted = false; if(itVoted != mapVotedOutpoints.end()) { for (const auto& hash : itVoted->second) { std::map<uint256, CTxLockCandidate>::iterator it2 = mapTxLockCandidates.find(hash); 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; LogPrintf("CInstantSend::Vote -- WARNING: We already voted for this outpoint, skipping: txHash=%s, outpoint=%s\n", txHash.ToString(), itOutpointLock->first.ToStringShort()); break; } } } if(fAlreadyVoted) { ++itOutpointLock; continue; // skip to the next outpoint } // we haven't voted for this outpoint yet, let's try to do this now CTxLockVote vote(txHash, itOutpointLock->first, activeMasternode.outpoint); if(!vote.Sign()) { LogPrintf("CInstantSend::Vote -- Failed to sign consensus vote\n"); return; } if(!vote.CheckSignature()) { LogPrintf("CInstantSend::Vote -- Signature invalid\n"); return; } // vote constructed sucessfully, let's store and relay it uint256 nVoteHash = vote.GetHash(); mapTxLockVotes.insert(std::make_pair(nVoteHash, vote)); if(itOutpointLock->second.AddVote(vote)) { LogPrintf("CInstantSend::Vote -- Vote created successfully, relaying: txHash=%s, outpoint=%s, vote=%s\n", txHash.ToString(), itOutpointLock->first.ToStringShort(), nVoteHash.ToString()); if(itVoted == mapVotedOutpoints.end()) { std::set<uint256> setHashes; setHashes.insert(txHash); mapVotedOutpoints.insert(std::make_pair(itOutpointLock->first, setHashes)); } else { mapVotedOutpoints[itOutpointLock->first].insert(txHash); if(mapVotedOutpoints[itOutpointLock->first].size() > 1) { // it's ok to continue, just warn user LogPrintf("CInstantSend::Vote -- WARNING: Vote conflicts with some existing votes: txHash=%s, outpoint=%s, vote=%s\n", txHash.ToString(), itOutpointLock->first.ToStringShort(), nVoteHash.ToString()); } } vote.Relay(connman); } ++itOutpointLock; } }