dash/src/masternode.cpp

853 lines
34 KiB
C++
Raw Normal View History

2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash Core developers
2015-02-24 15:02:22 +01:00
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "activemasternode.h"
#include "base58.h"
#include "init.h"
#include "netbase.h"
#include "masternode.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
#include "masternodeman.h"
#include "messagesigner.h"
#include "script/standard.h"
#include "util.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif // ENABLE_WALLET
#include <boost/lexical_cast.hpp>
CMasternode::CMasternode() :
masternode_info_t{ MASTERNODE_ENABLED, PROTOCOL_VERSION, GetAdjustedTime()},
fAllowMixingTx(true)
{}
CMasternode::CMasternode(CService addr, COutPoint outpoint, CPubKey pubKeyCollateralAddress, CPubKey pubKeyMasternode, int nProtocolVersionIn) :
masternode_info_t{ MASTERNODE_ENABLED, nProtocolVersionIn, GetAdjustedTime(),
outpoint, addr, pubKeyCollateralAddress, pubKeyMasternode},
fAllowMixingTx(true)
{}
CMasternode::CMasternode(const CMasternode& other) :
masternode_info_t{other},
lastPing(other.lastPing),
vchSig(other.vchSig),
nCollateralMinConfBlockHash(other.nCollateralMinConfBlockHash),
nBlockLastPaid(other.nBlockLastPaid),
2016-10-20 23:11:30 +02:00
nPoSeBanScore(other.nPoSeBanScore),
nPoSeBanHeight(other.nPoSeBanHeight),
fAllowMixingTx(other.fAllowMixingTx),
fUnitTest(other.fUnitTest)
{}
CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
masternode_info_t{ mnb.nActiveState, mnb.nProtocolVersion, mnb.sigTime,
mnb.vin.prevout, mnb.addr, mnb.pubKeyCollateralAddress, mnb.pubKeyMasternode,
mnb.sigTime /*nTimeLastWatchdogVote*/},
lastPing(mnb.lastPing),
vchSig(mnb.vchSig),
fAllowMixingTx(true)
{}
//
// When a new masternode broadcast is sent, update our information
//
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb, CConnman& connman)
{
if(mnb.sigTime <= sigTime && !mnb.fRecovery) return false;
2016-10-20 23:11:30 +02:00
pubKeyMasternode = mnb.pubKeyMasternode;
sigTime = mnb.sigTime;
vchSig = mnb.vchSig;
nProtocolVersion = mnb.nProtocolVersion;
addr = mnb.addr;
nPoSeBanScore = 0;
nPoSeBanHeight = 0;
2016-10-20 23:11:30 +02:00
nTimeLastChecked = 0;
int nDos = 0;
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
if(mnb.lastPing == CMasternodePing() || (mnb.lastPing != CMasternodePing() && mnb.lastPing.CheckAndUpdate(this, true, nDos, connman))) {
2016-10-20 23:11:30 +02:00
lastPing = mnb.lastPing;
mnodeman.mapSeenMasternodePing.insert(std::make_pair(lastPing.GetHash(), lastPing));
}
// if it matches our Masternode privkey...
if(fMasterNode && pubKeyMasternode == activeMasternode.pubKeyMasternode) {
nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
if(nProtocolVersion == PROTOCOL_VERSION) {
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
activeMasternode.ManageState(connman);
2016-10-20 23:11:30 +02:00
} else {
// ... otherwise we need to reactivate our node, do not add it to the list and do not relay
// but also do not ban the node we get this message from
LogPrintf("CMasternode::UpdateFromNewBroadcast -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", nProtocolVersion, PROTOCOL_VERSION);
return false;
2015-08-12 03:39:22 +02:00
}
}
2016-10-20 23:11:30 +02:00
return true;
}
//
2015-03-05 09:11:56 +01:00
// Deterministically calculate a given "score" for a Masternode depending on how close it's hash is to
// the proof of work for that block. The further away they are the better, the furthest will win the election
// and get paid this block
//
arith_uint256 CMasternode::CalculateScore(const uint256& blockHash)
{
// Deterministically calculate a "score" for a Masternode based on any given (block)hash
2015-07-24 17:50:10 +02:00
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
ss << vin.prevout << nCollateralMinConfBlockHash << blockHash;
return UintToArith256(ss.GetHash());
}
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, const CPubKey& pubkey)
{
int nHeight;
return CheckCollateral(outpoint, pubkey, nHeight);
}
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, const CPubKey& pubkey, int& nHeightRet)
{
AssertLockHeld(cs_main);
2017-09-26 16:33:46 +02:00
Coin coin;
if(!GetUTXOCoin(outpoint, coin)) {
return COLLATERAL_UTXO_NOT_FOUND;
}
2017-09-26 16:33:46 +02:00
if(coin.out.nValue != 1000 * COIN) {
return COLLATERAL_INVALID_AMOUNT;
}
if(pubkey == CPubKey() || coin.out.scriptPubKey != GetScriptForDestination(pubkey.GetID())) {
return COLLATERAL_INVALID_PUBKEY;
}
2017-09-26 16:33:46 +02:00
nHeightRet = coin.nHeight;
return COLLATERAL_OK;
}
void CMasternode::Check(bool fForce)
{
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
LOCK(cs);
2015-07-03 00:09:14 +02:00
if(ShutdownRequested()) return;
if(!fForce && (GetTime() - nTimeLastChecked < MASTERNODE_CHECK_SECONDS)) return;
nTimeLastChecked = GetTime();
2015-08-08 12:36:30 +02:00
LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state\n", vin.prevout.ToStringShort(), GetStateString());
//once spent, stop doing the checks
if(IsOutpointSpent()) return;
int nHeight = 0;
2016-10-20 23:11:30 +02:00
if(!fUnitTest) {
TRY_LOCK(cs_main, lockMain);
if(!lockMain) return;
Coin coin;
if(!GetUTXOCoin(vin.prevout, coin)) {
2016-10-20 23:11:30 +02:00
nActiveState = MASTERNODE_OUTPOINT_SPENT;
LogPrint("masternode", "CMasternode::Check -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
return;
}
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
nHeight = chainActive.Height();
}
2015-08-08 12:36:30 +02:00
if(IsPoSeBanned()) {
if(nHeight < nPoSeBanHeight) return; // too early?
// Otherwise give it a chance to proceed further to do all the usual checks and to change its state.
// Masternode still will be on the edge and can be banned back easily if it keeps ignoring mnverify
// or connect attempts. Will require few mnverify messages to strengthen its position in mn list.
LogPrintf("CMasternode::Check -- Masternode %s is unbanned and back in list now\n", vin.prevout.ToStringShort());
DecreasePoSeBanScore();
2016-10-20 23:11:30 +02:00
} else if(nPoSeBanScore >= MASTERNODE_POSE_BAN_MAX_SCORE) {
nActiveState = MASTERNODE_POSE_BAN;
// ban for the whole payment cycle
nPoSeBanHeight = nHeight + mnodeman.size();
LogPrintf("CMasternode::Check -- Masternode %s is banned till block %d now\n", vin.prevout.ToStringShort(), nPoSeBanHeight);
return;
}
int nActiveStatePrev = nActiveState;
bool fOurMasternode = fMasterNode && activeMasternode.pubKeyMasternode == pubKeyMasternode;
// masternode doesn't meet payment protocol requirements ...
bool fRequireUpdate = nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto() ||
// or it's our own node and we just updated it to the new protocol but we are still waiting for activation ...
(fOurMasternode && nProtocolVersion < PROTOCOL_VERSION);
if(fRequireUpdate) {
nActiveState = MASTERNODE_UPDATE_REQUIRED;
if(nActiveStatePrev != nActiveState) {
LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", vin.prevout.ToStringShort(), GetStateString());
}
return;
}
// keep old masternodes on start, give them a chance to receive updates...
bool fWaitForPing = !masternodeSync.IsMasternodeListSynced() && !IsPingedWithin(MASTERNODE_MIN_MNP_SECONDS);
2016-10-20 23:11:30 +02:00
if(fWaitForPing && !fOurMasternode) {
// ...but if it was already expired before the initial check - return right away
if(IsExpired() || IsWatchdogExpired() || IsNewStartRequired()) {
LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state, waiting for ping\n", vin.prevout.ToStringShort(), GetStateString());
return;
}
}
// don't expire if we are still in "waiting for ping" mode unless it's our own masternode
if(!fWaitForPing || fOurMasternode) {
if(!IsPingedWithin(MASTERNODE_NEW_START_REQUIRED_SECONDS)) {
nActiveState = MASTERNODE_NEW_START_REQUIRED;
if(nActiveStatePrev != nActiveState) {
LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", vin.prevout.ToStringShort(), GetStateString());
}
return;
}
bool fWatchdogActive = masternodeSync.IsSynced() && mnodeman.IsWatchdogActive();
bool fWatchdogExpired = (fWatchdogActive && ((GetAdjustedTime() - nTimeLastWatchdogVote) > MASTERNODE_WATCHDOG_MAX_SECONDS));
LogPrint("masternode", "CMasternode::Check -- outpoint=%s, nTimeLastWatchdogVote=%d, GetAdjustedTime()=%d, fWatchdogExpired=%d\n",
vin.prevout.ToStringShort(), nTimeLastWatchdogVote, GetAdjustedTime(), fWatchdogExpired);
if(fWatchdogExpired) {
nActiveState = MASTERNODE_WATCHDOG_EXPIRED;
if(nActiveStatePrev != nActiveState) {
LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", vin.prevout.ToStringShort(), GetStateString());
}
return;
}
if(!IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)) {
nActiveState = MASTERNODE_EXPIRED;
if(nActiveStatePrev != nActiveState) {
LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", vin.prevout.ToStringShort(), GetStateString());
}
return;
}
}
Implement named devnets (#1791) * Initial devnet * Move genesis block adding into its own method * Introduce -allowprivatenet to lift limitation on RFC1918 addresses Normally, RFC1918 (192.168.x.x/10.x.x.x/...) addresses are not allowed to be relayed. Also, masternodes won't start when the address is considered invalid. This is needed to test local devnet or regtest based networks. * Lift the requirement of minimum MN age for regtest/devnet * Implement named devnets This allows the creation of multiple independent devnets. Each one is identified by a name which is hardened into a "devnet genesis" block, which is automatically positioned at height 1. Validation rules will ensure that a node from devnet=test1 never be able to accept blocks from devnet=test2. This is done by checking the expected devnet genesis block. The genesis block of the devnet is the same as the one from regtest. This starts the devnet with a very low difficulty, allowing us to fill up needed balances for masternodes very fast. Also, the devnet name is put into the sub-version of the VERSION message. If a node connects to the wrong network, it will immediately be disconnected. * Allow to select multiple addresses from the same group in devnet/regtest The selection code normally only allows to select addresses from the same group (e.g. 192.168.x.x) once. This results in connecting to only a single node in devnet/regtest. * Show the devnet name in the title bar and on the loading screen * Add AllowMultipleAddressesFromGroup to chainparams and use it in net.cpp * Remove unused/unneeded scripts from devnet geneses creation 1. OP_RETURN not needed in input script of devnet genesis 2. genesisOutputScript was unused * Fix copy/paste error in -allowprivatenet description * Improve -devnet parameter error handling - Only allow one of -devnet, -regtest or -testnet - Only allow -devnet=name to be specified once * Use different datadir for each devnet * Fix `devnet-devnet` issue * Fix devnet splashscreen (should use testnet img) * Avoid passing devNetName around (most of the time) * Remove nMaxTipAge from CDevNetParams Not present anymore after rebase on develop
2017-12-20 12:45:01 +01:00
// Allow MNs to become ENABLED immediately in regtest/devnet
// On mainnet/testnet, we require them to be in PRE_ENABLED state for some time before they get into ENABLED state
if (Params().NetworkIDString() != CBaseChainParams::REGTEST && Params().NetworkIDString() != CBaseChainParams::DEVNET) {
if (lastPing.sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS) {
nActiveState = MASTERNODE_PRE_ENABLED;
if (nActiveStatePrev != nActiveState) {
LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", vin.prevout.ToStringShort(), GetStateString());
}
return;
}
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
nActiveState = MASTERNODE_ENABLED; // OK
if(nActiveStatePrev != nActiveState) {
LogPrint("masternode", "CMasternode::Check -- Masternode %s is in %s state now\n", vin.prevout.ToStringShort(), GetStateString());
}
}
bool CMasternode::IsValidNetAddr()
{
return IsValidNetAddr(addr);
}
bool CMasternode::IsValidNetAddr(CService addrIn)
{
// TODO: regtest is fine with any addresses for now,
// should probably be a bit smarter if one day we start to implement tests for this
return Params().NetworkIDString() == CBaseChainParams::REGTEST ||
(addrIn.IsIPv4() && IsReachable(addrIn) && addrIn.IsRoutable());
}
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
masternode_info_t CMasternode::GetInfo()
{
masternode_info_t info{*this};
info.nTimeLastPing = lastPing.sigTime;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
info.fInfoValid = true;
return info;
}
std::string CMasternode::StateToString(int nStateIn)
{
switch(nStateIn) {
case MASTERNODE_PRE_ENABLED: return "PRE_ENABLED";
case MASTERNODE_ENABLED: return "ENABLED";
case MASTERNODE_EXPIRED: return "EXPIRED";
case MASTERNODE_OUTPOINT_SPENT: return "OUTPOINT_SPENT";
case MASTERNODE_UPDATE_REQUIRED: return "UPDATE_REQUIRED";
case MASTERNODE_WATCHDOG_EXPIRED: return "WATCHDOG_EXPIRED";
case MASTERNODE_NEW_START_REQUIRED: return "NEW_START_REQUIRED";
case MASTERNODE_POSE_BAN: return "POSE_BAN";
default: return "UNKNOWN";
}
}
std::string CMasternode::GetStateString() const
{
return StateToString(nActiveState);
}
std::string CMasternode::GetStatus() const
{
// TODO: return smth a bit more human readable here
return GetStateString();
}
void CMasternode::UpdateLastPaid(const CBlockIndex *pindex, int nMaxBlocksToScanBack)
{
if(!pindex) return;
const CBlockIndex *BlockReading = pindex;
CScript mnpayee = GetScriptForDestination(pubKeyCollateralAddress.GetID());
// LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s\n", vin.prevout.ToStringShort());
LOCK(cs_mapMasternodeBlocks);
for (int i = 0; BlockReading && BlockReading->nHeight > nBlockLastPaid && i < nMaxBlocksToScanBack; i++) {
if(mnpayments.mapMasternodeBlocks.count(BlockReading->nHeight) &&
mnpayments.mapMasternodeBlocks[BlockReading->nHeight].HasPayeeWithVotes(mnpayee, 2))
{
CBlock block;
if(!ReadBlockFromDisk(block, BlockReading, Params().GetConsensus())) // shouldn't really happen
continue;
CAmount nMasternodePayment = GetMasternodePayment(BlockReading->nHeight, block.vtx[0]->GetValueOut());
BOOST_FOREACH(CTxOut txout, block.vtx[0]->vout)
if(mnpayee == txout.scriptPubKey && nMasternodePayment == txout.nValue) {
nBlockLastPaid = BlockReading->nHeight;
nTimeLastPaid = BlockReading->nTime;
LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- found new %d\n", vin.prevout.ToStringShort(), nBlockLastPaid);
return;
}
}
if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
BlockReading = BlockReading->pprev;
}
// Last payment for this masternode wasn't found in latest mnpayments blocks
// or it was found in mnpayments blocks but wasn't found in the blockchain.
// LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- keeping old %d\n", vin.prevout.ToStringShort(), nBlockLastPaid);
}
#ifdef ENABLE_WALLET
2016-09-05 18:09:25 +02:00
bool CMasternodeBroadcast::Create(std::string strService, std::string strKeyMasternode, std::string strTxHash, std::string strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast &mnbRet, bool fOffline)
{
COutPoint outpoint;
CPubKey pubKeyCollateralAddressNew;
CKey keyCollateralAddressNew;
CPubKey pubKeyMasternodeNew;
CKey keyMasternodeNew;
auto Log = [&strErrorRet](std::string sErr)->bool
{
strErrorRet = sErr;
2016-09-05 18:09:25 +02:00
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
};
//need correct blocks to send ping
if (!fOffline && !masternodeSync.IsBlockchainSynced())
return Log("Sync in progress. Must wait until sync is complete to start Masternode");
if (!CMessageSigner::GetKeysFromSecret(strKeyMasternode, keyMasternodeNew, pubKeyMasternodeNew))
return Log(strprintf("Invalid masternode key %s", strKeyMasternode));
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))
return Log(strprintf("Invalid address %s for masternode.", strService));
2016-09-05 18:09:25 +02:00
int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
if (service.GetPort() != mainnetDefaultPort)
return Log(strprintf("Invalid port %u for masternode %s, only %d is supported on mainnet.", service.GetPort(), strService, mainnetDefaultPort));
} 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(outpoint, service, keyCollateralAddressNew, pubKeyCollateralAddressNew, keyMasternodeNew, pubKeyMasternodeNew, strErrorRet, 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;
LogPrint("masternode", "CMasternodeBroadcast::Create -- pubKeyCollateralAddressNew = %s, pubKeyMasternodeNew.GetID() = %s\n",
CBitcoinAddress(pubKeyCollateralAddressNew.GetID()).ToString(),
pubKeyMasternodeNew.GetID().ToString());
auto Log = [&strErrorRet,&mnbRet](std::string sErr)->bool
{
strErrorRet = sErr;
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
2016-09-05 18:09:25 +02:00
mnbRet = CMasternodeBroadcast();
return false;
};
CMasternodePing mnp(outpoint);
if (!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew))
return Log(strprintf("Failed to sign ping, masternode=%s", outpoint.ToStringShort()));
mnbRet = CMasternodeBroadcast(service, outpoint, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION);
if (!mnbRet.IsValidNetAddr())
return Log(strprintf("Invalid IP address, masternode=%s", outpoint.ToStringShort()));
2016-09-05 18:09:25 +02:00
mnbRet.lastPing = mnp;
if (!mnbRet.Sign(keyCollateralAddressNew))
return Log(strprintf("Failed to sign broadcast, masternode=%s", outpoint.ToStringShort()));
return true;
}
#endif // ENABLE_WALLET
2016-10-20 23:11:30 +02:00
bool CMasternodeBroadcast::SimpleCheck(int& nDos)
{
nDos = 0;
2016-10-20 23:11:30 +02:00
// make sure addr is valid
if(!IsValidNetAddr()) {
LogPrintf("CMasternodeBroadcast::SimpleCheck -- Invalid addr, rejected: masternode=%s addr=%s\n",
vin.prevout.ToStringShort(), addr.ToString());
return false;
}
// make sure signature isn't in the future (past is OK)
if (sigTime > GetAdjustedTime() + 60 * 60) {
2016-10-20 23:11:30 +02:00
LogPrintf("CMasternodeBroadcast::SimpleCheck -- Signature rejected, too far into the future: masternode=%s\n", vin.prevout.ToStringShort());
nDos = 1;
return false;
}
// empty ping or incorrect sigTime/unknown blockhash
if(lastPing == CMasternodePing() || !lastPing.SimpleCheck(nDos)) {
// one of us is probably forked or smth, just mark it as expired and check the rest of the rules
nActiveState = MASTERNODE_EXPIRED;
2016-09-05 18:09:25 +02:00
}
if(nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) {
2016-10-20 23:11:30 +02:00
LogPrintf("CMasternodeBroadcast::SimpleCheck -- ignoring outdated Masternode: masternode=%s nProtocolVersion=%d\n", vin.prevout.ToStringShort(), nProtocolVersion);
return false;
}
CScript pubkeyScript;
pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID());
if(pubkeyScript.size() != 25) {
2016-10-20 23:11:30 +02:00
LogPrintf("CMasternodeBroadcast::SimpleCheck -- pubKeyCollateralAddress has the wrong size\n");
nDos = 100;
return false;
}
CScript pubkeyScript2;
pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID());
if(pubkeyScript2.size() != 25) {
2016-10-20 23:11:30 +02:00
LogPrintf("CMasternodeBroadcast::SimpleCheck -- pubKeyMasternode has the wrong size\n");
nDos = 100;
return false;
}
if(!vin.scriptSig.empty()) {
2016-10-20 23:11:30 +02:00
LogPrintf("CMasternodeBroadcast::SimpleCheck -- Ignore Not Empty ScriptSig %s\n",vin.ToString());
nDos = 100;
return false;
}
int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
if(addr.GetPort() != mainnetDefaultPort) return false;
} else if(addr.GetPort() == mainnetDefaultPort) return false;
2016-10-20 23:11:30 +02:00
return true;
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
bool CMasternodeBroadcast::Update(CMasternode* pmn, int& nDos, CConnman& connman)
2016-10-20 23:11:30 +02:00
{
nDos = 0;
if(pmn->sigTime == sigTime && !fRecovery) {
2016-10-20 23:11:30 +02:00
// mapSeenMasternodeBroadcast in CMasternodeMan::CheckMnbAndUpdateMasternodeList should filter legit duplicates
// but this still can happen if we just started, which is ok, just do nothing here.
return false;
2016-10-20 23:11:30 +02:00
}
2016-10-20 23:11:30 +02:00
// this broadcast is older than the one that we already have - it's bad and should never happen
// unless someone is doing something fishy
2016-10-20 23:11:30 +02:00
if(pmn->sigTime > sigTime) {
LogPrintf("CMasternodeBroadcast::Update -- Bad sigTime %d (existing broadcast is at %d) for Masternode %s %s\n",
sigTime, pmn->sigTime, vin.prevout.ToStringShort(), addr.ToString());
return false;
}
2016-10-20 23:11:30 +02:00
pmn->Check();
// masternode is banned by PoSe
if(pmn->IsPoSeBanned()) {
LogPrintf("CMasternodeBroadcast::Update -- Banned by PoSe, masternode=%s\n", vin.prevout.ToStringShort());
return false;
}
// IsVnAssociatedWithPubkey is validated once in CheckOutpoint, after that they just need to match
if(pmn->pubKeyCollateralAddress != pubKeyCollateralAddress) {
LogPrintf("CMasternodeBroadcast::Update -- Got mismatched pubKeyCollateralAddress and vin\n");
2016-10-20 23:11:30 +02:00
nDos = 33;
return false;
}
if (!CheckSignature(nDos)) {
LogPrintf("CMasternodeBroadcast::Update -- CheckSignature() failed, masternode=%s\n", vin.prevout.ToStringShort());
return false;
}
2016-10-20 23:11:30 +02:00
// if ther was no masternode broadcast recently or if it matches our Masternode privkey...
if(!pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS) || (fMasterNode && pubKeyMasternode == activeMasternode.pubKeyMasternode)) {
// take the newest entry
LogPrintf("CMasternodeBroadcast::Update -- Got UPDATED Masternode entry: addr=%s\n", addr.ToString());
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
if(pmn->UpdateFromNewBroadcast(*this, connman)) {
2015-08-12 03:39:22 +02:00
pmn->Check();
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
Relay(connman);
2015-08-12 03:39:22 +02:00
}
masternodeSync.BumpAssetLastTime("CMasternodeBroadcast::Update");
}
return true;
}
2016-10-20 23:11:30 +02:00
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.outpoint && pubKeyMasternode == activeMasternode.pubKeyMasternode) {
return false;
2016-09-05 18:09:25 +02:00
}
AssertLockHeld(cs_main);
int nHeight;
CollateralStatus err = CheckCollateral(vin.prevout, pubKeyCollateralAddress, nHeight);
if (err == COLLATERAL_UTXO_NOT_FOUND) {
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
return false;
}
if (err == COLLATERAL_INVALID_AMOUNT) {
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should have 1000 DASH, masternode=%s\n", vin.prevout.ToStringShort());
nDos = 33;
return false;
}
if(err == COLLATERAL_INVALID_PUBKEY) {
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should match pubKeyCollateralAddress, masternode=%s\n", vin.prevout.ToStringShort());
nDos = 33;
return false;
}
if(chainActive.Height() - nHeight + 1 < Params().GetConsensus().nMasternodeMinimumConfirmations) {
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO must have at least %d confirmations, masternode=%s\n",
Params().GetConsensus().nMasternodeMinimumConfirmations, vin.prevout.ToStringShort());
// UTXO is legit but has not enough confirmations.
// Maybe we miss few blocks, let this mnb be checked again later.
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
return false;
2015-07-30 15:44:18 +02:00
}
2016-10-20 23:11:30 +02:00
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO verified\n");
// Verify that sig time is legit, should be at least not earlier than the timestamp of the block
// at which collateral became nMasternodeMinimumConfirmations blocks deep.
// NOTE: this is not accurate because block timestamp is NOT guaranteed to be 100% correct one.
CBlockIndex* pRequiredConfIndex = chainActive[nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations
if(pRequiredConfIndex->GetBlockTime() > sigTime) {
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n",
sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pRequiredConfIndex->GetBlockTime(), vin.prevout.ToStringShort(), addr.ToString());
2015-07-30 15:44:18 +02:00
return false;
}
if (!CheckSignature(nDos)) {
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- CheckSignature() failed, masternode=%s\n", vin.prevout.ToStringShort());
return false;
2015-07-30 15:44:18 +02:00
}
// remember the block hash when collateral for this masternode had minimum required confirmations
nCollateralMinConfBlockHash = pRequiredConfIndex->GetBlockHash();
2015-07-30 15:44:18 +02:00
return true;
}
bool CMasternodeBroadcast::Sign(const CKey& keyCollateralAddress)
{
std::string strError;
std::string strMessage;
sigTime = GetAdjustedTime();
strMessage = addr.ToString(false) + boost::lexical_cast<std::string>(sigTime) +
pubKeyCollateralAddress.GetID().ToString() + pubKeyMasternode.GetID().ToString() +
boost::lexical_cast<std::string>(nProtocolVersion);
if(!CMessageSigner::SignMessage(strMessage, vchSig, keyCollateralAddress)) {
LogPrintf("CMasternodeBroadcast::Sign -- SignMessage() failed\n");
return false;
}
if(!CMessageSigner::VerifyMessage(pubKeyCollateralAddress, vchSig, strMessage, strError)) {
LogPrintf("CMasternodeBroadcast::Sign -- VerifyMessage() failed, error: %s\n", strError);
return false;
}
return true;
}
bool CMasternodeBroadcast::CheckSignature(int& nDos)
{
std::string strMessage;
std::string strError = "";
nDos = 0;
strMessage = addr.ToString(false) + boost::lexical_cast<std::string>(sigTime) +
pubKeyCollateralAddress.GetID().ToString() + pubKeyMasternode.GetID().ToString() +
boost::lexical_cast<std::string>(nProtocolVersion);
LogPrint("masternode", "CMasternodeBroadcast::CheckSignature -- strMessage: %s pubKeyCollateralAddress address: %s sig: %s\n", strMessage, CBitcoinAddress(pubKeyCollateralAddress.GetID()).ToString(), EncodeBase64(&vchSig[0], vchSig.size()));
if(!CMessageSigner::VerifyMessage(pubKeyCollateralAddress, vchSig, strMessage, strError)){
LogPrintf("CMasternodeBroadcast::CheckSignature -- Got bad Masternode announce signature, error: %s\n", strError);
nDos = 100;
return false;
}
return true;
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodeBroadcast::Relay(CConnman& connman)
{
// Do not relay until fully synced
if(!masternodeSync.IsSynced()) {
LogPrint("masternode", "CMasternodeBroadcast::Relay -- won't relay until fully synced\n");
return;
}
CInv inv(MSG_MASTERNODE_ANNOUNCE, GetHash());
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
connman.RelayInv(inv);
}
CMasternodePing::CMasternodePing(const COutPoint& outpoint)
{
LOCK(cs_main);
if (!chainActive.Tip() || chainActive.Height() < 12) return;
vin = CTxIn(outpoint);
blockHash = chainActive[chainActive.Height() - 12]->GetBlockHash();
sigTime = GetAdjustedTime();
}
bool CMasternodePing::Sign(const CKey& keyMasternode, const CPubKey& pubKeyMasternode)
{
std::string strError;
std::string strMasterNodeSignMessage;
// TODO: add sentinel data
sigTime = GetAdjustedTime();
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
if(!CMessageSigner::SignMessage(strMessage, vchSig, keyMasternode)) {
LogPrintf("CMasternodePing::Sign -- SignMessage() failed\n");
return false;
}
if(!CMessageSigner::VerifyMessage(pubKeyMasternode, vchSig, strMessage, strError)) {
LogPrintf("CMasternodePing::Sign -- VerifyMessage() failed, error: %s\n", strError);
return false;
}
return true;
}
bool CMasternodePing::CheckSignature(CPubKey& pubKeyMasternode, int &nDos)
{
// TODO: add sentinel data
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
std::string strError = "";
nDos = 0;
if(!CMessageSigner::VerifyMessage(pubKeyMasternode, vchSig, strMessage, strError)) {
LogPrintf("CMasternodePing::CheckSignature -- Got bad Masternode ping signature, masternode=%s, error: %s\n", vin.prevout.ToStringShort(), strError);
nDos = 33;
return false;
}
return true;
}
bool CMasternodePing::SimpleCheck(int& nDos)
{
// don't ban by default
nDos = 0;
if (sigTime > GetAdjustedTime() + 60 * 60) {
LogPrintf("CMasternodePing::SimpleCheck -- Signature rejected, too far into the future, masternode=%s\n", vin.prevout.ToStringShort());
nDos = 1;
return false;
}
{
AssertLockHeld(cs_main);
BlockMap::iterator mi = mapBlockIndex.find(blockHash);
if (mi == mapBlockIndex.end()) {
LogPrint("masternode", "CMasternodePing::SimpleCheck -- Masternode ping is invalid, unknown block hash: masternode=%s blockHash=%s\n", vin.prevout.ToStringShort(), blockHash.ToString());
// maybe we stuck or forked so we shouldn't ban this node, just fail to accept this ping
// TODO: or should we also request this block?
return false;
}
}
LogPrint("masternode", "CMasternodePing::SimpleCheck -- Masternode ping verified: masternode=%s blockHash=%s sigTime=%d\n", vin.prevout.ToStringShort(), blockHash.ToString(), sigTime);
return true;
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
bool CMasternodePing::CheckAndUpdate(CMasternode* pmn, bool fFromNewBroadcast, int& nDos, CConnman& connman)
{
// don't ban by default
nDos = 0;
if (!SimpleCheck(nDos)) {
return false;
}
if (pmn == NULL) {
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Couldn't find Masternode entry, masternode=%s\n", vin.prevout.ToStringShort());
return false;
}
2016-12-26 07:44:48 +01:00
if(!fFromNewBroadcast) {
if (pmn->IsUpdateRequired()) {
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- masternode protocol is outdated, masternode=%s\n", vin.prevout.ToStringShort());
return false;
}
if (pmn->IsNewStartRequired()) {
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- masternode is completely expired, new start is required, masternode=%s\n", vin.prevout.ToStringShort());
return false;
}
}
{
LOCK(cs_main);
BlockMap::iterator mi = mapBlockIndex.find(blockHash);
if ((*mi).second && (*mi).second->nHeight < chainActive.Height() - 24) {
LogPrintf("CMasternodePing::CheckAndUpdate -- Masternode ping is invalid, block hash is too old: masternode=%s blockHash=%s\n", vin.prevout.ToStringShort(), blockHash.ToString());
// nDos = 1;
return false;
}
}
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- New ping: masternode=%s blockHash=%s sigTime=%d\n", vin.prevout.ToStringShort(), blockHash.ToString(), sigTime);
2015-07-20 20:43:10 +02:00
// LogPrintf("mnping - Found corresponding mn for vin: %s\n", vin.prevout.ToStringShort());
// update only if there is no known ping for this masternode or
// last ping was more then MASTERNODE_MIN_MNP_SECONDS-60 ago comparing to this one
if (pmn->IsPingedWithin(MASTERNODE_MIN_MNP_SECONDS - 60, sigTime)) {
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Masternode ping arrived too early, masternode=%s\n", vin.prevout.ToStringShort());
//nDos = 1; //disable, this is happening frequently and causing banned peers
return false;
}
if (!CheckSignature(pmn->pubKeyMasternode, nDos)) return false;
// so, ping seems to be ok
// if we are still syncing and there was no known ping for this mn for quite a while
// (NOTE: assuming that MASTERNODE_EXPIRATION_SECONDS/2 should be enough to finish mn list sync)
if(!masternodeSync.IsMasternodeListSynced() && !pmn->IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS/2)) {
// let's bump sync timeout
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- bumping sync timeout, masternode=%s\n", vin.prevout.ToStringShort());
masternodeSync.BumpAssetLastTime("CMasternodePing::CheckAndUpdate");
}
// let's store this ping as the last one
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Masternode ping accepted, masternode=%s\n", vin.prevout.ToStringShort());
pmn->lastPing = *this;
// and update mnodeman.mapSeenMasternodeBroadcast.lastPing which is probably outdated
CMasternodeBroadcast mnb(*pmn);
uint256 hash = mnb.GetHash();
if (mnodeman.mapSeenMasternodeBroadcast.count(hash)) {
mnodeman.mapSeenMasternodeBroadcast[hash].second.lastPing = *this;
}
// force update, ignoring cache
pmn->Check(true);
// relay ping for nodes in ENABLED/EXPIRED/WATCHDOG_EXPIRED state only, skip everyone else
if (!pmn->IsEnabled() && !pmn->IsExpired() && !pmn->IsWatchdogExpired()) return false;
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Masternode ping acceepted and relayed, masternode=%s\n", vin.prevout.ToStringShort());
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
Relay(connman);
return true;
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodePing::Relay(CConnman& connman)
{
// Do not relay until fully synced
if(!masternodeSync.IsSynced()) {
LogPrint("masternode", "CMasternodePing::Relay -- won't relay until fully synced\n");
return;
}
CInv inv(MSG_MASTERNODE_PING, GetHash());
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
connman.RelayInv(inv);
}
Merge #944: V0.12.1.x governance pr - part 1 - base functionality 068c178 Added DBG macro in util.h to facilitate debugging - This macro allows debugging statements (typically printf's or cout's) to be activated or deactivated with a single comment. Uncomment the line: //#define ENABLE_DASH_DEBUG in util.h to enable debugging statements. - When commented any code wrapped with the DBG() macro will simply be removed by the preprocessor. When not commented all such wrapped statements will be present. - For maximum effectiveness it is best that util.h be the first effective include in all source files. It is also possible to enable the macro for a single file by temporarily adding #define ENABLE_DASH_DEBUG to the top of the file. - Code committed to non-development branches should always have the define commented. d125d9b V0.12.1.x -- merging trigger/generic object/superblock changes for testnet phase II - This commit contains the core governance system changes for 0.12.1. Any unrelated changes have either been removed or moved to separate commits. 120724c File mode fixes - Changed mode 0755->0644 on several source files. c7f9e11 Updated todo reminders - Added reminder to revert temporary reduction of number of votes required to trigger superblock to 1 for testing 92adc98 Made CSuperblockManager::IsValidSuperblockHeight an inline function - This is for efficiency since this function is called often and is only 1 line of code. c050ed7 Added comment explaining rationale for no LOCK(cs) in CSuperblock::IsValid dc933fe Removed unused CSuperblockManager::IsBlockValid function decec88 Moved calls to SuperblockManager::IsValidSuperblockHeight into IsSuperblockTriggered. - Since calls to the later function are always protected by the former there's no reason to keep these separate and this simplifies the code in masternode-payments.cpp. 8672885 Reestablished expected value check for non-superblocks in IsBlockValueValid b01cbe0 Changes to IsBlockValueValid to fix rpc test failure a937c76 Changed include order to allow per file activation of the DBG macro d116aa5 Fixed IsValidSuperblockHeight logic - Note this has an effect on testing because we can now only create 1 superblock per day. Devs may need to temporarily change testnet params for easier testing. 2d0c2de Convert superblock payments to CAmount - We assume that payment values in JSON are in units of DASH for consistency with other RPC functions, such as createrawtransaction. 376b833 Revert temporary testing value for nAbsVoteReq - Also ensure that number of votes required is never smaller than 1 8c89f4b Cleaned up CSuperblock error handling - Exceptions are now thrown consistently rather than using a mix of exceptions and return code checking. Exceptions are now caught only in AddNewTrigger when the CSuperblock constructor is called. Unnecessary object status members have been removed. d7c8a6b Removed utilstrencodings header - This appears to help with travis tests, for unknown reasons. c4dfc7a Fixed some minor code review issues 63c3580 Reverted locking change in miner. - This should have been done in the original PR but was overlooked. 4ab72de Fixed variable name to match common practice and bracket formatting 886a678 Improvements to vote conversion code - Replaced redundantly defined function with inclusion of governance-vote.h - Replaced magic numbers with their corresponding constant symbols 0a37966 Reordered governance message handling
2016-08-17 09:08:25 +02:00
void CMasternode::AddGovernanceVote(uint256 nGovernanceObjectHash)
{
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
if(mapGovernanceObjectsVotedOn.count(nGovernanceObjectHash)) {
mapGovernanceObjectsVotedOn[nGovernanceObjectHash]++;
Merge #944: V0.12.1.x governance pr - part 1 - base functionality 068c178 Added DBG macro in util.h to facilitate debugging - This macro allows debugging statements (typically printf's or cout's) to be activated or deactivated with a single comment. Uncomment the line: //#define ENABLE_DASH_DEBUG in util.h to enable debugging statements. - When commented any code wrapped with the DBG() macro will simply be removed by the preprocessor. When not commented all such wrapped statements will be present. - For maximum effectiveness it is best that util.h be the first effective include in all source files. It is also possible to enable the macro for a single file by temporarily adding #define ENABLE_DASH_DEBUG to the top of the file. - Code committed to non-development branches should always have the define commented. d125d9b V0.12.1.x -- merging trigger/generic object/superblock changes for testnet phase II - This commit contains the core governance system changes for 0.12.1. Any unrelated changes have either been removed or moved to separate commits. 120724c File mode fixes - Changed mode 0755->0644 on several source files. c7f9e11 Updated todo reminders - Added reminder to revert temporary reduction of number of votes required to trigger superblock to 1 for testing 92adc98 Made CSuperblockManager::IsValidSuperblockHeight an inline function - This is for efficiency since this function is called often and is only 1 line of code. c050ed7 Added comment explaining rationale for no LOCK(cs) in CSuperblock::IsValid dc933fe Removed unused CSuperblockManager::IsBlockValid function decec88 Moved calls to SuperblockManager::IsValidSuperblockHeight into IsSuperblockTriggered. - Since calls to the later function are always protected by the former there's no reason to keep these separate and this simplifies the code in masternode-payments.cpp. 8672885 Reestablished expected value check for non-superblocks in IsBlockValueValid b01cbe0 Changes to IsBlockValueValid to fix rpc test failure a937c76 Changed include order to allow per file activation of the DBG macro d116aa5 Fixed IsValidSuperblockHeight logic - Note this has an effect on testing because we can now only create 1 superblock per day. Devs may need to temporarily change testnet params for easier testing. 2d0c2de Convert superblock payments to CAmount - We assume that payment values in JSON are in units of DASH for consistency with other RPC functions, such as createrawtransaction. 376b833 Revert temporary testing value for nAbsVoteReq - Also ensure that number of votes required is never smaller than 1 8c89f4b Cleaned up CSuperblock error handling - Exceptions are now thrown consistently rather than using a mix of exceptions and return code checking. Exceptions are now caught only in AddNewTrigger when the CSuperblock constructor is called. Unnecessary object status members have been removed. d7c8a6b Removed utilstrencodings header - This appears to help with travis tests, for unknown reasons. c4dfc7a Fixed some minor code review issues 63c3580 Reverted locking change in miner. - This should have been done in the original PR but was overlooked. 4ab72de Fixed variable name to match common practice and bracket formatting 886a678 Improvements to vote conversion code - Replaced redundantly defined function with inclusion of governance-vote.h - Replaced magic numbers with their corresponding constant symbols 0a37966 Reordered governance message handling
2016-08-17 09:08:25 +02:00
} else {
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
mapGovernanceObjectsVotedOn.insert(std::make_pair(nGovernanceObjectHash, 1));
Merge #944: V0.12.1.x governance pr - part 1 - base functionality 068c178 Added DBG macro in util.h to facilitate debugging - This macro allows debugging statements (typically printf's or cout's) to be activated or deactivated with a single comment. Uncomment the line: //#define ENABLE_DASH_DEBUG in util.h to enable debugging statements. - When commented any code wrapped with the DBG() macro will simply be removed by the preprocessor. When not commented all such wrapped statements will be present. - For maximum effectiveness it is best that util.h be the first effective include in all source files. It is also possible to enable the macro for a single file by temporarily adding #define ENABLE_DASH_DEBUG to the top of the file. - Code committed to non-development branches should always have the define commented. d125d9b V0.12.1.x -- merging trigger/generic object/superblock changes for testnet phase II - This commit contains the core governance system changes for 0.12.1. Any unrelated changes have either been removed or moved to separate commits. 120724c File mode fixes - Changed mode 0755->0644 on several source files. c7f9e11 Updated todo reminders - Added reminder to revert temporary reduction of number of votes required to trigger superblock to 1 for testing 92adc98 Made CSuperblockManager::IsValidSuperblockHeight an inline function - This is for efficiency since this function is called often and is only 1 line of code. c050ed7 Added comment explaining rationale for no LOCK(cs) in CSuperblock::IsValid dc933fe Removed unused CSuperblockManager::IsBlockValid function decec88 Moved calls to SuperblockManager::IsValidSuperblockHeight into IsSuperblockTriggered. - Since calls to the later function are always protected by the former there's no reason to keep these separate and this simplifies the code in masternode-payments.cpp. 8672885 Reestablished expected value check for non-superblocks in IsBlockValueValid b01cbe0 Changes to IsBlockValueValid to fix rpc test failure a937c76 Changed include order to allow per file activation of the DBG macro d116aa5 Fixed IsValidSuperblockHeight logic - Note this has an effect on testing because we can now only create 1 superblock per day. Devs may need to temporarily change testnet params for easier testing. 2d0c2de Convert superblock payments to CAmount - We assume that payment values in JSON are in units of DASH for consistency with other RPC functions, such as createrawtransaction. 376b833 Revert temporary testing value for nAbsVoteReq - Also ensure that number of votes required is never smaller than 1 8c89f4b Cleaned up CSuperblock error handling - Exceptions are now thrown consistently rather than using a mix of exceptions and return code checking. Exceptions are now caught only in AddNewTrigger when the CSuperblock constructor is called. Unnecessary object status members have been removed. d7c8a6b Removed utilstrencodings header - This appears to help with travis tests, for unknown reasons. c4dfc7a Fixed some minor code review issues 63c3580 Reverted locking change in miner. - This should have been done in the original PR but was overlooked. 4ab72de Fixed variable name to match common practice and bracket formatting 886a678 Improvements to vote conversion code - Replaced redundantly defined function with inclusion of governance-vote.h - Replaced magic numbers with their corresponding constant symbols 0a37966 Reordered governance message handling
2016-08-17 09:08:25 +02:00
}
}
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
void CMasternode::RemoveGovernanceObject(uint256 nGovernanceObjectHash)
{
std::map<uint256, int>::iterator it = mapGovernanceObjectsVotedOn.find(nGovernanceObjectHash);
if(it == mapGovernanceObjectsVotedOn.end()) {
return;
}
mapGovernanceObjectsVotedOn.erase(it);
}
void CMasternode::UpdateWatchdogVoteTime(uint64_t nVoteTime)
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
nTimeLastWatchdogVote = (nVoteTime == 0) ? GetAdjustedTime() : nVoteTime;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
/**
Merge #944: V0.12.1.x governance pr - part 1 - base functionality 068c178 Added DBG macro in util.h to facilitate debugging - This macro allows debugging statements (typically printf's or cout's) to be activated or deactivated with a single comment. Uncomment the line: //#define ENABLE_DASH_DEBUG in util.h to enable debugging statements. - When commented any code wrapped with the DBG() macro will simply be removed by the preprocessor. When not commented all such wrapped statements will be present. - For maximum effectiveness it is best that util.h be the first effective include in all source files. It is also possible to enable the macro for a single file by temporarily adding #define ENABLE_DASH_DEBUG to the top of the file. - Code committed to non-development branches should always have the define commented. d125d9b V0.12.1.x -- merging trigger/generic object/superblock changes for testnet phase II - This commit contains the core governance system changes for 0.12.1. Any unrelated changes have either been removed or moved to separate commits. 120724c File mode fixes - Changed mode 0755->0644 on several source files. c7f9e11 Updated todo reminders - Added reminder to revert temporary reduction of number of votes required to trigger superblock to 1 for testing 92adc98 Made CSuperblockManager::IsValidSuperblockHeight an inline function - This is for efficiency since this function is called often and is only 1 line of code. c050ed7 Added comment explaining rationale for no LOCK(cs) in CSuperblock::IsValid dc933fe Removed unused CSuperblockManager::IsBlockValid function decec88 Moved calls to SuperblockManager::IsValidSuperblockHeight into IsSuperblockTriggered. - Since calls to the later function are always protected by the former there's no reason to keep these separate and this simplifies the code in masternode-payments.cpp. 8672885 Reestablished expected value check for non-superblocks in IsBlockValueValid b01cbe0 Changes to IsBlockValueValid to fix rpc test failure a937c76 Changed include order to allow per file activation of the DBG macro d116aa5 Fixed IsValidSuperblockHeight logic - Note this has an effect on testing because we can now only create 1 superblock per day. Devs may need to temporarily change testnet params for easier testing. 2d0c2de Convert superblock payments to CAmount - We assume that payment values in JSON are in units of DASH for consistency with other RPC functions, such as createrawtransaction. 376b833 Revert temporary testing value for nAbsVoteReq - Also ensure that number of votes required is never smaller than 1 8c89f4b Cleaned up CSuperblock error handling - Exceptions are now thrown consistently rather than using a mix of exceptions and return code checking. Exceptions are now caught only in AddNewTrigger when the CSuperblock constructor is called. Unnecessary object status members have been removed. d7c8a6b Removed utilstrencodings header - This appears to help with travis tests, for unknown reasons. c4dfc7a Fixed some minor code review issues 63c3580 Reverted locking change in miner. - This should have been done in the original PR but was overlooked. 4ab72de Fixed variable name to match common practice and bracket formatting 886a678 Improvements to vote conversion code - Replaced redundantly defined function with inclusion of governance-vote.h - Replaced magic numbers with their corresponding constant symbols 0a37966 Reordered governance message handling
2016-08-17 09:08:25 +02:00
* FLAG GOVERNANCE ITEMS AS DIRTY
*
* - When masternode come and go on the network, we must flag the items they voted on to recalc it's cached flags
*
*/
void CMasternode::FlagGovernanceItemsAsDirty()
{
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
std::vector<uint256> vecDirty;
{
std::map<uint256, int>::iterator it = mapGovernanceObjectsVotedOn.begin();
while(it != mapGovernanceObjectsVotedOn.end()) {
vecDirty.push_back(it->first);
++it;
}
}
for(size_t i = 0; i < vecDirty.size(); ++i) {
mnodeman.AddDirtyGovernanceObjectHash(vecDirty[i]);
Merge #944: V0.12.1.x governance pr - part 1 - base functionality 068c178 Added DBG macro in util.h to facilitate debugging - This macro allows debugging statements (typically printf's or cout's) to be activated or deactivated with a single comment. Uncomment the line: //#define ENABLE_DASH_DEBUG in util.h to enable debugging statements. - When commented any code wrapped with the DBG() macro will simply be removed by the preprocessor. When not commented all such wrapped statements will be present. - For maximum effectiveness it is best that util.h be the first effective include in all source files. It is also possible to enable the macro for a single file by temporarily adding #define ENABLE_DASH_DEBUG to the top of the file. - Code committed to non-development branches should always have the define commented. d125d9b V0.12.1.x -- merging trigger/generic object/superblock changes for testnet phase II - This commit contains the core governance system changes for 0.12.1. Any unrelated changes have either been removed or moved to separate commits. 120724c File mode fixes - Changed mode 0755->0644 on several source files. c7f9e11 Updated todo reminders - Added reminder to revert temporary reduction of number of votes required to trigger superblock to 1 for testing 92adc98 Made CSuperblockManager::IsValidSuperblockHeight an inline function - This is for efficiency since this function is called often and is only 1 line of code. c050ed7 Added comment explaining rationale for no LOCK(cs) in CSuperblock::IsValid dc933fe Removed unused CSuperblockManager::IsBlockValid function decec88 Moved calls to SuperblockManager::IsValidSuperblockHeight into IsSuperblockTriggered. - Since calls to the later function are always protected by the former there's no reason to keep these separate and this simplifies the code in masternode-payments.cpp. 8672885 Reestablished expected value check for non-superblocks in IsBlockValueValid b01cbe0 Changes to IsBlockValueValid to fix rpc test failure a937c76 Changed include order to allow per file activation of the DBG macro d116aa5 Fixed IsValidSuperblockHeight logic - Note this has an effect on testing because we can now only create 1 superblock per day. Devs may need to temporarily change testnet params for easier testing. 2d0c2de Convert superblock payments to CAmount - We assume that payment values in JSON are in units of DASH for consistency with other RPC functions, such as createrawtransaction. 376b833 Revert temporary testing value for nAbsVoteReq - Also ensure that number of votes required is never smaller than 1 8c89f4b Cleaned up CSuperblock error handling - Exceptions are now thrown consistently rather than using a mix of exceptions and return code checking. Exceptions are now caught only in AddNewTrigger when the CSuperblock constructor is called. Unnecessary object status members have been removed. d7c8a6b Removed utilstrencodings header - This appears to help with travis tests, for unknown reasons. c4dfc7a Fixed some minor code review issues 63c3580 Reverted locking change in miner. - This should have been done in the original PR but was overlooked. 4ab72de Fixed variable name to match common practice and bracket formatting 886a678 Improvements to vote conversion code - Replaced redundantly defined function with inclusion of governance-vote.h - Replaced magic numbers with their corresponding constant symbols 0a37966 Reordered governance message handling
2016-08-17 09:08:25 +02:00
}
}