+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ unsigned int nSerSize = 0;
READWRITE(txHash);
READWRITE(vinMasternode);
READWRITE(vchMasterNodeSignature);
READWRITE(nBlockHeight);
- )
+ }
};
class CTransactionLock
diff --git a/src/kernel.cpp b/src/kernel.cpp
index cb75047d..d6390b4b 100644
--- a/src/kernel.cpp
+++ b/src/kernel.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2012-2013 The PPCoin developers
-// Copyright (c) 2014 The Memetic developers
+// Copyright (c) 2014 The PepeCoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -318,8 +318,15 @@ bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned
int nDepth;
nStakeMinConfirmations = 360; // 6 hours
- if((pindexPrev->nHeight+1) >= PEPE_STAKE_WINTER_SWITCH_HEIGHT)
+ if((pindexPrev->nHeight+1) >= PEPE_STAKE_WINTER_SWITCH_HEIGHT || Params().NetworkID() == CChainParams::TESTNET)
nStakeMinConfirmations = 60;
+ // if((pindexPrev->nHeight+1) > PEPE_KEKDAQ_MID_FIX_HEIGHT) //revert fix until stake_conf_height to resolve block loading issue
+ // nStakeMinConfirmations = 600;
+ if((pindexPrev->nHeight+1) > PEPE_STAKE_CONF_HEIGHT)
+ nStakeMinConfirmations = 360;
+ if((pindexPrev->nHeight+1) > PEPE_STAKE_CONF_TWEAK)
+ nStakeMinConfirmations = 600;
+
if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, nStakeMinConfirmations - 1, nDepth))
return tx.DoS(100, error("CheckProofOfStake() : tried to stake at depth %d", nDepth + 1));
@@ -372,6 +379,10 @@ bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, int64_t nTime, con
int nStakeMinConfirmations = 360; // 6 hours
if((pindexPrev->nHeight+1) >= PEPE_STAKE_WINTER_SWITCH_HEIGHT)
nStakeMinConfirmations = 60;
+ if((pindexPrev->nHeight+1) > PEPE_STAKE_CONF_HEIGHT)
+ nStakeMinConfirmations = 360;
+ if((pindexPrev->nHeight+1) > PEPE_STAKE_CONF_TWEAK)
+ nStakeMinConfirmations = 600;
if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, nStakeMinConfirmations - 1, nDepth))
return false;
diff --git a/src/leveldb/AUTHORS b/src/leveldb/AUTHORS
old mode 100755
new mode 100644
diff --git a/src/leveldb/LICENSE b/src/leveldb/LICENSE
old mode 100755
new mode 100644
diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile
old mode 100755
new mode 100644
diff --git a/src/leveldb/NEWS b/src/leveldb/NEWS
old mode 100755
new mode 100644
diff --git a/src/leveldb/README b/src/leveldb/README
old mode 100755
new mode 100644
diff --git a/src/leveldb/TODO b/src/leveldb/TODO
old mode 100755
new mode 100644
diff --git a/src/leveldb/WINDOWS.md b/src/leveldb/WINDOWS.md
old mode 100755
new mode 100644
diff --git a/src/leveldb/doc/index.html b/src/leveldb/doc/index.html
index d7683f13..fa135c9d 100644
--- a/src/leveldb/doc/index.html
+++ b/src/leveldb/doc/index.html
@@ -101,7 +101,7 @@ Atomic Updates
Synchronous Writes
By default, each write to leveldb is asynchronous: it
returns after pushing the write from the process into the operating
-system. The memetic from operating system memory to the underlying
+system. The pepecoin from operating system memory to the underlying
persistent storage happens asynchronously. The sync flag
can be turned on for a particular write to make the write operation
not return until the data being written has been pushed all the way to
@@ -319,7 +319,7 @@ Performance
Block size
leveldb groups adjacent keys together into the same block and such a
-block is the unit of memetic to and from persistent storage. The
+block is the unit of pepecoin to and from persistent storage. The
default block size is approximately 4096 uncompressed bytes.
Applications that mostly do bulk scans over the contents of the
database may wish to increase this size. Applications that do a lot
@@ -382,7 +382,7 @@
Cache
Key Layout
-Note that the unit of disk memetic and caching is a block. Adjacent
+Note that the unit of disk pepecoin and caching is a block. Adjacent
keys (according to the database sort order) will usually be placed in
the same block. Therefore the application can improve its performance
by placing keys that are accessed together near each other and placing
diff --git a/src/main.cpp b/src/main.cpp
index 7c2a7849..aedc8839 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -9,6 +9,7 @@
// Copyright (c) 2014 NetCoin Developers
// Copyright (c) 2015 Transfercoin Developer
// Copyright (c) 2015-2016 PepeCoin Developers
+// Copyright (c) 2016-2019 Memetic / PepeCoin Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -29,8 +30,7 @@
#include "ui_interface.h"
#include "instantx.h"
#include "darksend.h"
-#include "masternodeman.h"
-#include "masternode-payments.h"
+#include "masternode.h"
#include "spork.h"
#include "smessage.h"
@@ -57,7 +57,7 @@ CBigNum bnProofOfStakeLimit(~uint256(0) >> 20);
unsigned int nStakeMinAge = 6 * 60 * 60; // 6 hours temporary 1 hr for test
unsigned int nModifierInterval = 2 * 60; // time to elapse before new modifier is computed
-int nCoinbaseMaturity = 60;
+int nCoinbaseMaturity = 60; // 60 blocks until new POW or POS minted coins can be moved
CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
@@ -327,7 +327,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
return false;
}
// nTime has different purpose from nLockTime but can be used in similar attacks
- if (tx.nTime > FutureDrift(GetAdjustedTime())) {
+ if (tx.nTime > FutureDrift(GetAdjustedTime(), nBestHeight + 1)) {
reason = "time-too-new";
return false;
}
@@ -400,6 +400,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
AssertLockHeld(cs_main);
+
// Time based nLockTime implemented in 0.1.6
if (tx.nLockTime == 0)
return true;
@@ -697,13 +698,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx, bool fLimitFree,
// ----------- instantX transaction scanning -----------
- BOOST_FOREACH(const CTxIn& in, tx.vin){
+ /*BOOST_FOREACH(const CTxIn& in, tx.vin){
if(mapLockedInputs.count(in.prevout)){
if(mapLockedInputs[in.prevout] != tx.GetHash()){
return tx.DoS(0, error("AcceptToMemoryPool : conflicts with existing transaction lock: %s", reason));
}
}
- }
+ }*/
// Check for conflicts with in-memory transactions
{
@@ -714,7 +715,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx, bool fLimitFree,
if (pool.mapNextTx.count(outpoint))
{
// Disable replacement feature for now
- return false;
+ // return false;
}
}
}
@@ -844,7 +845,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx, bool fLimitFree,
bool AcceptableInputs(CTxMemPool& pool, const CTransaction &txo, bool fLimitFree,
bool* pfMissingInputs, bool fRejectInsaneFee, bool isDSTX)
{
- AssertLockHeld(cs_main);
+ //AssertLockHeld(cs_main);
if (pfMissingInputs)
*pfMissingInputs = false;
@@ -1010,32 +1011,6 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
return pindexBest->nHeight - pindex->nHeight + 1;
}
-int CMerkleTx::GetTransactionLockSignatures() const
-{
- if(!IsSporkActive(SPORK_2_INSTANTX)) return -3;
- if(!fEnableInstantX) return -1;
-
- //compile consessus vote
- std::map::iterator i = mapTxLocks.find(GetHash());
- if (i != mapTxLocks.end()){
- return (*i).second.CountSignatures();
- }
-
- return -1;
-}
-
-bool CMerkleTx::IsTransactionLockTimedOut() const
-{
- if(!fEnableInstantX) return -1;
-
- //compile consessus vote
- std::map::iterator i = mapTxLocks.find(GetHash());
- if (i != mapTxLocks.end()){
- return GetTime() > (*i).second.nTimeout;
- }
-
- return false;
-}
int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet, bool enableIX) const
{
@@ -1044,15 +1019,6 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet, bool enableIX) const
if (nResult == 0 && !mempool.exists(GetHash()))
return -1; // Not in chain, not in mempool
- if(enableIX){
- if (nResult < 10){
- int signatures = GetTransactionLockSignatures();
- if(signatures >= INSTANTX_SIGNATURES_REQUIRED){
- return nInstantXDepth+nResult;
- }
- }
- }
-
return nResult;
}
@@ -1100,7 +1066,7 @@ int GetInputAge(CTxIn& vin)
const uint256& prevHash = vin.prevout.hash;
CTransaction tx;
uint256 hashBlock;
- bool fFound = GetTransaction(prevHash, tx, hashBlock);
+ bool fFound = GetTransaction(prevHash, tx, hashBlock, false);
if(fFound)
{
if(mapBlockIndex.find(hashBlock) != mapBlockIndex.end())
@@ -1166,14 +1132,17 @@ int CTxIndex::GetDepthInMainChain() const
}
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
-bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock)
+bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fCheckMempool)
{
{
- LOCK(cs_main);
+ if(fCheckMempool) // avoid the mempool check and lock on cs_main if called from the masternode message handler
{
- if (mempool.lookup(hash, tx))
+ LOCK(cs_main);
{
- return true;
+ if (mempool.lookup(hash, tx))
+ {
+ return true;
+ }
}
}
CTxDB txdb("r");
@@ -1532,29 +1501,40 @@ int64_t nSubsidy = 20 * COIN;
{
nSubsidy = 20 * COIN;
}
- else if(nHeight > RESTART_POW_BLOCK)
+ else if(nHeight > RESTART_POW_BLOCK && nHeight < PEPE_REBRAND_HEIGHT)
{
nSubsidy = 10 * COIN;
nSubsidy >>= (nHeight / 131400); // block reward halves roughly four times a year a year (every 365/4 days at 1440 blocks per day)
}
- return nSubsidy + nFees;
-
-}
+ else if(nHeight >= PEPE_REBRAND_HEIGHT)
+ {
+ // subsidy starts at 7 Coins per block for 43,200 blocks
+ if(nHeight <= (PEPE_REBRAND_HEIGHT + 43200))
+ {
+ nSubsidy = 7 * COIN;
+ }
+ else
+ {
+ nSubsidy = 15 * COIN;
+ nSubsidy >>= ((nHeight - PEPE_REBRAND_HEIGHT) / 525600); // block reward halves once a year
+ }
+
+ if(nHeight == PEPE_REBRAND_PF_HEIGHT)
+ nSubsidy += (3 * PEPE_DEV_GRANT);
+ if(nHeight == PEPE_KEKDAQ_MID_FIX_HEIGHT)
+ nSubsidy += (3 * PEPE_DEV_GRANT_MID);
+ if(nHeight == PEPE_IPFSMN_FNL_HEIGHT)
+ nSubsidy += (3 * PEPE_DEV_GRANT_FINAL);
+ if(nHeight == PEPE_STAKE_CONF_HEIGHT)
+ nSubsidy += (3 * PEPE_DEV_GRANT);
+ if(nHeight == PEPE_KEKDAQ2_SWAP_HEIGHT)
+ nSubsidy += (3 * DEVFEE_OFF_SWAP_FINAL);
-/*
- // PEPE STAKE RATE CALCULATION
- // Original credit to: madprofezzor@gmail.com
+ }
- // returns an integer between 0 and PIR_PHASES-1 representing which PIR phase the supplied block height falls into
+ return nSubsidy + nFees;
- Pepe Stake Rate (PSR) %
-| PEPE Amount | Stake % Year 1| Year 2 | Year 3+ |
-|:-------------|:-------------:|------------:|------------:|
- |0 to 10000 | 3.0% | 2.0% | 1.0% |
- |10,000+ | 4.0%| 3.0% | 2.0% |
- |50,000+ | 5.0%| 4.0% | 3.0% |
- |100,000+ | 6.0%| 5.0% | 4.0% |
-*/
+}
int GetPIRRewardPhase(int64_t nHeight)
{
@@ -1611,19 +1591,64 @@ int64_t nSubsidy = 20 * COIN;
{
return GetProofOfStakeRewardV1(pindexPrev, nCoinAge, nFees, nCoinValue);
}
+ else if((!TestNet() && pindexPrev->nHeight > PEPE_REBRAND_HEIGHT) ||
+ (TestNet() && pindexPrev->nHeight > PEPE_REBRAND_HEIGHT_TESTNET))
+ {
+ return GetProofOfStakeRewardV3(pindexPrev, nCoinAge, nFees, nCoinValue);
+ }
else
{
return GetProofOfStakeRewardV2(pindexPrev, nCoinAge, nFees, nCoinValue);
}
}
+ // PEPE rebrand 7% pos
+ int64_t GetProofOfStakeRewardV3(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees, int64_t nCoinValue)
+ {
+ int64_t nHeight = pindexPrev->nHeight;
+ int64_t nRewardCoinYear = 7 * CENT; // 7% per year
+
+ // Now calculate the reward
+ int64_t nSubsidy = nCoinAge * nRewardCoinYear * 33 / (365 * 33 + 8); //integer equivalent of nCoinAge * nRewardCoinYear / 365.2424242..
+
+ if (nHeight >= PEPE_JACKOLANTERN_FORK_HEIGHT)
+ nSubsidy = 1 * COIN; // Minimum 1 PEPE stake return for optimal KEKDAQ functionality.
+
+ if (nHeight >= PEPE_STAKEONLY_HEIGHT)
+ {
+ // adopt the proof-of-work reward schedule when swap over to stake only
+ // this will pick up the current pow reward of 3.25 at fork height with halving
+ nSubsidy = 15 * COIN;
+ nSubsidy >>= ((nHeight - PEPE_STAKEONLY_HEIGHT) / 525600); // block reward halves once a year
+
+ if(nSubsidy < 1 * COIN) // minimum 1 PEPE stake return
+ nSubsidy = 1 * COIN;
+ }
+
+ if(nHeight+1 == PEPE_REBRAND_PF_HEIGHT)
+ nSubsidy += (3 * PEPE_DEV_GRANT);
+ if(nHeight+1 == PEPE_KEKDAQ_MID_FIX_HEIGHT)
+ nSubsidy += (3 * PEPE_DEV_GRANT_MID);
+ if(nHeight+1 == PEPE_IPFSMN_FNL_HEIGHT)
+ nSubsidy += (3 * PEPE_DEV_GRANT_FINAL);
+ if(nHeight+1 == PEPE_STAKE_CONF_HEIGHT)
+ nSubsidy += (3 * PEPE_DEV_GRANT);
+ if(nHeight+1 == PEPE_KEKDAQ2_SWAP_HEIGHT)
+ nSubsidy += (3 * DEVFEE_OFF_SWAP_FINAL);
+ if(nHeight+1 == PEPE_STAKEONLY_HEIGHT)
+ nSubsidy += (4 * PEPE_SO_SWAP_GRANT);
+
+ return nSubsidy + nFees;
+ }
+
// PEPE stake fix
- // Simplified code to make it easier to understand, debug and maintain
+ // Not used anymore
int64_t GetProofOfStakeRewardV2(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees, int64_t nCoinValue)
{
int64_t nHeight = pindexPrev->nHeight;
int64_t nRewardCoinYear = 1 * CENT; // 1% per year
+
// PEPE Stake Reward table
// Amount Year 1 Year 2 Year 3+
// 0-10,000 3% 2% 1%
@@ -1707,7 +1732,8 @@ int64_t nSubsidy = 20 * COIN;
-static int64_t nTargetTimespan = 10 * 60; // 10 mins
+static int64_t nTargetTimespan = 10 * 60; // 10 mins stake difficulty retargeting
+
// ppcoin: find last block index up to pindex
const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake)
@@ -1719,9 +1745,25 @@ const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfSta
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
{
+ // if(pindexLast->nHeight >= PEPE_JACKOLANTERN_FORK_HEIGHT)
+ // nTargetTimespan = 2 * 60;
+
+ nTargetTimespan = 10 * 60; // 10 mins stake difficulty retargeting
+
+ if(pindexLast->nHeight >= PEPE_NTARGETTIMESPAN_UNSTICK_HEIGHT)
+ nTargetTimespan = 2 * 60;
+
+ // set fork-fix timespan back to 10 minutes for these blocks, to pass POW block sync sticking issues
+ if(pindexLast->nHeight >= 886415 && pindexLast->nHeight <=888057)
+ nTargetTimespan = 10 * 60;
+
+ // POS difficulty timespan set back to 10 minutes to lessen difficulty swings after block 1823000
+ if(pindexLast->nHeight >= PEPE_DIFFIMPROVE_HEIGHT )
+ nTargetTimespan = 10 * 60;
+
CBigNum bnTargetLimit = fProofOfStake ? GetProofOfStakeLimit(pindexLast->nHeight) : Params().ProofOfWorkLimit();
- if (pindexLast == NULL)
+ if (pindexLast == NULL || TestNet())
return bnTargetLimit.GetCompact(); // genesis block
const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
@@ -1770,9 +1812,41 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
return true;
}
+static int nAskedForBlocks = 0;
+
+bool IsSyncing()
+{
+ int nSyncSpan = GetArg("-syncspan", 90);
+ return pindexBest->GetBlockTime() < GetTime() - nSyncSpan * 60;
+}
+
+void DropNonRespondingSyncPeer()
+{
+ // detect if the currently connected sync node has not started sending blocks
+ // within timeout period, and if so disconnect it so we can try to sync
+ // from a new peer
+ BOOST_FOREACH(CNode* pnode, vNodes) {
+ if(pnode->fStartSync && !pnode->fDisconnect && IsSyncing())
+ {
+ int nSyncTimeout = GetArg("-synctimeout", 60);
+ int64_t tNow = GetTimeMillis();
+ if (pnode->tGetblocks) {
+ if (pnode->tGetblocks > pnode->tBlockInvs && tNow-pnode->tGetblocks > nSyncTimeout * 1000) {
+ LogPrintf("sync peer=%d: Block sync did not start within %d seconds. Disconnecting peer.\n", pnode->id, nSyncTimeout);
+ pnode->fDisconnect = true;
+ pnode->fStartSync = false;
+ nAskedForBlocks = 0;
+
+ break;
+ }
+ }
+ }
+ }
+}
+
bool IsInitialBlockDownload()
{
- LOCK(cs_main);
+ //LOCK(cs_main);
if (pindexBest == NULL || nBestHeight < Checkpoints::GetTotalBlocksEstimate())
return true;
static int64_t nLastUpdate;
@@ -1798,7 +1872,7 @@ void Misbehaving(NodeId pnode, int howmuch)
if(pn->GetId() == pnode)
{
pn->nMisbehavior += howmuch;
- int banscore = GetArg("-banscore", 100);
+ int banscore = GetArg("-banscore", 25);
if (pn->nMisbehavior >= banscore && pn->nMisbehavior - howmuch < banscore)
{
LogPrintf("Misbehaving: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n", pn->addrName, pn->nMisbehavior-howmuch, pn->nMisbehavior);
@@ -2187,6 +2261,34 @@ bool FindTransactionsByDestination(const CTxDestination &dest, std::vectornHeight;
+ CBlockIndex* pblockAddrIndex = FindBlockByHeight(nStartHeight);
+ CTxDB txdbAddr("rw");
+ while(pblockAddrIndex && pblockAddrIndex->nHeight <= nStopHeight)
+ {
+ CBlock pblockAddr;
+ if(pblockAddr.ReadFromDisk(pblockAddrIndex, true))
+ pblockAddr.RebuildAddressIndex(txdbAddr);
+ pblockAddrIndex = pblockAddrIndex->pnext;
+ }
+ LogPrintf("RebuildAddressIndexFromHeight(): Complete\n");
+}
+
+void RebuildAddressIndexForBlock(int64_t nBlockHeight)
+{
+ LogPrintf("RebuildAddressIndexForBlock(): nBlockHeight: %d\n", nBlockHeight);
+ CBlockIndex* pblockAddrIndex = FindBlockByHeight(nBlockHeight);
+ CTxDB txdbAddr("rw");
+ CBlock pblockAddr;
+ if(pblockAddr.ReadFromDisk(pblockAddrIndex, true))
+ pblockAddr.RebuildAddressIndex(txdbAddr);
+
+ LogPrintf("RebuildAddressIndexForBlock(): Complete\n");
+}
+
void CBlock::RebuildAddressIndex(CTxDB& txdb)
{
BOOST_FOREACH(CTransaction& tx, vtx)
@@ -2304,6 +2406,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size());
}
+
if (IsProofOfWork())
{
int64_t nReward = GetProofOfWorkReward(pindex->nHeight, nFees);
@@ -2312,6 +2415,11 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
return DoS(50, error("ConnectBlock() : coinbase reward exceeded (actual=%d vs calculated=%d)",
vtx[0].GetValueOut(),
nReward));
+
+ // If after rebrand hardfork, check that dev rewards are present
+ if(pindex->nHeight >= PEPE_REBRAND_PF_HEIGHT)
+ if(!CheckDevRewards(vtx[0], pindex->nHeight, nReward, nFees))
+ return error("ConnectBlock(): check proof-of-work failed for block, dev rewards mising.");
}
if (IsProofOfStake())
{
@@ -2325,8 +2433,103 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
if (nStakeReward > nCalculatedStakeReward)
return DoS(100, error("ConnectBlock() : coinstake pays too much(actual=%d vs calculated=%d)", nStakeReward, nCalculatedStakeReward));
+
+ // If after rebrand hardfork, check that dev rewards are present
+ if(pindex->nHeight >= PEPE_REBRAND_PF_HEIGHT)
+ if(!CheckDevRewards(vtx[1], pindex->nHeight, nStakeReward, nFees))
+ return error("ConnectBlock(): check proof-of-stake failed for block, dev rewards mising.");
+ }
+
+ // ----------- masternode payments -----------
+
+ bool MasternodePayments = false;
+ if ( Params().NetworkID() == CChainParams::TESTNET ){
+ if (pindex->nHeight > PEPE_KEKDAQ_MID_HEIGHT_TESTNET ){
+ MasternodePayments = true;
+ }
+ }else{
+ if (pindex->nHeight > PEPE_KEKDAQ_MID_FIX_HEIGHT){
+ MasternodePayments = true;
+ }
+ }
+
+ if(MasternodePayments == true)
+ {
+ CAmount masternodePaymentAmount = 0;
+ if(IsProofOfStake())
+ {
+ int64_t nDevReward = 0.02 * nStakeReward; // 2% per dev reward
+
+ if (pindex->nHeight > PEPE_REBRAND_PF_HEIGHT)
+ nDevReward = 0.04 * nStakeReward; // 4% per dev reward
+ if (pindex->nHeight == PEPE_REBRAND_PF_HEIGHT)
+ nDevReward = PEPE_DEV_GRANT;
+ if (pindex->nHeight == PEPE_KEKDAQ_MID_FIX_HEIGHT)
+ nDevReward = PEPE_DEV_GRANT_MID;
+ if (pindex->nHeight == PEPE_IPFSMN_FNL_HEIGHT)
+ nDevReward = PEPE_DEV_GRANT_FINAL;
+ if (pindex->nHeight == PEPE_STAKE_CONF_HEIGHT)
+ nDevReward = PEPE_DEV_GRANT;
+ if (pindex->nHeight == PEPE_KEKDAQ2_SWAP_HEIGHT)
+ nDevReward = DEVFEE_OFF_SWAP_FINAL;
+ if (pindex->nHeight == PEPE_STAKEONLY_HEIGHT)
+ nDevReward = PEPE_SO_SWAP_GRANT;
+
+ int64_t nTotalDevRewards = 3 * nDevReward;
+ if(pindex->nHeight >= PEPE_STAKEONLY_HEIGHT)
+ nTotalDevRewards = 4 * nDevReward;
+ int64_t nMnRewardBase = nStakeReward - nTotalDevRewards;
+ masternodePaymentAmount = GetMasternodePayment(pindex->nHeight, nMnRewardBase);
+ }
+ else if(IsProofOfWork())
+ {
+ masternodePaymentAmount = GetMasternodePayment(pindex->nHeight, vtx[0].GetValueOut());
+ }
+
+ bool fIsInitialDownload = IsInitialBlockDownload();
+
+ // If we don't already have its previous block, skip masternode payment step
+ if (!fIsInitialDownload && pindex != NULL)
+ {
+ bool foundPaymentAmount = false;
+ bool foundPayee = false;
+
+ CScript payee;
+ if(!masternodePayments.GetBlockPayee(pindex->nHeight, payee) || payee == CScript()){
+ foundPayee = true; //doesn't require a specific payee
+
+ if(fDebug) { LogPrintf("CheckBlock() : Using non-specific masternode payments %d\n", pindex->nHeight); }
+ }
+
+ int vtxIndex = 0;
+ if(IsProofOfStake())
+ vtxIndex = 1;
+
+ for (unsigned int i = 0; i < vtx[vtxIndex].vout.size(); i++) {
+ if(vtx[vtxIndex].vout[i].nValue == masternodePaymentAmount )
+ foundPaymentAmount = true;
+ if(vtx[vtxIndex].vout[i].scriptPubKey == payee )
+ foundPayee = true;
+ }
+
+ if(!foundPaymentAmount || !foundPayee) {
+ CTxDestination address1;
+ ExtractDestination(payee, address1);
+ CBitcoinAddress address2(address1);
+
+ if(fDebug) { LogPrintf("CheckBlock() : Couldn't find masternode payment(%d|%d) or payee(%d|%s) nHeight %d. \n", foundPaymentAmount, masternodePaymentAmount, foundPayee, address2.ToString().c_str(), pindex->nHeight); }
+ return DoS(1, error("CheckBlock() : Couldn't find masternode payment or payee"));
+ } else {
+ if(fDebug) { LogPrintf("CheckBlock() : Found masternode payment %d\n", pindexBest->nHeight+1); }
+ }
+ } else {
+ if(fDebug) { LogPrintf("CheckBlock() : Is initial download, skipping masternode payment check %d\n", pindex->nHeight); }
+ }
+ } else {
+ if(fDebug) { LogPrintf("CheckBlock() : Skipping masternode payment check - nHeight %d Hash %s\n", pindex->nHeight, GetHash().ToString().c_str()); }
}
+
// ppcoin: track money supply and mint amount info
pindex->nMint = nValueOut - nValueIn + nFees;
pindex->nMoneySupply = (pindex->pprev? pindex->pprev->nMoneySupply : 0) + nValueOut - nValueIn;
@@ -2343,8 +2546,19 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
return error("ConnectBlock() : UpdateTxIndex failed");
}
- if(GetBoolArg("-addrindex", false))
+ if(GetBoolArg("-addrindex", false) && !fJustCheck)
{
+ CBitcoinAddress addrDevOne;
+ addrDevOne.SetString(DecodeBase64(PEPE_REBRAND_DEV_1));
+ CScript payeeDevOne = GetScriptForDestination(addrDevOne.Get());
+ CBitcoinAddress addrDevTwo;
+ addrDevTwo.SetString(DecodeBase64(PEPE_REBRAND_DEV_2));
+ CScript payeeDevTwo = GetScriptForDestination(addrDevTwo.Get());
+ CBitcoinAddress addrDevThree;
+ addrDevThree.SetString(DecodeBase64(PEPE_REBRAND_DEV_3));
+ CScript payeeDevThree = GetScriptForDestination(addrDevThree.Get());
+
+ CTxDB txdbaddr("rw");
// Write Address Index
BOOST_FOREACH(CTransaction& tx, vtx)
{
@@ -2355,7 +2569,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
MapPrevTx mapInputs;
map mapQueuedChangesT;
bool fInvalid;
- if (!tx.FetchInputs(txdb, mapQueuedChangesT, true, false, mapInputs, fInvalid))
+ if (!tx.FetchInputs(txdbaddr, mapQueuedChangesT, true, false, mapInputs, fInvalid))
return false;
MapPrevTx::const_iterator mi;
@@ -2364,12 +2578,16 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
BOOST_FOREACH(const CTxOut &atxout, (*mi).second.second.vout)
{
std::vector addrIds;
- if(BuildAddrIndex(atxout.scriptPubKey, addrIds))
+
+ if(atxout.scriptPubKey != payeeDevOne && atxout.scriptPubKey != payeeDevTwo && atxout.scriptPubKey != payeeDevThree)
{
- BOOST_FOREACH(uint160 addrId, addrIds)
+ if(BuildAddrIndex(atxout.scriptPubKey, addrIds))
{
- if(!txdb.WriteAddrIndex(addrId, hashTx))
- LogPrintf("ConnectBlock(): txins WriteAddrIndex failed addrId: %s txhash: %s\n", addrId.ToString().c_str(), hashTx.ToString().c_str());
+ BOOST_FOREACH(uint160 addrId, addrIds)
+ {
+ if(!txdbaddr.WriteAddrIndex(addrId, hashTx))
+ LogPrintf("ConnectBlock(): txins WriteAddrIndex failed addrId: %s txhash: %s\n", addrId.ToString().c_str(), hashTx.ToString().c_str());
+ }
}
}
}
@@ -2379,13 +2597,16 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
// outputs
BOOST_FOREACH(const CTxOut &atxout, tx.vout)
{
- std::vector addrIds;
- if(BuildAddrIndex(atxout.scriptPubKey, addrIds))
+ if(atxout.scriptPubKey != payeeDevOne && atxout.scriptPubKey != payeeDevTwo && atxout.scriptPubKey != payeeDevThree)
{
- BOOST_FOREACH(uint160 addrId, addrIds)
+ std::vector addrIds;
+ if(BuildAddrIndex(atxout.scriptPubKey, addrIds))
{
- if(!txdb.WriteAddrIndex(addrId, hashTx))
- LogPrintf("ConnectBlock(): txouts WriteAddrIndex failed addrId: %s txhash: %s\n", addrId.ToString().c_str(), hashTx.ToString().c_str());
+ BOOST_FOREACH(uint160 addrId, addrIds)
+ {
+ if(!txdbaddr.WriteAddrIndex(addrId, hashTx))
+ LogPrintf("ConnectBlock(): txouts WriteAddrIndex failed addrId: %s txhash: %s\n", addrId.ToString().c_str(), hashTx.ToString().c_str());
+ }
}
}
}
@@ -2617,13 +2838,14 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
- uint256 nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust;
-
- LogPrintf("SetBestChain: new best=%s height=%d trust=%s blocktrust=%d date=%s\n",
+ // remove some unneeded log messages to reduce disk thrashing
+ /*
+ LogPrintf("SetBestChain: new best=%s height=%d trust=%s blocktrust=%d date=%s\n",
hashBestChain.ToString(), nBestHeight,
CBigNum(nBestChainTrust).ToString(),
nBestBlockTrust.Get64(),
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()));
+ */
// Check the version of the last 100 blocks to see if we need to upgrade:
if (!fIsInitialDownload)
@@ -2669,6 +2891,12 @@ bool CTransaction::GetCoinAge(CTxDB& txdb, const CBlockIndex* pindexPrev, uint64
int nStakeMinConfirmations = 360;
if((pindexPrev->nHeight+1) > PEPE_STAKE_WINTER_SWITCH_HEIGHT)
nStakeMinConfirmations = 60;
+ if((pindexPrev->nHeight+1) > PEPE_KEKDAQ_MID_FIX_HEIGHT)
+ nStakeMinConfirmations = 600;
+ if((pindexPrev->nHeight+1) > PEPE_STAKE_CONF_HEIGHT)
+ nStakeMinConfirmations = 360;
+ if((pindexPrev->nHeight+1) > PEPE_STAKE_CONF_TWEAK)
+ nStakeMinConfirmations = 600;
if (IsCoinBase())
return true;
@@ -2788,8 +3016,18 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c
return DoS(50, error("CheckBlock() : proof of work failed"));
// Check timestamp
- if (GetBlockTime() > FutureDrift(GetAdjustedTime()))
+ int nHeight = 0;
+ map::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
+ if (miPrev != mapBlockIndex.end())
+ {
+ nHeight = (*miPrev).second->nHeight + 1;
+ }
+
+ if (GetBlockTime() > FutureDrift(GetAdjustedTime(), nHeight))
+ {
+ LogPrintf("CheckBlock(): block timestamp too far in the future for block height: %d\n", nHeight);
return error("CheckBlock() : block timestamp too far in the future");
+ }
// First transaction must be coinbase, the rest must not be
if (vtx.empty() || !vtx[0].IsCoinBase())
@@ -2869,18 +3107,18 @@ bool CBlock::AcceptBlock()
// Get prev block index
map::iterator mi = mapBlockIndex.find(hashPrevBlock);
if (mi == mapBlockIndex.end())
- return DoS(10, error("AcceptBlock() : prev block not found"));
+ return DoS(1, error("AcceptBlock() : prev block not found"));
CBlockIndex* pindexPrev = (*mi).second;
int nHeight = pindexPrev->nHeight+1;
- if (IsProofOfWork() && nHeight > STOP_POW_BLOCK && nHeight < RESTART_POW_BLOCK )
+ if (IsProofOfWork() && ((nHeight > STOP_POW_BLOCK && nHeight < RESTART_POW_BLOCK) || nHeight >= PEPE_STAKEONLY_HEIGHT))
return DoS(100, error("AcceptBlock() : reject proof-of-work at height %d", nHeight));
if (IsProofOfStake() && nHeight < Params().POSStartBlock() )
return DoS(100, error("AcceptBlock() : reject proof-of-stake at height <= %d", nHeight));
// Check coinbase timestamp
- if (GetBlockTime() > FutureDrift((int64_t)vtx[0].nTime) && IsProofOfStake())
+ if (GetBlockTime() > FutureDrift((int64_t)vtx[0].nTime, nHeight) && IsProofOfStake())
return DoS(50, error("AcceptBlock() : coinbase timestamp is too early"));
// Check coinstake timestamp
@@ -2888,11 +3126,14 @@ bool CBlock::AcceptBlock()
return DoS(50, error("AcceptBlock() : coinstake timestamp violation nTimeBlock=%d nTimeTx=%u", GetBlockTime(), vtx[1].nTime));
// Check proof-of-work or proof-of-stake
- if (nBits != GetNextTargetRequired(pindexPrev, IsProofOfStake()))
- return DoS(100, error("AcceptBlock() : incorrect %s", IsProofOfWork() ? "proof-of-work" : "proof-of-stake"));
+ if (nBits != GetNextTargetRequired(pindexPrev, IsProofOfStake()) &&
+ hash != uint256("0x73f988a95293b060f1b4034c5e62a6e4439090e5d19bf078f3c90548671c5a82") && // exception for block 886907 past hard-fork stick
+ hash != uint256("0x9b345b188b1fb5cbd535666cf678b53577b58481765705592d1d3c5986ed6ac6")) // exception for block 886416 past hard-fork stick
+
+ return DoS(1, error("AcceptBlock() : incorrect %s", IsProofOfWork() ? "proof-of-work" : "proof-of-stake"));
// Check timestamp against prev
- if (GetBlockTime() <= pindexPrev->GetPastTimeLimit() || FutureDrift(GetBlockTime()) < pindexPrev->GetBlockTime())
+ if (GetBlockTime() <= pindexPrev->GetPastTimeLimit() || FutureDrift(GetBlockTime(), nHeight) < pindexPrev->GetBlockTime())
return error("AcceptBlock() : block's timestamp is too early");
// Check that all transactions are finalized
@@ -2902,7 +3143,7 @@ bool CBlock::AcceptBlock()
// Check that the block chain matches the known block chain up to a checkpoint
if (!Checkpoints::CheckHardened(nHeight, hash))
- return DoS(100, error("AcceptBlock() : rejected by hardened checkpoint lock-in at %d", nHeight));
+ return DoS(10, error("AcceptBlock() : rejected by hardened checkpoint lock-in at %d", nHeight));
uint256 hashProof;
// Verify hash target and signature of coinstake tx
@@ -2953,6 +3194,119 @@ bool CBlock::AcceptBlock()
return true;
}
+bool CBlock::CheckDevRewards(CTransaction tx, int64_t nHeight, int64_t nReward, int64_t nFees)
+{
+ // Check that the transaction contains
+ // the 3 dev reward outputs with the
+ // appropriate % of the total nReward for the block
+
+ int64_t nDevReward = 0.02 * nReward; // 2% per dev reward
+
+ if (nHeight > PEPE_REBRAND_PF_HEIGHT)
+ nDevReward = 0.04 * nReward; // 4% per dev reward
+ if (nHeight == PEPE_REBRAND_PF_HEIGHT)
+ nDevReward = PEPE_DEV_GRANT;
+ if (nHeight == PEPE_KEKDAQ_MID_FIX_HEIGHT)
+ nDevReward = PEPE_DEV_GRANT_MID;
+ if (nHeight == PEPE_IPFSMN_FNL_HEIGHT)
+ nDevReward = PEPE_DEV_GRANT_FINAL;
+ if (nHeight == PEPE_STAKE_CONF_HEIGHT)
+ nDevReward = PEPE_DEV_GRANT;
+ if (nHeight == PEPE_KEKDAQ2_SWAP_HEIGHT)
+ nDevReward = DEVFEE_OFF_SWAP_FINAL;
+ if (nHeight == PEPE_STAKEONLY_HEIGHT)
+ nDevReward = PEPE_SO_SWAP_GRANT;
+
+ int64_t nTotalDevRewards = 3 * nDevReward;
+ if(nHeight >= PEPE_STAKEONLY_HEIGHT)
+ nTotalDevRewards = 4 * nDevReward;
+
+ int64_t nFoundDevRewards = 0;
+
+ CBitcoinAddress addrDevOne;
+ addrDevOne.SetString(DecodeBase64(PEPE_REBRAND_DEV_1));
+ CScript payeeDevOne = GetScriptForDestination(addrDevOne.Get());
+ CBitcoinAddress addrDevTwo;
+ addrDevTwo.SetString(DecodeBase64(PEPE_REBRAND_DEV_2));
+ CScript payeeDevTwo = GetScriptForDestination(addrDevTwo.Get());
+ CBitcoinAddress addrDevThree;
+ addrDevThree.SetString(DecodeBase64(PEPE_REBRAND_DEV_3));
+ CScript payeeDevThree = GetScriptForDestination(addrDevThree.Get());
+ CBitcoinAddress addrDevFour;
+ addrDevFour.SetString(DecodeBase64(PEPE_DEV_4));
+ CScript payeeDevFour = GetScriptForDestination(addrDevFour.Get());
+
+ bool bFoundDevOne = false;
+ bool bFoundDevTwo = false;
+ bool bFoundDevThree = false;
+ bool bFoundDevFour = false;
+ for(unsigned int i=0; i addresses;
+ int nRequired;
+
+ if (ExtractDestinations(tx.vout[i].scriptPubKey, type, addresses, nRequired))
+ {
+ BOOST_FOREACH(const CTxDestination& addr, addresses)
+ {
+ CBitcoinAddress addrFound = CBitcoinAddress(addr);
+
+ if(addrFound == addrDevOne)
+ {
+ if(tx.vout[i].nValue >= nDevReward)
+ {
+ bFoundDevOne = true;
+ nFoundDevRewards += nDevReward;
+ }
+ }
+
+ if(addrFound == addrDevTwo)
+ {
+ if(tx.vout[i].nValue >= nDevReward)
+ {
+ bFoundDevTwo = true;
+ nFoundDevRewards += nDevReward;
+ }
+ }
+
+ if(addrFound == addrDevThree)
+ {
+ if(tx.vout[i].nValue >= nDevReward)
+ {
+ bFoundDevThree = true;
+ nFoundDevRewards += nDevReward;
+ }
+ }
+
+ if(addrFound == addrDevFour)
+ {
+ if(tx.vout[i].nValue >= nDevReward)
+ {
+ bFoundDevFour = true;
+ nFoundDevRewards += nDevReward;
+ }
+ }
+ }
+ }
+ }
+
+ if(nHeight >= PEPE_STAKEONLY_HEIGHT)
+ {
+ if((bFoundDevOne && bFoundDevTwo && bFoundDevThree && bFoundDevFour) && (nFoundDevRewards >= nTotalDevRewards))
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ if((bFoundDevOne && bFoundDevTwo && bFoundDevThree) && (nFoundDevRewards >= nTotalDevRewards))
+ return true;
+ else
+ return false;
+ }
+}
+
uint256 CBlockIndex::GetBlockTrust() const
{
CBigNum bnTarget;
@@ -3027,6 +3381,14 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
// If we don't already have its previous block, shunt it off to holding area until we get it
if (!mapBlockIndex.count(pblock->hashPrevBlock))
{
+ if(IsSyncing())
+ {
+ pfrom->fDisconnect = true;
+ pfrom->fStartSync = false;
+ nAskedForBlocks = 0;
+ return error("ProcessBlock(): ORPHAN detected, but we syncing. Disconnecting from peer.\n");
+ }
+
LogPrintf("ProcessBlock: ORPHAN BLOCK %lu, prev=%s\n", (unsigned long)mapOrphanBlocks.size(), pblock->hashPrevBlock.ToString());
// Accept orphans as long as there is a node to request its parents from
@@ -3093,67 +3455,50 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
mapOrphanBlocksByPrev.erase(hashPrev);
}
- if(!IsInitialBlockDownload()){
-
- CScript payee;
- CTxIn vin;
-
- // If we're in LiteMode disable darksend features without disabling masternodes
- if (!fLiteMode && !fImporting && !fReindex && pindexBest->nHeight > Checkpoints::GetTotalBlocksEstimate()){
-
- if(masternodePayments.GetBlockPayee(pindexBest->nHeight, payee, vin)){
- //UPDATE MASTERNODE LAST PAID TIME
- CMasternode* pmn = mnodeman.Find(vin);
- if(pmn != NULL) {
- pmn->nLastPaid = GetAdjustedTime();
- }
-
- LogPrintf("ProcessBlock() : Update Masternode Last Paid Time - %d\n", pindexBest->nHeight);
- }
-
- darkSendPool.CheckTimeout();
- darkSendPool.NewBlock();
- masternodePayments.ProcessBlock(GetHeight()+10);
-
- } else if (fLiteMode && !fImporting && !fReindex && pindexBest->nHeight > Checkpoints::GetTotalBlocksEstimate())
+ // Cache any found pepe messages
+ if(GetBoolArg("-messagewall", false))
+ {
+ CTxDB txdb("rw");
+ BOOST_FOREACH(const CTransaction& tx, pblock->vtx)
{
- if(masternodePayments.GetBlockPayee(pindexBest->nHeight, payee, vin)){
- //UPDATE MASTERNODE LAST PAID TIME
- CMasternode* pmn = mnodeman.Find(vin);
- if(pmn != NULL) {
- pmn->nLastPaid = GetAdjustedTime();
+ BOOST_FOREACH(const CTxOut vout, tx.vout)
+ {
+ if(vout.scriptPubKey.size() > 0 && vout.scriptPubKey[0] == OP_RETURN)
+ {
+ std::vector vch(vout.scriptPubKey.begin()+2,vout.scriptPubKey.end());
+ std::string astring(vch.begin(), vch.end());
+ CPepeMessage pmsg;
+ pmsg.nTime = tx.nTime;
+ pmsg.msg = astring;
+ txdb.WritePepeMessage(pmsg.GetHash(), pmsg);
+ if(mapPepeMessages.count(pmsg.GetHash()) == 0)
+ mapPepeMessages.insert(make_pair(pmsg.GetHash(), pmsg));
}
-
- LogPrintf("ProcessBlock() : Update Masternode Last Paid Time - %d\n", pindexBest->nHeight);
}
-
- masternodePayments.ProcessBlock(GetHeight()+10);
}
+ }
- }
+ int nShift = (pblock->nBits >> 24) & 0xff;
+ double dDiff = (double)0x0000ffff / (double)(pblock->nBits & 0x00ffffff);
- // Cache any found pepe messages
- CTxDB txdb("rw");
- BOOST_FOREACH(const CTransaction& tx, pblock->vtx)
+ while (nShift < 29)
{
- BOOST_FOREACH(const CTxOut vout, tx.vout)
- {
- if(vout.scriptPubKey.size() > 0 && vout.scriptPubKey[0] == OP_RETURN)
- {
- std::vector vch(vout.scriptPubKey.begin()+2,vout.scriptPubKey.end());
- std::string astring(vch.begin(), vch.end());
- CPepeMessage pmsg;
- pmsg.nTime = tx.nTime;
- pmsg.msg = astring;
- txdb.WritePepeMessage(pmsg.GetHash(), pmsg);
- if(mapPepeMessages.count(pmsg.GetHash()) == 0)
- mapPepeMessages.insert(make_pair(pmsg.GetHash(), pmsg));
- }
- }
+ dDiff *= 256.0;
+ nShift++;
}
-
+ while (nShift > 29)
+ {
+ dDiff /= 256.0;
+ nShift--;
+ }
+ LogPrintf("ProcessBlock: ACCEPTED Height: %d Difficulty: %d\n", mapBlockIndex[hash]->nHeight, dDiff);
- LogPrintf("ProcessBlock: ACCEPTED\n");
+#ifdef ENABLE_WALLET
+ {
+ LOCK(pwalletMain->cs_wallet);
+ pwalletMain->fCachedBalanceNeedsUpdating = true; // update cached balance in case coins came out of stake with the accepted block
+ }
+#endif
return true;
}
@@ -3631,151 +3976,154 @@ bool static AlreadyHave(CTxDB& txdb, const CInv& inv)
void static ProcessGetData(CNode* pfrom)
{
- std::deque::iterator it = pfrom->vRecvGetData.begin();
+ {
+ std::deque::iterator it = pfrom->vRecvGetData.begin();
- vector vNotFound;
+ vector vNotFound;
- LOCK(cs_main);
-
- while (it != pfrom->vRecvGetData.end()) {
- // Don't bother if send buffer is too full to respond anyway
- if (pfrom->nSendSize >= SendBufferSize())
- break;
+ LOCK(cs_main);
- const CInv &inv = *it;
- {
- boost::this_thread::interruption_point();
- it++;
+ while (it != pfrom->vRecvGetData.end()) {
+ // Don't bother if send buffer is too full to respond anyway
+ if (pfrom->nSendSize >= SendBufferSize())
+ break;
- if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
+ const CInv &inv = *it;
{
- // Send block from disk
- map::iterator mi = mapBlockIndex.find(inv.hash);
- if (mi != mapBlockIndex.end())
- {
- CBlock block;
- block.ReadFromDisk((*mi).second);
- pfrom->PushMessage("block", block);
+ boost::this_thread::interruption_point();
+ it++;
- // Trigger them to send a getblocks request for the next batch of inventory
- if (inv.hash == pfrom->hashContinue)
+ if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
+ {
+ // Send block from disk
+ map::iterator mi = mapBlockIndex.find(inv.hash);
+ if (mi != mapBlockIndex.end())
{
- // Bypass PushInventory, this must send even if redundant,
- // and we want it right after the last block so they don't
- // wait for other stuff first.
- vector vInv;
- vInv.push_back(CInv(MSG_BLOCK, hashBestChain));
- pfrom->PushMessage("inv", vInv);
- pfrom->hashContinue = 0;
+ CBlock block;
+ block.ReadFromDisk((*mi).second);
+ pfrom->PushMessage("block", block);
+
+ // Trigger them to send a getblocks request for the next batch of inventory
+ if (inv.hash == pfrom->hashContinue)
+ {
+ // Bypass PushInventory, this must send even if redundant,
+ // and we want it right after the last block so they don't
+ // wait for other stuff first.
+ vector vInv;
+ vInv.push_back(CInv(MSG_BLOCK, hashBestChain));
+ pfrom->PushMessage("inv", vInv);
+ pfrom->hashContinue = 0;
+ }
}
}
- }
- else if (inv.IsKnownType())
- {
- if(fDebug) LogPrintf("ProcessGetData -- Starting \n");
- // Send stream from relay memory
- bool pushed = false;
- /*{
- LOCK(cs_mapRelay);
- map::iterator mi = mapRelay.find(inv);
- if (mi != mapRelay.end()) {
- pfrom->PushMessage(inv.GetCommand(), (*mi).second);
- if(fDebug) LogPrintf("ProcessGetData -- pushed = true Rest will fail\n");
- pushed = true;
+ else if (inv.IsKnownType())
+ {
+ if(fDebug) LogPrintf("ProcessGetData -- Starting \n");
+ // Send stream from relay memory
+ bool pushed = false;
+ {
+ LOCK(cs_mapRelay);
+ map::iterator mi = mapRelay.find(inv);
+ if (mi != mapRelay.end()) {
+ pfrom->PushMessage(inv.GetCommand(), (*mi).second);
+ if(fDebug) LogPrintf("ProcessGetData -- pushed = true Rest will fail\n");
+ pushed = true;
+ }
}
- }*/
- if (!pushed && inv.type == MSG_TX) {
-
- CTransaction tx;
- if (mempool.lookup(inv.hash, tx)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << tx;
- pfrom->PushMessage("tx", ss);
- pushed = true;
+
+ if (!pushed && inv.type == MSG_TX) {
+
+ CTransaction tx;
+ if (mempool.lookup(inv.hash, tx)) {
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << tx;
+ pfrom->PushMessage("tx", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_TXLOCK_VOTE) {
- if(mapTxLockVote.count(inv.hash)){
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mapTxLockVote[inv.hash];
- pfrom->PushMessage("txlvote", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_TXLOCK_VOTE) {
+ if(mapTxLockVote.count(inv.hash)){
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mapTxLockVote[inv.hash];
+ pfrom->PushMessage("txlvote", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_TXLOCK_REQUEST) {
- if(mapTxLockReq.count(inv.hash)){
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mapTxLockReq[inv.hash];
- pfrom->PushMessage("txlreq", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_TXLOCK_REQUEST) {
+ if(mapTxLockReq.count(inv.hash)){
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mapTxLockReq[inv.hash];
+ pfrom->PushMessage("txlreq", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_SPORK) {
- if(mapSporks.count(inv.hash)){
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mapSporks[inv.hash];
- pfrom->PushMessage("spork", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_SPORK) {
+ if(mapSporks.count(inv.hash)){
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mapSporks[inv.hash];
+ pfrom->PushMessage("spork", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_MASTERNODE_WINNER) {
- if(mapSeenMasternodeVotes.count(inv.hash)){
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mapSeenMasternodeVotes[inv.hash];
- pfrom->PushMessage("mnw", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_MASTERNODE_WINNER) {
+ if(mapSeenMasternodeVotes.count(inv.hash)){
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mapSeenMasternodeVotes[inv.hash];
+ pfrom->PushMessage("mnw", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_DSTX) {
- if(mapDarksendBroadcastTxes.count(inv.hash)){
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss <<
- mapDarksendBroadcastTxes[inv.hash].tx <<
- mapDarksendBroadcastTxes[inv.hash].vin <<
- mapDarksendBroadcastTxes[inv.hash].vchSig <<
- mapDarksendBroadcastTxes[inv.hash].sigTime;
-
- pfrom->PushMessage("dstx", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_DSTX) {
+ if(mapDarksendBroadcastTxes.count(inv.hash)){
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss <<
+ mapDarksendBroadcastTxes[inv.hash].tx <<
+ mapDarksendBroadcastTxes[inv.hash].vin <<
+ mapDarksendBroadcastTxes[inv.hash].vchSig <<
+ mapDarksendBroadcastTxes[inv.hash].sigTime;
+
+ pfrom->PushMessage("dstx", ss);
+ pushed = true;
+ }
+ }
+ if (!pushed) {
+ vNotFound.push_back(inv);
}
}
- if (!pushed) {
- vNotFound.push_back(inv);
- }
- }
- // Track requests for our stuff.
- g_signals.Inventory(inv.hash);
+ // Track requests for our stuff.
+ g_signals.Inventory(inv.hash);
- if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
- break;
+ if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
+ break;
+ }
}
- }
-
- pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it);
- if (!vNotFound.empty()) {
- // Let the peer know that we didn't find what it asked for, so it doesn't
- // have to wait around forever. Currently only SPV clients actually care
- // about this message: it's needed when they are recursively walking the
- // dependencies of relevant unconfirmed transactions. SPV clients want to
- // do that because they want to know about (and store and rebroadcast and
- // risk analyze) the dependencies of transactions relevant to them, without
- // having to download the entire memory pool.
- pfrom->PushMessage("notfound", vNotFound);
+ pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it);
+
+ if (!vNotFound.empty()) {
+ // Let the peer know that we didn't find what it asked for, so it doesn't
+ // have to wait around forever. Currently only SPV clients actually care
+ // about this message: it's needed when they are recursively walking the
+ // dependencies of relevant unconfirmed transactions. SPV clients want to
+ // do that because they want to know about (and store and rebroadcast and
+ // risk analyze) the dependencies of transactions relevant to them, without
+ // having to download the entire memory pool.
+ pfrom->PushMessage("notfound", vNotFound);
+ }
}
}
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
{
RandAddSeedPerfmon();
- LogPrint("net", "received: %s (%u bytes)\n", strCommand, vRecv.size());
+ LogPrint("net", "received: %s (%u bytes) peer=%s\n", strCommand, vRecv.size(), pfrom->addr.ToString());
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
{
LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
@@ -3801,6 +4149,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// disconnect from peers older than this proto version
LogPrintf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString(), pfrom->nVersion);
pfrom->fDisconnect = true;
+ pfrom->Misbehaving(100); // just ban them
return false;
}
@@ -3812,6 +4161,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vRecv >> pfrom->strSubVer;
if (!vRecv.empty())
vRecv >> pfrom->nStartingHeight;
+
+ pfrom->fRelayTxes = true;
pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer);
@@ -3869,6 +4220,22 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
+ //---
+ // Ask the first connected node for block updates
+
+ if (!pfrom->fClient && !pfrom->fOneShot && !pfrom->fDisconnect &&
+ (pfrom->nStartingHeight > nBestHeight) &&
+ (pfrom->nVersion < NOBLKS_VERSION_START ||
+ pfrom->nVersion > NOBLKS_VERSION_END) &&
+ (nAskedForBlocks < 1 || vNodes.size() <= 1))
+ {
+ pfrom->fStartSync = true;
+ nAskedForBlocks++;
+ PushGetBlocks(pfrom, pindexBest, uint256(0));
+ pfrom->tGetblocks = GetTimeMillis();
+ }
+ //---
+
// Relay alerts
{
LOCK(cs_mapAlerts);
@@ -3974,7 +4341,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->Misbehaving(20);
return error("message inv size() = %u", vInv.size());
}
-
+
// find last block in inv vector
unsigned int nLastBlock = (unsigned int)(-1);
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
@@ -3983,8 +4350,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
break;
}
}
-
+
LOCK(cs_main);
+ int nBlocksGet = 0;
+
CTxDB txdb("r");
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
@@ -3999,7 +4368,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (!fAlreadyHave) {
if (!fImporting)
- pfrom->AskFor(inv);
+ if (inv.type == MSG_BLOCK) {
+ if (pfrom->tGetblocks > pfrom->tBlockInvs || !IsSyncing()) {
+ pfrom->AskFor(inv);
+ nBlocksGet++;
+ }
+ } else
+ pfrom->AskFor(inv);
} else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(inv.hash));
} else if (nInv == nLastBlock) {
@@ -4011,9 +4386,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LogPrintf("force request: %s\n", inv.ToString());
}
+
// Track requests for our stuff
g_signals.Inventory(inv.hash);
}
+
+ if (nBlocksGet)
+ pfrom->tBlockInvs = GetTimeMillis();
}
@@ -4052,7 +4431,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Send the rest of the chain
if (pindex)
pindex = pindex->pnext;
- int nLimit = 5000;
+ int nLimit = 500;
LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), nLimit);
for (; pindex; pindex = pindex->pnext)
{
@@ -4075,12 +4454,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else if (strCommand == "getheaders")
{
- CBlockLocator locator;
+ /*CBlockLocator locator;
uint256 hashStop;
vRecv >> locator >> hashStop;
-
LOCK(cs_main);
-
CBlockIndex* pindex = NULL;
if (locator.IsNull())
{
@@ -4097,9 +4474,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (pindex)
pindex = pindex->pnext;
}
-
vector vHeaders;
- int nLimit = 2000;
+ int nLimit = 500;
LogPrint("net", "getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString());
for (; pindex; pindex = pindex->pnext)
{
@@ -4107,64 +4483,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
break;
}
- pfrom->PushMessage("headers", vHeaders);
+ pfrom->PushMessage("headers", vHeaders);*/
}
- else if (strCommand == "tx"|| strCommand == "dstx")
+ else if (strCommand == "tx")
{
vector vWorkQueue;
vector vEraseQueue;
CTransaction tx;
-
- //masternode signed transaction
- bool ignoreFees = false;
- CTxIn vin;
- vector vchSig;
- int64_t sigTime;
-
- if(strCommand == "tx") {
- vRecv >> tx;
- } else if (strCommand == "dstx") {
- //these allow masternodes to publish a limited amount of free transactions
- vRecv >> tx >> vin >> vchSig >> sigTime;
-
- CMasternode* pmn = mnodeman.Find(vin);
- if(pmn != NULL)
- {
- if(!pmn->allowFreeTx){
- //multiple peers can send us a valid masternode transaction
- if(fDebug) LogPrintf("dstx: Masternode sending too many transactions %s\n", tx.GetHash().ToString().c_str());
- return true;
- }
-
- std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast(sigTime);
-
- std::string errorMessage = "";
- if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchSig, strMessage, errorMessage)){
- LogPrintf("dstx: Got bad masternode address signature %s \n", vin.ToString().c_str());
- //pfrom->Misbehaving(20);
- return false;
- }
-
- LogPrintf("dstx: Got Masternode transaction %s\n", tx.GetHash().ToString().c_str());
-
- ignoreFees = true;
- pmn->allowFreeTx = false;
-
- if(!mapDarksendBroadcastTxes.count(tx.GetHash())){
- CDarksendBroadcastTx dstx;
- dstx.tx = tx;
- dstx.vin = vin;
- dstx.vchSig = vchSig;
- dstx.sigTime = sigTime;
-
- mapDarksendBroadcastTxes.insert(make_pair(tx.GetHash(), dstx));
- }
- }
- }
+ vRecv >> tx;
+ CTxDB txdb("r");
CInv inv(MSG_TX, tx.GetHash());
+ // Check for recently rejected (and do other quick existence checks)
+ if (AlreadyHave(txdb, inv))
+ return true;
+
pfrom->AddInventoryKnown(inv);
LOCK(cs_main);
@@ -4173,7 +4508,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
mapAlreadyAskedFor.erase(inv);
- if (AcceptToMemoryPool(mempool, tx, true, &fMissingInputs, false, ignoreFees))
+ if (AcceptToMemoryPool(mempool, tx, true, &fMissingInputs))
{
RelayTransaction(tx, inv.hash);
vWorkQueue.push_back(inv.hash);
@@ -4221,29 +4556,36 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (nEvicted > 0)
LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted);
}
- if(strCommand == "dstx"){
- CInv inv(MSG_DSTX, tx.GetHash());
- RelayInventory(inv);
- }
if (tx.nDoS) pfrom->Misbehaving(tx.nDoS);
}
-
else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing
{
+ int size = vRecv.size();
CBlock block;
vRecv >> block;
uint256 hashBlock = block.GetHash();
- LogPrint("net", "received block %s\n", hashBlock.ToString());
+ //LogPrint("net", "received block %s\n", hashBlock.ToString());
CInv inv(MSG_BLOCK, hashBlock);
+
pfrom->AddInventoryKnown(inv);
+ int timetodownload = GetTimeMillis() - pfrom->tBlockRecved/1000;
+ if (timetodownload > 1000)
+ LogPrint("net", "received block %s (%u bytes, %us, %uB/s) peer=%d\n",
+ inv.hash.ToString(), size, timetodownload / 1000, size * 1000 / timetodownload, pfrom->id);
+ else
+ LogPrint("net", "received block %s (%u bytes) peer=%d\n", inv.hash.ToString(), size, pfrom->id);
+
LOCK(cs_main);
if (ProcessBlock(pfrom, &block))
+ {
mapAlreadyAskedFor.erase(inv);
+ pfrom->tBlockRecved = GetTimeMillis();
+ }
if (block.nDoS) pfrom->Misbehaving(block.nDoS);
if (fSecMsgEnabled)
SecureMsgScanBlock(block);
@@ -4395,15 +4737,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else
- {
- if (fSecMsgEnabled)
- SecureMsgReceiveData(pfrom, strCommand, vRecv);
-
- darkSendPool.ProcessMessageDarksend(pfrom, strCommand, vRecv);
- mnodeman.ProcessMessage(pfrom, strCommand, vRecv);
- ProcessMessageMasternodePayments(pfrom, strCommand, vRecv);
- ProcessMessageInstantX(pfrom, strCommand, vRecv);
- ProcessSpork(pfrom, strCommand, vRecv);
+ {
+ if(IsSyncing() && !pfrom->fStartSync)
+ {
+ pfrom->fDisconnect = true;
+ }
+ else if(!fLiteMode && !IsSyncing())
+ {
+ if (fSecMsgEnabled)
+ SecureMsgReceiveData(pfrom, strCommand, vRecv);
+
+ ProcessMessageDarksend(pfrom, strCommand, vRecv);
+ ProcessMessageMasternode(pfrom, strCommand, vRecv);
+ ProcessMessageInstantX(pfrom, strCommand, vRecv);
+ ProcessSpork(pfrom, strCommand, vRecv);
+ }
// Ignore unknown commands for extensibility
}
@@ -4432,7 +4780,7 @@ bool ProcessMessages(CNode* pfrom)
// (4) checksum
// (x) data
//
- bool fOk = true;
+ bool fOk = true;
if (!pfrom->vRecvGetData.empty())
ProcessGetData(pfrom);
@@ -4448,12 +4796,28 @@ bool ProcessMessages(CNode* pfrom)
// get next message
CNetMessage& msg = *it;
+ CMessageHeader& hdr = msg.hdr;
+ unsigned int nMessageSize = hdr.nMessageSize;
+ string strCommand = hdr.GetCommand();
//if (fDebug)
// LogPrintf("ProcessMessages(message %u msgsz, %zu bytes, complete:%s)\n",
// msg.hdr.nMessageSize, msg.vRecv.size(),
// msg.complete() ? "Y" : "N");
+ if (msg.nDataPos != msg.nLastDataPos) {
+ if (strCommand == "block") {
+ if (msg.nLastDataPos == 0) {
+ pfrom->tBlockRecvStart = GetTimeMillis();
+ if (pfrom->tBlockRecved)
+ LogPrint("net", "%ums later, ", pfrom->tBlockRecvStart - pfrom->tBlockRecved);
+ LogPrint("net", "incoming block (%u bytes) peer=%d\n", nMessageSize, pfrom->id);
+ }
+ pfrom->tBlockRecving = GetTimeMillis();
+ }
+ msg.nLastDataPos = msg.nDataPos;
+ }
+
// end, if an incomplete message is found
if (!msg.complete())
break;
@@ -4469,16 +4833,16 @@ bool ProcessMessages(CNode* pfrom)
}
// Read header
- CMessageHeader& hdr = msg.hdr;
+ //CMessageHeader& hdr = msg.hdr;
if (!hdr.IsValid())
{
- LogPrintf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand());
+ LogPrintf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", strCommand);
continue;
}
- string strCommand = hdr.GetCommand();
+ //string strCommand = hdr.GetCommand();
// Message size
- unsigned int nMessageSize = hdr.nMessageSize;
+ //unsigned int nMessageSize = hdr.nMessageSize;
// Checksum
CDataStream& vRecv = msg.vRecv;
@@ -4542,7 +4906,8 @@ bool ProcessMessages(CNode* pfrom)
bool SendMessages(CNode* pto, bool fSendTrickle)
{
TRY_LOCK(cs_main, lockMain);
- if (lockMain) {
+ if (lockMain)
+ {
// Don't send anything until we get their version message
if (pto->nVersion == 0)
return true;
@@ -4576,15 +4941,15 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
}
}
- TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
- if (!lockMain)
- return true;
+ //TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
+ //if (!lockMain)
+ // return true;
// Start block sync
- if (pto->fStartSync && !fImporting && !fReindex) {
+ /* if (pto->fStartSync && !fImporting && !fReindex) {
pto->fStartSync = false;
PushGetBlocks(pto, pindexBest, uint256(0));
- }
+ }*/
// Resend wallet transactions that haven't gotten in a block yet
// Except during reindex, importing and IBD, when old wallet
@@ -4659,8 +5024,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (pto->setInventoryKnown.count(inv))
continue;
+ // --- Don't trickle tx's, network is too small and results in transaction delays ---
// trickle out tx inv to protect privacy
- if (inv.type == MSG_TX && !fSendTrickle)
+ /* if (inv.type == MSG_TX && !fSendTrickle)
{
// 1/4 of tx invs blast to all immediately
static uint256 hashSalt;
@@ -4675,7 +5041,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
vInvWait.push_back(inv);
continue;
}
- }
+ }*/
// returns true if wasn't already contained in the set
if (pto->setInventoryKnown.insert(inv).second)
@@ -4693,6 +5059,34 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (!vInv.empty())
pto->PushMessage("inv", vInv);
+ // Detect stalled peers.
+ int nSyncTimeout = GetArg("-synctimeout", 60);
+ int64_t tNow = GetTimeMillis();
+ if (pto->tGetblocks && IsSyncing()) {
+ if (pto->tBlockRecving > pto->tBlockRecved) {
+ if (tNow-pto->tBlockRecving > nSyncTimeout * 1000) {
+ LogPrintf("sync peer=%d: Block download stalled for over %d seconds.\n", pto->id, nSyncTimeout);
+ pto->fDisconnect = true;
+ pto->fStartSync = false;
+ nAskedForBlocks = 0;
+ }
+ } else if (pto->tGetblocks > pto->tBlockInvs && tNow-pto->tGetblocks > nSyncTimeout * 1000) {
+ LogPrintf("sync peer=%d: No invs of new blocks received within %d seconds.\n", pto->id, nSyncTimeout);
+ pto->fDisconnect = true;
+ pto->fStartSync = false;
+ nAskedForBlocks = 0;
+ } else if (IsSyncing() && pto->tBlockRecved && tNow-pto->tBlockRecved > nSyncTimeout * 1000) {
+ LogPrintf("sync peer=%d: No block reception for over %d seconds.\n", pto->id, nSyncTimeout);
+ pto->fDisconnect = true;
+ pto->fStartSync = false;
+ nAskedForBlocks = 0;
+ } else if (pto->tGetdataBlock > pto->tBlockRecving && tNow-pto->tGetdataBlock > nSyncTimeout * 1000) {
+ LogPrintf("sync peer=%d: No block download started for over %d seconds.\n", pto->id, nSyncTimeout);
+ pto->fDisconnect = true;
+ pto->fStartSync = false;
+ nAskedForBlocks = 0;
+ }
+ }
//
// Message: getdata
@@ -4708,6 +5102,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (fDebug)
LogPrint("net", "sending getdata: %s\n", inv.ToString());
vGetData.push_back(inv);
+ if (!pto->tGetdataBlock)
+ pto->tGetdataBlock = GetTimeMillis();
if (vGetData.size() >= 1000)
{
pto->PushMessage("getdata", vGetData);
@@ -4731,7 +5127,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
int64_t GetMasternodePayment(int nHeight, int64_t blockValue)
{
- int64_t ret = blockValue * 0.1; // 10% Masternodes pay + staking
+ int64_t ret = blockValue * 0.375; // 37.5% Masternodes pay + staking
return ret;
}
@@ -4775,4 +5171,4 @@ void RescanPepeMessages()
pindex = pindex->pprev;
}
-}
\ No newline at end of file
+}
diff --git a/src/main.h b/src/main.h
index 3287aa9c..fb151d58 100644
--- a/src/main.h
+++ b/src/main.h
@@ -9,7 +9,7 @@
// Copyright (c) 2014 NetCoin Developers
// Copyright (c) 2015 Transfercoin Developer
// Copyright (c) 2015-2016 PepeCoin Developers
-// Copyright (c) 2016 The Memetic Developers
+// Copyright (c) 2016-2019 Memetic / PepeCoin Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -26,13 +26,15 @@
#include "hashblock.h"
#include
+#include
class CValidationState;
-#define START_MASTERNODE_PAYMENTS_TESTNET 1460635200 // "20160414 0600"
-#define START_MASTERNODE_PAYMENTS 1460635200
+#define START_MASTERNODE_PAYMENTS_TESTNET 1496987073 // June 9, 2017 2:20:04 AM GMT
+#define START_MASTERNODE_PAYMENTS 1499579073 // Sunday, July 9, 2017 5:44:33 AM GMT
-static const int64_t DARKSEND_COLLATERAL = (0.01*COIN);
+static const int64_t DARKSEND_COLLATERAL = (5000*COIN);
+static const int64_t DARKSEND_FEE = (0.0001*COIN);
static const int64_t DARKSEND_POOL_MAX = (9999.99*COIN);
static const int64_t TARGET_SPACING = 60;
@@ -55,10 +57,43 @@ class CReserveKey;
class CWallet;
class CPepeMessage;
+static const int64_t PEPE_JACKOLANTERN_FORK_HEIGHT = 888000;
+static const int64_t PEPE_NTARGETTIMESPAN_UNSTICK_HEIGHT = 885655;
+
+static const int64_t MASTERTOAD_LOWERTRAFFIC_FORK = 1030000;
+static const int64_t MASTERTOAD_RELOWERTRAFFIC_FORK = 1177777;
+
static const int64_t PEPE_STAKE_WINTER_SWITCH_HEIGHT = 312000;
static const int64_t PEPE_STAKE_V2_SWITCH_HEIGHT = 32000;
static const int64_t PEPE_STAKE_V2_SWITCH_HEIGHT_TESTNET = 10;
+
+// Rebrand Back To PEPE Hardfork
+// At this height, POS moves to 7%, POW moves to 7 for 1 month of blocks then 5 and then halving every year
+// and dev reward is implemented (3 dev addresses at 3% each)
+static const int64_t PEPE_REBRAND_HEIGHT = 580000;
+static const int64_t PEPE_REBRAND_HEIGHT_TESTNET = 100;
+static const std::string PEPE_REBRAND_DEV_1 = "UE5hSlMzbVBNY1FjNmdZc0xKMUg4endHSDZIMVh4VG40OA==";
+static const std::string PEPE_REBRAND_DEV_2 = "UFJyeFZQWGNUQjN2TGNjZlBVRlRNVzJ6NTd3Skd3ZEd1ag==";
+static const std::string PEPE_REBRAND_DEV_3 = "UExSY1ZHVmNZdkE2NmJNWGVQd2hSUTJleFdNdlBvVm83MQ==";
+static const std::string PEPE_DEV_4 = "UFUxWm05N3R6NmRyQ0FuQmZNYjVFd2s3R0NSa3FYV2dZeA==";
+static const int64_t PEPE_REBRAND_PF_HEIGHT = 600000;
+static const int64_t PEPE_KEKDAQ_MID_HEIGHT = 733333;
+static const int64_t PEPE_KEKDAQ_MID_FIX_HEIGHT = 738500;
+static const int64_t PEPE_IPFSMN_FNL_HEIGHT = 833333;
+static const int64_t PEPE_KEKDAQ2_SWAP_HEIGHT = 1161137;
+static const int64_t PEPE_REBRAND_PF_HEIGHT_TESTNET = 200;
+static const int64_t PEPE_KEKDAQ_MID_HEIGHT_TESTNET = 10000;
+static const int64_t PEPE_DEV_GRANT = 333333 * COIN;
+static const int64_t PEPE_DEV_GRANT_MID = 333333 * COIN;
+static const int64_t PEPE_DEV_GRANT_FINAL = 111111 * COIN;
+static const int64_t DEVFEE_OFF_SWAP_FINAL = 777777 * COIN;
+static const int64_t PEPE_SO_SWAP_GRANT = 888888 * COIN;
+static const int64_t PEPE_STAKE_CONF_HEIGHT = 1021111;
+static const int64_t PEPE_STAKE_CONF_TWEAK = 1177777;
+static const int64_t PEPE_STAKEONLY_HEIGHT = 1700000;
+static const int64_t PEPE_DIFFIMPROVE_HEIGHT = 1830000;
+
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 20000000;
/** The maximum size for mined blocks */
@@ -76,18 +111,18 @@ static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
/** The maximum number of orphan transactions kept in memory */
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
/** Default for -maxorphanblocks, maximum number of orphan blocks kept in memory */
-static const unsigned int DEFAULT_MAX_ORPHAN_BLOCKS = 10000;
+static const unsigned int DEFAULT_MAX_ORPHAN_BLOCKS = 750;
/** The maximum number of entries in an 'inv' protocol message */
static const unsigned int MAX_INV_SZ = 50000;
/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
static const int64_t MIN_TX_FEE = 0.0001*COIN;
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying) */
static const int64_t MIN_RELAY_TX_FEE = MIN_TX_FEE;
-/** No amount larger than this (in satoshi) is valid */
-static const int64_t MAX_MONEY = 16628690 * COIN; // 16,628,690 POW Coins
-
-// Pepe Stake Rate PSR / PIR : Staking rewards are variable depending on the number of coins held.
+/** No amount larger than this (in satoshi) is valid */
+// static const int64_t MAX_MONEY = 16628690 * COIN; // 16,628,690 POW Coins
+static const int64_t MAX_MONEY = 28600000 * COIN; // more realistic target project of 28.6m total coins by 2024 minus KDAQ burns
+// no longer used, kept for old block confirmation
static const int PIR_LEVELS = 4; // number of entries in PIR_THRESHOLDS
static const int64_t PIR_PHASEBLOCKS = 365 * 24 * 60; // one year for each phase
static const int PIR_PHASES = 3; // pepe - three POS reward phases
@@ -113,12 +148,12 @@ inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MO
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
static const int64_t DRIFT = 600;
-inline int64_t FutureDrift(int64_t nTime) { return nTime + DRIFT; }
+inline int64_t FutureDrift(int64_t nTime, int nHeight) { return nHeight >= PEPE_DIFFIMPROVE_HEIGHT ? nTime + 60 : nTime + DRIFT; }
/** "reject" message codes **/
static const unsigned char REJECT_INVALID = 0x10;
-inline int64_t GetMNCollateral(int nHeight) { return nHeight>=420000 ? 10000 : 10000; } // No change for now.
+inline int64_t GetMNCollateral(int nHeight) { return 15000; } // 15k PEPE / MEME required for MN
extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
@@ -203,10 +238,13 @@ int64_t GetPIRRewardCoinYear(int64_t nCoinValue, int64_t nHeight);
int64_t GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees, int64_t nCoinValue);
int64_t GetProofOfStakeRewardV1(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees, int64_t nCoinValue);
int64_t GetProofOfStakeRewardV2(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees, int64_t nCoinValue);
+int64_t GetProofOfStakeRewardV3(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees, int64_t nCoinValue);
+bool IsSyncing();
+void DropNonRespondingSyncPeer();
bool IsInitialBlockDownload();
bool IsConfirmedInNPrevBlocks(const CTxIndex& txindex, const CBlockIndex* pindexFrom, int nMaxDepth, int& nActualDepth);
std::string GetWarnings(std::string strFor);
-bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock);
+bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fCheckMempool = true);
uint256 WantedByOrphan(const COrphanBlock* pblockOrphan);
const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake);
void ThreadStakeMiner(CWallet *pwallet);
@@ -232,6 +270,9 @@ void Misbehaving(NodeId nodeid, int howmuch);
int64_t GetMasternodePayment(int nHeight, int64_t blockValue);
+void RebuildAddressIndexFromHeight(int64_t nStartHeight);
+void RebuildAddressIndexForBlock(int64_t nBlockHeight);
+
/** Message cached from op_return **/
class CPepeMessage
{
@@ -256,6 +297,11 @@ class CPepeMessage
return DateTimeStrFormat(nTime) + ": " + msg;
}
+bool operator < (const CPepeMessage& a) const
+ {
+ return (nTime < a.nTime);
+ }
+
};
/** Position on disk for a particular transaction. */
@@ -623,8 +669,7 @@ class CMerkleTx : public CTransaction
bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
int GetBlocksToMaturity() const;
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true, bool ignoreFees=false);
- int GetTransactionLockSignatures() const;
- bool IsTransactionLockTimedOut() const;
+
};
@@ -962,6 +1007,7 @@ class CBlock
bool SignBlock(CWallet& keystore, int64_t nFees);
bool CheckBlockSignature() const;
void RebuildAddressIndex(CTxDB& txdb);
+ bool CheckDevRewards(CTransaction tx, int64_t nHeight, int64_t nReward, int64_t nFees);
private:
bool SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew);
@@ -1113,7 +1159,10 @@ class CBlockIndex
int64_t GetPastTimeLimit() const
{
- return GetBlockTime() - DRIFT;
+ if(nHeight >= PEPE_DIFFIMPROVE_HEIGHT)
+ return GetBlockTime();
+ else
+ return GetBlockTime() - DRIFT;
}
enum { nMedianTimeSpan=11 };
diff --git a/src/makefile.bsd b/src/makefile.bsd
index ca7995ed..98f83592 100644
--- a/src/makefile.bsd
+++ b/src/makefile.bsd
@@ -142,7 +142,7 @@ ifeq (${USE_WALLET}, 1)
obj/walletdb.o
endif
-all: memeticd
+all: pepecoind
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include)
@@ -176,11 +176,11 @@ obj/%.o: %.cpp
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
-memeticd: $(OBJS:obj/%=obj/%)
+pepecoind: $(OBJS:obj/%=obj/%)
$(LINK) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS)
clean:
- -rm -f memeticd
+ -rm -f pepecoind
-rm -f obj/*.o
-rm -f obj/*.P
-rm -f obj/build.h
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
index 87b63943..9d6891db 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -52,7 +52,7 @@ ifneq (${USE_UPNP}, -)
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
endif
-LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l memetic32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
+LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l pepecoin32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
HEADERS = $(wildcard *.h)
@@ -105,7 +105,7 @@ ifeq (${USE_WALLET}, 1)
obj/walletdb.o
endif
-all: memeticd.exe
+all: pepecoind.exe
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
DEFS += -I"$(CURDIR)/leveldb/include"
@@ -123,9 +123,9 @@ DEFS += -DHAVE_BUILD_INFO
obj/%.o: %.cpp $(HEADERS)
$(CXX) -c $(CFLAGS) -o $@ $<
-memeticd.exe: $(OBJS:obj/%=obj/%)
+pepecoind.exe: $(OBJS:obj/%=obj/%)
$(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lshlwapi
- $(STRIP) memeticd.exe
+ $(STRIP) pepecoind.exe
obj/scrypt-x86.o: scrypt-x86.S
$(CXX) -c $(CFLAGS) -MMD -o $@ $<
@@ -135,7 +135,7 @@ obj/scrypt-x86_64.o: scrypt-x86_64.S
clean:
-rm -f obj/*.o
- -rm -f memeticd.exe
+ -rm -f pepecoind.exe
-rm -f obj/build.h
cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) clean && cd ..
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 1fd05e3e..ffde523b 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -38,7 +38,8 @@ LIBS= \
DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
DEBUGFLAGS=-g
-CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter -fpermissive $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
+CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -
+Wno-unused-parameter -fpermissive $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat -Wl,--large-address-aware -static
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
@@ -51,7 +52,9 @@ ifneq (${USE_UPNP}, -)
DEFS += -DMINIUPNP_STATICLIB -DUSE_UPNP=$(USE_UPNP)
endif
-LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
+LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l
+shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock
+-l shlwapi
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
HEADERS = $(wildcard *.h)
@@ -97,12 +100,9 @@ OBJS= \
obj/stealth.o \
obj/activemasternode.o \
obj/darksend.o \
- obj/darksend-relay.o \
obj/instantx.o \
obj/masternodeconfig.o \
- obj/masternodeman.o \
obj/masternode.o \
- obj/masternode-payments.o \
obj/rpcdarksend.o \
obj/spork.o \
obj/crypto/hmac_sha256.o \
@@ -137,14 +137,15 @@ ifeq (${USE_WALLET}, 1)
obj/walletdb.o
endif
-all: memeticd.exe
+all: pepecoind.exe
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include)
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
OBJS += obj/txdb-leveldb.o
leveldb/libleveldb.a:
- @echo "Building LevelDB ..."; cd leveldb; chmod 755 *;make libleveldb.a libmemenv.a; cd ..;
+ @echo "Building LevelDB ..."; cd leveldb; chmod 755 *;make libleveldb.a
+libmemenv.a; cd ..;
obj/txdb-leveldb.o: leveldb/libleveldb.a
obj/%.o: %.cpp $(HEADERS)
@@ -153,7 +154,7 @@ obj/%.o: %.cpp $(HEADERS)
obj/%.o: %.c $(HEADERS)
$(CXX) -c $(CFLAGS) -fpermissive -o $@ $<
-memeticd.exe: $(OBJS:obj/%=obj/%)
+pepecoind.exe: $(OBJS:obj/%=obj/%)
g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
obj/scrypt-x86.o: scrypt-x86.S
diff --git a/src/makefile.osx b/src/makefile.osx
index 3cf706d2..c6522e6b 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -3,7 +3,7 @@
# Distributed under the MIT/X11 software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-# Mac OS X makefile for memetic
+# Mac OS X makefile for pepecoin
# Originally by Laszlo Hanyecz (solar@heliacal.net)
CXX=clang++
@@ -30,7 +30,7 @@ USE_WALLET:=1
LIBS= -dead_strip
ifdef STATIC
-# Build STATIC if you are redistributing the memeticd binary
+# Build STATIC if you are redistributing the pepecoind binary
LIBS += \
$(DEPSDIR)/lib/db48/libdb_cxx-4.8.a \
$(DEPSDIR)/lib/libboost_system.a \
@@ -160,13 +160,13 @@ else
endif
endif
-all: memeticd
+all: pepecoind
# build secp256k1
DEFS += $(addprefix -I,$(CURDIR)/secp256k1/include)
secp256k1/src/libsecp256k1_la-secp256k1.o:
@echo "Building Secp256k1 ..."; cd secp256k1; chmod 755 *; ./autogen.sh; ./configure --enable-module-recovery; make; cd ..;
-memeticd: secp256k1/src/libsecp256k1_la-secp256k1.o
+pepecoind: secp256k1/src/libsecp256k1_la-secp256k1.o
# build leveldb
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
@@ -205,11 +205,11 @@ obj/%.o: %.c
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
-memeticd: $(OBJS:obj/%=obj/%)
+pepecoind: $(OBJS:obj/%=obj/%)
$(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
clean:
- -rm -f memeticd
+ -rm -f pepecoind
-rm -f obj/*.o
-rm -f obj/*.P
-rm -f obj/build.h
diff --git a/src/makefile.unix b/src/makefile.unix
index 61ebfc1d..0b6a8789 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -143,12 +143,9 @@ OBJS= \
obj/stealth.o \
obj/activemasternode.o \
obj/darksend.o \
- obj/darksend-relay.o \
obj/instantx.o \
obj/masternodeconfig.o \
- obj/masternodeman.o \
obj/masternode.o \
- obj/masternode-payments.o \
obj/rpcdarksend.o \
obj/spork.o \
obj/crypto/hmac_sha256.o \
@@ -183,13 +180,13 @@ ifeq (${USE_WALLET}, 1)
obj/walletdb.o
endif
-all: memeticd
+all: pepecoind
# build secp256k1
DEFS += $(addprefix -I,$(CURDIR)/secp256k1/include)
secp256k1/src/libsecp256k1_la-secp256k1.o:
@echo "Building Secp256k1 ..."; cd secp256k1; chmod 755 *; ./autogen.sh; ./configure --enable-module-recovery; make; cd ..;
-memeticd: secp256k1/src/libsecp256k1_la-secp256k1.o
+pepecoind: secp256k1/src/libsecp256k1_la-secp256k1.o
# build leveldb
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
@@ -231,11 +228,11 @@ obj/%.o: %.c
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
-memeticd: $(OBJS:obj/%=obj/%)
+pepecoind: $(OBJS:obj/%=obj/%)
$(LINK) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS)
clean:
- -rm -f memeticd
+ -rm -f pepecoind
-rm -f obj/*.o
-rm -f obj/*.P
-rm -f obj/build.h
diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp
deleted file mode 100644
index 62f2da84..00000000
--- a/src/masternode-payments.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright (c) 2014-2015 The Dash developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include "masternode-payments.h"
-#include "masternodeman.h"
-#include "darksend.h"
-#include "util.h"
-#include "sync.h"
-#include "spork.h"
-#include "addrman.h"
-#include
-
-CCriticalSection cs_masternodepayments;
-
-/** Object for who's going to get paid on which blocks */
-CMasternodePayments masternodePayments;
-// keep track of Masternode votes I've seen
-map mapSeenMasternodeVotes;
-
-int CMasternodePayments::GetMinMasternodePaymentsProto() {
- return IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)
- ? MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2
- : MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1;
-}
-
-void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
-{
- if(!darkSendPool.IsBlockchainSynced()) return;
-
- if (strCommand == "mnget") { //Masternode Payments Request Sync
-
- if(pfrom->HasFulfilledRequest("mnget")) {
- LogPrintf("mnget - peer already asked me for the list\n");
- Misbehaving(pfrom->GetId(), 20);
- return;
- }
-
- pfrom->FulfilledRequest("mnget");
- masternodePayments.Sync(pfrom);
- LogPrintf("mnget - Sent Masternode winners to %s\n", pfrom->addr.ToString().c_str());
- }
- else if (strCommand == "mnw") { //Masternode Payments Declare Winner
-
- LOCK(cs_masternodepayments);
-
- //this is required in litemode
- CMasternodePaymentWinner winner;
- vRecv >> winner;
-
- if(pindexBest == NULL) return;
-
- CTxDestination address1;
- ExtractDestination(winner.payee, address1);
- CBitcoinAddress address2(address1);
-
- uint256 hash = winner.GetHash();
- if(mapSeenMasternodeVotes.count(hash)) {
- if(fDebug) LogPrintf("mnw - seen vote %s Addr %s Height %d bestHeight %d\n", hash.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight);
- return;
- }
-
- if(winner.nBlockHeight < pindexBest->nHeight - 10 || winner.nBlockHeight > pindexBest->nHeight+20){
- LogPrintf("mnw - winner out of range %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight);
- return;
- }
-
- if(winner.vin.nSequence != std::numeric_limits::max()){
- LogPrintf("mnw - invalid nSequence\n");
- Misbehaving(pfrom->GetId(), 100);
- return;
- }
-
- LogPrintf("mnw - winning vote - Vin %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight);
-
- if(!masternodePayments.CheckSignature(winner)){
- LogPrintf("mnw - invalid signature\n");
- Misbehaving(pfrom->GetId(), 100);
- return;
- }
-
- mapSeenMasternodeVotes.insert(make_pair(hash, winner));
-
- if(masternodePayments.AddWinningMasternode(winner)){
- masternodePayments.Relay(winner);
- }
- }
-}
-
-
-bool CMasternodePayments::CheckSignature(CMasternodePaymentWinner& winner)
-{
- //note: need to investigate why this is failing
- std::string strMessage = winner.vin.ToString().c_str() + boost::lexical_cast(winner.nBlockHeight) + winner.payee.ToString();
- std::string strPubKey = strMainPubKey ;
- CPubKey pubkey(ParseHex(strPubKey));
-
- std::string errorMessage = "";
- if(!darkSendSigner.VerifyMessage(pubkey, winner.vchSig, strMessage, errorMessage)){
- return false;
- }
-
- return true;
-}
-
-bool CMasternodePayments::Sign(CMasternodePaymentWinner& winner)
-{
- std::string strMessage = winner.vin.ToString().c_str() + boost::lexical_cast(winner.nBlockHeight) + winner.payee.ToString();
-
- CKey key2;
- CPubKey pubkey2;
- std::string errorMessage = "";
-
- if(!darkSendSigner.SetKey(strMasterPrivKey, errorMessage, key2, pubkey2))
- {
- LogPrintf("CMasternodePayments::Sign - ERROR: Invalid Masternodeprivkey: '%s'\n", errorMessage.c_str());
- return false;
- }
-
- if(!darkSendSigner.SignMessage(strMessage, errorMessage, winner.vchSig, key2)) {
- LogPrintf("CMasternodePayments::Sign - Sign message failed");
- return false;
- }
-
- if(!darkSendSigner.VerifyMessage(pubkey2, winner.vchSig, strMessage, errorMessage)) {
- LogPrintf("CMasternodePayments::Sign - Verify message failed");
- return false;
- }
-
- return true;
-}
-
-uint64_t CMasternodePayments::CalculateScore(uint256 blockHash, CTxIn& vin)
-{
- uint256 n1 = blockHash;
- uint256 n2 = Hash(BEGIN(n1), END(n1));
- uint256 n3 = Hash(BEGIN(vin.prevout.hash), END(vin.prevout.hash));
- uint256 n4 = n3 > n2 ? (n3 - n2) : (n2 - n3);
-
- //printf(" -- CMasternodePayments CalculateScore() n2 = %d \n", n2.Get64());
- //printf(" -- CMasternodePayments CalculateScore() n3 = %d \n", n3.Get64());
- //printf(" -- CMasternodePayments CalculateScore() n4 = %d \n", n4.Get64());
-
- return n4.Get64();
-}
-
-bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee, CTxIn& vin)
-{
- BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
- if(winner.nBlockHeight == nBlockHeight) {
- payee = winner.payee;
- vin = winner.vin;
- return true;
- }
- }
-
- return false;
-}
-
-bool CMasternodePayments::GetWinningMasternode(int nBlockHeight, CTxIn& vinOut)
-{
- BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
- if(winner.nBlockHeight == nBlockHeight) {
- vinOut = winner.vin;
- return true;
- }
- }
-
- return false;
-}
-
-bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerIn)
-{
- uint256 blockHash = 0;
- if(!GetBlockHash(blockHash, winnerIn.nBlockHeight-576)) {
- return false;
- }
-
- winnerIn.score = CalculateScore(blockHash, winnerIn.vin);
-
- bool foundBlock = false;
- BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
- if(winner.nBlockHeight == winnerIn.nBlockHeight) {
- foundBlock = true;
- if(winner.score < winnerIn.score){
- winner.score = winnerIn.score;
- winner.vin = winnerIn.vin;
- winner.payee = winnerIn.payee;
- winner.vchSig = winnerIn.vchSig;
-
- mapSeenMasternodeVotes.insert(make_pair(winnerIn.GetHash(), winnerIn));
-
- return true;
- }
- }
- }
-
- // if it's not in the vector
- if(!foundBlock){
- vWinning.push_back(winnerIn);
- mapSeenMasternodeVotes.insert(make_pair(winnerIn.GetHash(), winnerIn));
-
- return true;
- }
-
- return false;
-}
-
-void CMasternodePayments::CleanPaymentList()
-{
- LOCK(cs_masternodepayments);
-
- if(pindexBest == NULL) return;
-
- int nLimit = std::max(((int)mnodeman.size())*((int)1.25), 1000);
-
- vector::iterator it;
- for(it=vWinning.begin();itnHeight - (*it).nBlockHeight > nLimit){
- if(fDebug) LogPrintf("CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d\n", (*it).nBlockHeight);
- vWinning.erase(it);
- break;
- }
- }
-}
-
-bool CMasternodePayments::ProcessBlock(int nBlockHeight)
-{
- LOCK(cs_masternodepayments);
-
- if(nBlockHeight <= nLastBlockHeight) return false;
- if(!enabled) return false;
- CMasternodePaymentWinner newWinner;
- int nMinimumAge = mnodeman.CountEnabled();
- CScript payeeSource;
-
- uint256 hash;
- if(!GetBlockHash(hash, nBlockHeight-10)) return false;
- unsigned int nHash;
- memcpy(&nHash, &hash, 2);
-
- LogPrintf(" ProcessBlock Start nHeight %d - vin %s. \n", nBlockHeight, activeMasternode.vin.ToString().c_str());
-
- std::vector vecLastPayments;
- BOOST_REVERSE_FOREACH(CMasternodePaymentWinner& winner, vWinning)
- {
- //if we already have the same vin - we have one full payment cycle, break
- if(vecLastPayments.size() > (unsigned int)nMinimumAge) break;
- vecLastPayments.push_back(winner.vin);
- }
-
- // pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
- CMasternode *pmn = mnodeman.FindOldestNotInVec(vecLastPayments, nMinimumAge);
- if(pmn != NULL)
- {
- LogPrintf(" Found by FindOldestNotInVec \n");
-
- newWinner.score = 0;
- newWinner.nBlockHeight = nBlockHeight;
- newWinner.vin = pmn->vin;
-
- if(pmn->donationPercentage > 0 && (nHash % 100) <= (unsigned int)pmn->donationPercentage) {
- newWinner.payee = pmn->donationAddress;
- } else {
- newWinner.payee = GetScriptForDestination(pmn->pubkey.GetID());
- }
-
- payeeSource = GetScriptForDestination(pmn->pubkey.GetID());
- }
-
- //if we can't find new MN to get paid, pick first active MN counting back from the end of vecLastPayments list
- if(newWinner.nBlockHeight == 0 && nMinimumAge > 0)
- {
- LogPrintf(" Find by reverse \n");
-
- BOOST_REVERSE_FOREACH(CTxIn& vinLP, vecLastPayments)
- {
- CMasternode* pmn = mnodeman.Find(vinLP);
- if(pmn != NULL)
- {
- pmn->Check();
- if(!pmn->IsEnabled()) continue;
-
- newWinner.score = 0;
- newWinner.nBlockHeight = nBlockHeight;
- newWinner.vin = pmn->vin;
-
- if(pmn->donationPercentage > 0 && (nHash % 100) <= (unsigned int)pmn->donationPercentage) {
- newWinner.payee = pmn->donationAddress;
- } else {
- newWinner.payee = GetScriptForDestination(pmn->pubkey.GetID());
- }
-
- payeeSource = GetScriptForDestination(pmn->pubkey.GetID());
-
- break; // we found active MN
- }
- }
- }
-
- if(newWinner.nBlockHeight == 0) return false;
-
- CTxDestination address1;
- ExtractDestination(newWinner.payee, address1);
- CBitcoinAddress address2(address1);
-
- CTxDestination address3;
- ExtractDestination(payeeSource, address3);
- CBitcoinAddress address4(address3);
-
- LogPrintf("Winner payee %s nHeight %d vin source %s. \n", address2.ToString().c_str(), newWinner.nBlockHeight, address4.ToString().c_str());
-
- if(Sign(newWinner))
- {
- if(AddWinningMasternode(newWinner))
- {
- Relay(newWinner);
- nLastBlockHeight = nBlockHeight;
- return true;
- }
- }
-
- return false;
-}
-
-
-void CMasternodePayments::Relay(CMasternodePaymentWinner& winner)
-{
- CInv inv(MSG_MASTERNODE_WINNER, winner.GetHash());
-
- vector vInv;
- vInv.push_back(inv);
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes){
- pnode->PushMessage("inv", vInv);
- }
-}
-
-void CMasternodePayments::Sync(CNode* node)
-{
- LOCK(cs_masternodepayments);
-
- BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning)
- if(winner.nBlockHeight >= pindexBest->nHeight-10 && winner.nBlockHeight <= pindexBest->nHeight + 20)
- node->PushMessage("mnw", winner);
-}
-
-
-bool CMasternodePayments::SetPrivKey(std::string strPrivKey)
-{
- CMasternodePaymentWinner winner;
-
- // Test signing successful, proceed
- strMasterPrivKey = strPrivKey;
-
- Sign(winner);
-
- if(CheckSignature(winner)){
- LogPrintf("CMasternodePayments::SetPrivKey - Successfully initialized as Masternode payments master\n");
- enabled = true;
- return true;
- } else {
- return false;
- }
-}
diff --git a/src/masternode-payments.h b/src/masternode-payments.h
deleted file mode 100644
index 487fafd6..00000000
--- a/src/masternode-payments.h
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-// Copyright (c) 2014-2015 The Dash developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef MASTERNODE_PAYMENTS_H
-#define MASTERNODE_PAYMENTS_H
-
-#include "sync.h"
-#include "net.h"
-#include "key.h"
-#include "util.h"
-#include "base58.h"
-#include "main.h"
-#include "masternode.h"
-#include "timedata.h"
-
-using namespace std;
-
-class CMasternodePayments;
-class CMasternodePaymentWinner;
-
-extern CMasternodePayments masternodePayments;
-extern map mapSeenMasternodeVotes;
-
-void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
-
-
-// for storing the winning payments
-class CMasternodePaymentWinner
-{
-public:
- int nBlockHeight;
- CTxIn vin;
- CScript payee;
- std::vector vchSig;
- uint64_t score;
-
- CMasternodePaymentWinner() {
- nBlockHeight = 0;
- score = 0;
- vin = CTxIn();
- payee = CScript();
- }
-
- uint256 GetHash(){
- uint256 n2 = Hash(BEGIN(nBlockHeight), END(nBlockHeight));
- uint256 n3 = vin.prevout.hash > n2 ? (vin.prevout.hash - n2) : (n2 - vin.prevout.hash);
-
- return n3;
- }
-
- IMPLEMENT_SERIALIZE(
- READWRITE(nBlockHeight);
- READWRITE(payee);
- READWRITE(vin);
- READWRITE(score);
- READWRITE(vchSig);
- )
-};
-
-//
-// Masternode Payments Class
-// Keeps track of who should get paid for which blocks
-//
-
-class CMasternodePayments
-{
-private:
- std::vector vWinning;
- int nSyncedFromPeer;
- std::string strMasterPrivKey;
- std::string strMainPubKey;
- bool enabled;
- int nLastBlockHeight;
-
-public:
-
- CMasternodePayments() {
- strMainPubKey = "";
- enabled = false;
- }
-
- bool SetPrivKey(std::string strPrivKey);
- bool CheckSignature(CMasternodePaymentWinner& winner);
- bool Sign(CMasternodePaymentWinner& winner);
-
- // Deterministically calculate a given "score" for a masternode depending on how close it's hash is
- // to the blockHeight. The further away they are the better, the furthest will win the election
- // and get paid this block
- //
-
- uint64_t CalculateScore(uint256 blockHash, CTxIn& vin);
- bool GetWinningMasternode(int nBlockHeight, CTxIn& vinOut);
- bool AddWinningMasternode(CMasternodePaymentWinner& winner);
- bool ProcessBlock(int nBlockHeight);
- void Relay(CMasternodePaymentWinner& winner);
- void Sync(CNode* node);
- void CleanPaymentList();
- int LastPayment(CMasternode& mn);
- int GetMinMasternodePaymentsProto();
-
- bool GetBlockPayee(int nBlockHeight, CScript& payee, CTxIn& vin);
-};
-
-
-#endif
\ No newline at end of file
diff --git a/src/masternode-pos.cpp b/src/masternode-pos.cpp
deleted file mode 100644
index 013d1ac1..00000000
--- a/src/masternode-pos.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-
-
-
-#include "bignum.h"
-#include "sync.h"
-#include "net.h"
-#include "key.h"
-#include "util.h"
-#include "script.h"
-#include "base58.h"
-#include "protocol.h"
-#include "activemasternode.h"
-#include "masternodeman.h"
-#include "spork.h"
-#include
-#include "masternodeman.h"
-
-using namespace std;
-using namespace boost;
-
-std::map mapMasternodeScanningErrors;
-CMasternodeScanning mnscan;
-
-/*
- Masternode - Proof of Service
-
- -- What it checks
-
- 1.) Making sure Masternodes have their ports open
- 2.) Are responding to requests made by the network
-
- -- How it works
-
- When a block comes in, DoMasternodePOS is executed if the client is a
- masternode. Using the deterministic ranking algorithm up to 1% of the masternode
- network is checked each block.
-
- A port is opened from Masternode A to Masternode B, if successful then nothing happens.
- If there is an error, a CMasternodeScanningError object is propagated with an error code.
- Errors are applied to the Masternodes and a score is incremented within the masternode object,
- after a threshold is met, the masternode goes into an error state. Each cycle the score is
- decreased, so if the masternode comes back online it will return to the list.
-
- Masternodes in a error state do not receive payment.
-
- -- Future expansion
-
- We want to be able to prove the nodes have many qualities such as a specific CPU speed, bandwidth,
- and dedicated storage. E.g. We could require a full node be a computer running 2GHz with 10GB of space.
-
-*/
-
-void ProcessMessageMasternodePOS(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
-{
- if(!IsSporkActive(SPORK_7_MASTERNODE_SCANNING)) return;
- if(IsInitialBlockDownload()) return;
-
- if (strCommand == "mnse") //Masternode Scanning Error
- {
-
- CDataStream vMsg(vRecv);
- CMasternodeScanningError mnse;
- vRecv >> mnse;
-
- CInv inv(MSG_MASTERNODE_SCANNING_ERROR, mnse.GetHash());
- pfrom->AddInventoryKnown(inv);
-
- if(mapMasternodeScanningErrors.count(mnse.GetHash())){
- return;
- }
- mapMasternodeScanningErrors.insert(make_pair(mnse.GetHash(), mnse));
-
- if(!mnse.IsValid())
- {
- LogPrintf("MasternodePOS::mnse - Invalid object\n");
- return;
- }
-
- CMasternode* pmnA = mnodeman.Find(mnse.vinMasternodeA);
- if(pmnA == NULL) return;
- if(pmnA->protocolVersion < MIN_MASTERNODE_POS_PROTO_VERSION) return;
-
- int nBlockHeight = pindexBest->nHeight;
- if(nBlockHeight - mnse.nBlockHeight > 10){
- LogPrintf("MasternodePOS::mnse - Too old\n");
- return;
- }
-
- // Lowest masternodes in rank check the highest each block
- int a = mnodeman.GetMasternodeRank(mnse.vinMasternodeA, mnse.nBlockHeight, MIN_MASTERNODE_POS_PROTO_VERSION);
- if(a == -1 || a > GetCountScanningPerBlock())
- {
- if(a != -1) LogPrintf("MasternodePOS::mnse - MasternodeA ranking is too high\n");
- return;
- }
-
- int b = mnodeman.GetMasternodeRank(mnse.vinMasternodeB, mnse.nBlockHeight, MIN_MASTERNODE_POS_PROTO_VERSION, false);
- if(b == -1 || b < mnodeman.CountMasternodesAboveProtocol(MIN_MASTERNODE_POS_PROTO_VERSION)-GetCountScanningPerBlock())
- {
- if(b != -1) LogPrintf("MasternodePOS::mnse - MasternodeB ranking is too low\n");
- return;
- }
-
- if(!mnse.SignatureValid()){
- LogPrintf("MasternodePOS::mnse - Bad masternode message\n");
- return;
- }
-
- CMasternode* pmnB = mnodeman.Find(mnse.vinMasternodeB);
- if(pmnB == NULL) return;
-
- if(fDebug) LogPrintf("ProcessMessageMasternodePOS::mnse - nHeight %d MasternodeA %s MasternodeB %s\n", mnse.nBlockHeight, pmnA->addr.ToString().c_str(), pmnB->addr.ToString().c_str());
-
- pmnB->ApplyScanningError(mnse);
- mnse.Relay();
- }
-}
-
-// Returns how many masternodes are allowed to scan each block
-int GetCountScanningPerBlock()
-{
- return std::max(1, mnodeman.CountMasternodesAboveProtocol(MIN_MASTERNODE_POS_PROTO_VERSION)/100);
-}
-
-
-void CMasternodeScanning::CleanMasternodeScanningErrors()
-{
- if(pindexBest == NULL) return;
-
- std::map::iterator it = mapMasternodeScanningErrors.begin();
-
- while(it != mapMasternodeScanningErrors.end()) {
- if(GetTime() > it->second.nExpiration){ //keep them for an hour
- LogPrintf("Removing old masternode scanning error %s\n", it->second.GetHash().ToString().c_str());
-
- mapMasternodeScanningErrors.erase(it++);
- } else {
- it++;
- }
- }
-
-}
-
-// Check other masternodes to make sure they're running correctly
-void CMasternodeScanning::DoMasternodePOSChecks()
-{
- if(!fMasterNode) return;
- if(!IsSporkActive(SPORK_7_MASTERNODE_SCANNING)) return;
- if(IsInitialBlockDownload()) return;
-
- int nBlockHeight = pindexBest->nHeight-5;
-
- int a = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight, MIN_MASTERNODE_POS_PROTO_VERSION);
- if(a == -1 || a > GetCountScanningPerBlock()){
- // we don't need to do anything this block
- return;
- }
-
- // The lowest ranking nodes (Masternode A) check the highest ranking nodes (Masternode B)
- CMasternode* pmn = mnodeman.GetMasternodeByRank(mnodeman.CountMasternodesAboveProtocol(MIN_MASTERNODE_POS_PROTO_VERSION)-a, nBlockHeight, MIN_MASTERNODE_POS_PROTO_VERSION, false);
- if(pmn == NULL) return;
-
- // -- first check : Port is open
-
- if(!ConnectNode((CAddress)pmn->addr, NULL, true)){
- // we couldn't connect to the node, let's send a scanning error
- CMasternodeScanningError mnse(activeMasternode.vin, pmn->vin, SCANNING_ERROR_NO_RESPONSE, nBlockHeight);
- mnse.Sign();
- mapMasternodeScanningErrors.insert(make_pair(mnse.GetHash(), mnse));
- mnse.Relay();
- }
-
- // success
- CMasternodeScanningError mnse(activeMasternode.vin, pmn->vin, SCANNING_SUCCESS, nBlockHeight);
- mnse.Sign();
- mapMasternodeScanningErrors.insert(make_pair(mnse.GetHash(), mnse));
- mnse.Relay();
-}
-
-bool CMasternodeScanningError::SignatureValid()
-{
- std::string errorMessage;
- std::string strMessage = vinMasternodeA.ToString() + vinMasternodeB.ToString() +
- boost::lexical_cast(nBlockHeight) + boost::lexical_cast(nErrorType);
-
- CMasternode* pmn = mnodeman.Find(vinMasternodeA);
-
- if(pmn == NULL)
- {
- LogPrintf("CMasternodeScanningError::SignatureValid() - Unknown Masternode\n");
- return false;
- }
-
- CScript pubkey;
- pubkey.SetDestination(pmn->pubkey2.GetID());
- CTxDestination address1;
- ExtractDestination(pubkey, address1);
- CBitcoinAddress address2(address1);
-
- if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
- LogPrintf("CMasternodeScanningError::SignatureValid() - Verify message failed\n");
- return false;
- }
-
- return true;
-}
-
-bool CMasternodeScanningError::Sign()
-{
- std::string errorMessage;
-
- CKey key2;
- CPubKey pubkey2;
- std::string strMessage = vinMasternodeA.ToString() + vinMasternodeB.ToString() +
- boost::lexical_cast(nBlockHeight) + boost::lexical_cast(nErrorType);
-
- if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2))
- {
- LogPrintf("CMasternodeScanningError::Sign() - ERROR: Invalid masternodeprivkey: '%s'\n", errorMessage.c_str());
- return false;
- }
-
- CScript pubkey;
- pubkey.SetDestination(pubkey2.GetID());
- CTxDestination address1;
- ExtractDestination(pubkey, address1);
- CBitcoinAddress address2(address1);
- //LogPrintf("signing pubkey2 %s \n", address2.ToString().c_str());
-
- if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, key2)) {
- LogPrintf("CMasternodeScanningError::Sign() - Sign message failed");
- return false;
- }
-
- if(!darkSendSigner.VerifyMessage(pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
- LogPrintf("CMasternodeScanningError::Sign() - Verify message failed");
- return false;
- }
-
- return true;
-}
-
-void CMasternodeScanningError::Relay()
-{
- CInv inv(MSG_MASTERNODE_SCANNING_ERROR, GetHash());
-
- vector vInv;
- vInv.push_back(inv);
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes){
- pnode->PushMessage("inv", vInv);
- }
-}
diff --git a/src/masternode-pos.h b/src/masternode-pos.h
deleted file mode 100644
index 411ef536..00000000
--- a/src/masternode-pos.h
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-// Copyright (c) 2014-2015 The Dash developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef MASTERNODE_POS_H
-#define MASTERNODE_POS_H
-
-#include "bignum.h"
-#include "sync.h"
-#include "net.h"
-#include "key.h"
-#include "core.h"
-#include "util.h"
-#include "script.h"
-#include "base58.h"
-#include "main.h"
-
-using namespace std;
-using namespace boost;
-
-class CMasternodeScanning;
-class CMasternodeScanningError;
-
-extern map mapMasternodeScanningErrors;
-extern CMasternodeScanning mnscan;
-
-static const int MIN_MASTERNODE_POS_PROTO_VERSION = 61402;
-
-/*
- 1% of the network is scanned every 2.5 minutes, making a full
- round of scanning take about 4.16 hours. We're targeting about
- a day of proof-of-service errors for complete removal from the
- masternode system.
-*/
-static const int MASTERNODE_SCANNING_ERROR_THESHOLD = 6;
-
-#define SCANNING_SUCCESS 1
-#define SCANNING_ERROR_NO_RESPONSE 2
-#define SCANNING_ERROR_IX_NO_RESPONSE 3
-#define SCANNING_ERROR_MAX 3
-
-void ProcessMessageMasternodePOS(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
-
-class CMasternodeScanning
-{
-public:
- void DoMasternodePOSChecks();
- void CleanMasternodeScanningErrors();
-};
-
-// Returns how many masternodes are allowed to scan each block
-int GetCountScanningPerBlock();
-
-class CMasternodeScanningError
-{
-public:
- CTxIn vinMasternodeA;
- CTxIn vinMasternodeB;
- int nErrorType;
- int nExpiration;
- int nBlockHeight;
- std::vector vchMasterNodeSignature;
-
- CMasternodeScanningError ()
- {
- vinMasternodeA = CTxIn();
- vinMasternodeB = CTxIn();
- nErrorType = 0;
- nExpiration = GetTime()+(60*60);
- nBlockHeight = 0;
- }
-
- CMasternodeScanningError (CTxIn& vinMasternodeAIn, CTxIn& vinMasternodeBIn, int nErrorTypeIn, int nBlockHeightIn)
- {
- vinMasternodeA = vinMasternodeAIn;
- vinMasternodeB = vinMasternodeBIn;
- nErrorType = nErrorTypeIn;
- nExpiration = GetTime()+(60*60);
- nBlockHeight = nBlockHeightIn;
- }
-
- CMasternodeScanningError (CTxIn& vinMasternodeBIn, int nErrorTypeIn, int nBlockHeightIn)
- {
- //just used for IX, MasternodeA is any client
- vinMasternodeA = CTxIn();
- vinMasternodeB = vinMasternodeBIn;
- nErrorType = nErrorTypeIn;
- nExpiration = GetTime()+(60*60);
- nBlockHeight = nBlockHeightIn;
- }
-
- uint256 GetHash() const {return SerializeHash(*this);}
-
- bool SignatureValid();
- bool Sign();
- bool IsExpired() {return GetTime() > nExpiration;}
- void Relay();
- bool IsValid() {
- return (nErrorType > 0 && nErrorType <= SCANNING_ERROR_MAX);
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(vinMasternodeA);
- READWRITE(vinMasternodeB);
- READWRITE(nErrorType);
- READWRITE(nExpiration);
- READWRITE(nBlockHeight);
- READWRITE(vchMasterNodeSignature);
- )
-};
-
-
-#endif
diff --git a/src/masternode.cpp b/src/masternode.cpp
index c1af6b4b..88002dbf 100644
--- a/src/masternode.cpp
+++ b/src/masternode.cpp
@@ -1,20 +1,407 @@
#include "masternode.h"
-#include "masternodeman.h"
+#include "activemasternode.h"
#include "darksend.h"
-#include "core.h"
+//#include "primitives/transaction.h"
#include "main.h"
-#include "sync.h"
#include "util.h"
#include "addrman.h"
#include
+int CMasterNode::minProtoVersion = MIN_MN_PROTO_VERSION;
+
CCriticalSection cs_masternodes;
+
+/** The list of active masternodes */
+std::vector vecMasternodes;
+/** Object for who's going to get paid on which blocks */
+CMasternodePayments masternodePayments;
+// keep track of masternode votes I've seen
+map mapSeenMasternodeVotes;
// keep track of the scanning errors I've seen
map mapSeenMasternodeScanningErrors;
+// who's asked for the masternode list and the last time
+std::map askedForMasternodeList;
+// which masternodes we've asked for
+std::map askedForMasternodeListEntry;
// cache block hashes as we calculate them
std::map mapCacheBlockHashes;
+std::set setKnownMnMsgs;
+
+// manage the masternode connections
+void ProcessMasternodeConnections(){
+ LOCK(cs_vNodes);
+
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ {
+ //if it's our masternode, let it be
+ if(darkSendPool.submittedToMasternode == pnode->addr) continue;
+
+ if(pnode->fDarkSendMaster){
+ LogPrintf("Closing masternode connection %s \n", pnode->addr.ToString().c_str());
+ pnode->CloseSocketDisconnect();
+ }
+ }
+}
+
+void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
+{
+
+ if(fLiteMode) return;
+
+ if (strCommand == "dsee") { //DarkSend Election Entry
+ if(fLiteMode) return; //disable all darksend/masternode related functionality
+
+ bool fIsInitialDownload = IsInitialBlockDownload();
+ if(fIsInitialDownload || IsSyncing()) return;
+
+ CTxIn vin;
+ CService addr;
+ CPubKey pubkey;
+ CPubKey pubkey2;
+ vector vchSig;
+ int64_t sigTime;
+ int count;
+ int current;
+ int64_t lastUpdated;
+ int protocolVersion;
+ std::string strMessage;
+
+ // 70047 and greater
+ vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current >> lastUpdated >> protocolVersion;
+
+ CDataStream ssCheck(SER_GETHASH, PROTOCOL_VERSION);
+ ssCheck << CMessageHeader("dsee",0) << vin << addr << vchSig << sigTime << pubkey << pubkey2 << count << current << lastUpdated << protocolVersion;
+ uint256 hashCheck = SerializeHash(std::vector(ssCheck.begin(), ssCheck.end()));
+
+ if(setKnownMnMsgs.count(hashCheck))
+ {
+ // already have this dsee
+ return;
+ }
+
+ setKnownMnMsgs.insert(hashCheck);
+
+ // make sure signature isn't in the future (past is OK)
+ if (sigTime > GetAdjustedTime() + 60 * 60) {
+ LogPrintf("dsee - Signature rejected, too far into the future %s\n", vin.ToString().c_str());
+ return;
+ }
+
+ bool isLocal = addr.IsRFC1918() || addr.IsLocal();
+ //if(Params().MineBlocksOnDemand()) isLocal = false;
+
+ std::string vchPubKey(pubkey.begin(), pubkey.end());
+ std::string vchPubKey2(pubkey2.begin(), pubkey2.end());
+
+ strMessage = addr.ToString() + boost::lexical_cast(sigTime) + vchPubKey + vchPubKey2 + boost::lexical_cast(protocolVersion);
+
+ if(protocolVersion < MIN_MN_PROTO_VERSION) {
+ LogPrintf("dsee - ignoring outdated masternode %s protocol version %d\n", vin.ToString().c_str(), protocolVersion);
+ return;
+ }
+
+ CScript pubkeyScript;
+ pubkeyScript =GetScriptForDestination(pubkey.GetID());
+
+ if(pubkeyScript.size() != 25) {
+ LogPrintf("dsee - pubkey the wrong size\n");
+ Misbehaving(pfrom->GetId(), 100);
+ return;
+ }
+
+ CScript pubkeyScript2;
+ pubkeyScript2 =GetScriptForDestination(pubkey2.GetID());
+
+ if(pubkeyScript2.size() != 25) {
+ LogPrintf("dsee - pubkey2 the wrong size\n");
+ Misbehaving(pfrom->GetId(), 100);
+ return;
+ }
+
+ std::string errorMessage = "";
+ if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, errorMessage)){
+ LogPrintf("dsee - Got bad masternode address signature\n");
+ Misbehaving(pfrom->GetId(), 100);
+ return;
+ }
+
+
+
+ //search existing masternode list, this is where we update existing masternodes with new dsee broadcasts
+ LOCK(cs_masternodes);
+ BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
+ if(mn.vin.prevout == vin.prevout) {
+ // count == -1 when it's a new entry
+ // e.g. We don't want the entry relayed/time updated when we're syncing the list
+ // mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below,
+ // after that they just need to match
+ if(count == -1 && mn.pubkey == pubkey && !mn.UpdatedWithin(MASTERNODE_MIN_DSEE_SECONDS)){
+ mn.UpdateLastSeen();
+
+ if(mn.now < sigTime){ //take the newest entry
+ LogPrintf("dsee - Got updated entry for %s\n", addr.ToString().c_str());
+ mn.pubkey2 = pubkey2;
+ mn.now = sigTime;
+ mn.sig = vchSig;
+ mn.protocolVersion = protocolVersion;
+ mn.addr = addr;
+
+ RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion);
+ }
+ }
+
+ return;
+ }
+ }
+
+ // make sure the vout that was signed is related to the transaction that spawned the masternode
+ // - this is expensive, so it's only done once per masternode
+ if(!darkSendSigner.IsVinAssociatedWithPubkey(vin, pubkey)) {
+ LogPrintf("dsee - Got mismatched pubkey and vin\n");
+ Misbehaving(pfrom->GetId(), 100);
+ return;
+ }
+
+ if(fDebug) LogPrintf("dsee - Got NEW masternode entry %s\n", addr.ToString().c_str());
+
+ // make sure it's still unspent
+ // - this is checked later by .check() in many places and by ThreadCheckDarkSendPool()
+
+ CValidationState state;
+ CTransaction tx = CTransaction();
+ CTxOut vout = CTxOut(14999*COIN, darkSendPool.collateralPubKey);
+ tx.vin.push_back(vin);
+ tx.vout.push_back(vout);
+ //if(AcceptableInputs(mempool, state, tx)){
+ bool* pfMissingInputs;
+ if(AcceptableInputs(mempool, tx, false, pfMissingInputs)){
+ if(fDebug) LogPrintf("dsee - Accepted masternode entry %i %i\n", count, current);
+
+ if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){
+ LogPrintf("dsee - Input must have least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS);
+ Misbehaving(pfrom->GetId(), 20);
+ return;
+ }
+
+ // use this as a peer
+ addrman.Add(CAddress(addr), pfrom->addr, 2*60*60);
+
+ // add our masternode
+ CMasterNode mn(addr, vin, pubkey, vchSig, sigTime, pubkey2, protocolVersion);
+ mn.UpdateLastSeen(lastUpdated);
+ vecMasternodes.push_back(mn);
+
+ // if it matches our masternodeprivkey, then we've been remotely activated
+ if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){
+ activeMasternode.EnableHotColdMasterNode(vin, addr);
+ }
+
+ if(count == -1 && !isLocal)
+ RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion);
+
+ } else {
+ LogPrintf("dsee - Rejected masternode entry %s\n", addr.ToString().c_str());
+
+ int nDoS = 0;
+ if (state.IsInvalid(nDoS))
+ {
+ LogPrintf("dsee - %s from %s %s was not accepted into the memory pool\n", tx.GetHash().ToString().c_str(),
+ pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str());
+ if (nDoS > 0)
+ Misbehaving(pfrom->GetId(), nDoS);
+ }
+ }
+ }
+
+ else if (strCommand == "dseep") { //DarkSend Election Entry Ping
+ if(fLiteMode) return; //disable all darksend/masternode related functionality
+ bool fIsInitialDownload = IsInitialBlockDownload();
+ if(fIsInitialDownload || IsSyncing()) return;
+
+ CTxIn vin;
+ vector vchSig;
+ int64_t sigTime;
+ bool stop;
+ vRecv >> vin >> vchSig >> sigTime >> stop;
+
+ CDataStream ssCheck(SER_GETHASH, PROTOCOL_VERSION);
+ ssCheck << CMessageHeader("dseep",0) << vin << vchSig << sigTime << stop;
+ uint256 hashCheck = SerializeHash(std::vector(ssCheck.begin(), ssCheck.end()));
+ if(setKnownMnMsgs.count(hashCheck))
+ {
+ // already have this dseep
+ return;
+ }
+
+ setKnownMnMsgs.insert(hashCheck);
+
+ //LogPrintf("dseep - Received: vin: %s sigTime: %lld stop: %s\n", vin.ToString().c_str(), sigTime, stop ? "true" : "false");
+
+ if (sigTime > GetAdjustedTime() + 60 * 60) {
+ LogPrintf("dseep - Signature rejected, too far into the future %s\n", vin.ToString().c_str());
+ return;
+ }
+
+ if (sigTime <= GetAdjustedTime() - 60 * 60) {
+ LogPrintf("dseep - Signature rejected, too far into the past %s - %d %d \n", vin.ToString().c_str(), sigTime, GetAdjustedTime());
+ return;
+ }
+
+ // see if we have this masternode
+ LOCK(cs_masternodes);
+ BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
+ if(mn.vin.prevout == vin.prevout) {
+ // LogPrintf("dseep - Found corresponding mn for vin: %s\n", vin.ToString().c_str());
+ // take this only if it's newer
+ if(mn.lastDseep < sigTime){
+ std::string strMessage = mn.addr.ToString() + boost::lexical_cast(sigTime) + boost::lexical_cast(stop);
+
+ std::string errorMessage = "";
+ if(!darkSendSigner.VerifyMessage(mn.pubkey2, vchSig, strMessage, errorMessage)){
+ LogPrintf("dseep - Got bad masternode address signature %s \n", vin.ToString().c_str());
+ //Misbehaving(pfrom->GetId(), 100);
+ return;
+ }
+
+ mn.lastDseep = sigTime;
+
+ if(!mn.UpdatedWithin(MASTERNODE_MIN_DSEEP_SECONDS)){
+ mn.UpdateLastSeen();
+ if(stop) {
+ mn.Disable();
+ mn.Check();
+ }
+ RelayDarkSendElectionEntryPing(vin, vchSig, sigTime, stop);
+ }
+ }
+ return;
+ }
+ }
+
+ if(fDebug) LogPrintf("dseep - Couldn't find masternode entry %s\n", vin.ToString().c_str());
+
+ std::map::iterator i = askedForMasternodeListEntry.find(vin.prevout);
+ if (i != askedForMasternodeListEntry.end()){
+ int64_t t = (*i).second;
+ if (GetTime() < t) {
+ // we've asked recently
+ return;
+ }
+ }
+
+ // ask for the dsee info once from the node that sent dseep
+
+ LogPrintf("dseep - Asking source node for missing entry %s\n", vin.ToString().c_str());
+ pfrom->PushMessage("dseg", vin);
+ int64_t askAgain = GetTime()+(60*60*24);
+ askedForMasternodeListEntry[vin.prevout] = askAgain;
+
+ } else if (strCommand == "dseg") { //Get masternode list or specific entry
+ if(fLiteMode) return; //disable all darksend/masternode related functionality
+ CTxIn vin;
+ vRecv >> vin;
+
+ if(vin == CTxIn()) { //only should ask for this once
+ //local network
+ //Note tor peers show up as local proxied addrs //if(!pfrom->addr.IsRFC1918())//&& !Params().MineBlocksOnDemand())
+ //{
+ std::map::iterator i = askedForMasternodeList.find(pfrom->addr);
+ if (i != askedForMasternodeList.end())
+ {
+ int64_t t = (*i).second;
+ if (GetTime() < t) {
+ //Misbehaving(pfrom->GetId(), 34);
+ //LogPrintf("dseg - peer already asked me for the list\n");
+ //return;
+ }
+ }
+
+ int64_t askAgain = GetTime()+(60*60*3);
+ askedForMasternodeList[pfrom->addr] = askAgain;
+ //}
+ } //else, asking for a specific node which is ok
+
+ LOCK(cs_masternodes);
+ int count = vecMasternodes.size();
+ int i = 0;
+
+ BOOST_FOREACH(CMasterNode mn, vecMasternodes) {
+
+ if(mn.addr.IsRFC1918()) continue; //local network
+
+ if(vin == CTxIn()){
+ mn.Check();
+ if(mn.IsEnabled()) {
+ if(fDebug) LogPrintf("dseg - Sending masternode entry - %s \n", mn.addr.ToString().c_str());
+ pfrom->PushMessage("dsee", mn.vin, mn.addr, mn.sig, mn.now, mn.pubkey, mn.pubkey2, count, i, mn.lastTimeSeen, mn.protocolVersion);
+ }
+ } else if (vin == mn.vin) {
+ if(fDebug) LogPrintf("dseg - Sending masternode entry - %s \n", mn.addr.ToString().c_str());
+ pfrom->PushMessage("dsee", mn.vin, mn.addr, mn.sig, mn.now, mn.pubkey, mn.pubkey2, count, i, mn.lastTimeSeen, mn.protocolVersion);
+ LogPrintf("dseg - Sent 1 masternode entries to %s\n", pfrom->addr.ToString().c_str());
+ return;
+ }
+ i++;
+ }
+
+ LogPrintf("dseg - Sent %d masternode entries to %s\n", count, pfrom->addr.ToString().c_str());
+ }
+
+ else if (strCommand == "mnget") { //Masternode Payments Request Sync
+ if(fLiteMode) return; //disable all darksend/masternode related functionality
+
+ /*if(pfrom->HasFulfilledRequest("mnget")) {
+ LogPrintf("mnget - peer already asked me for the list\n");
+ Misbehaving(pfrom->GetId(), 20);
+ return;
+ }*/
+
+ pfrom->FulfilledRequest("mnget");
+ masternodePayments.Sync(pfrom);
+ LogPrintf("mnget - Sent masternode winners to %s\n", pfrom->addr.ToString().c_str());
+ }
+ else if (strCommand == "mnw") { //Masternode Payments Declare Winner
+ //this is required in litemode / nomntesting mode
+ CMasternodePaymentWinner winner;
+ int a = 0;
+ vRecv >> winner >> a;
+
+ if(pindexBest == NULL) return;
+
+ uint256 hash = winner.GetHash();
+ if(mapSeenMasternodeVotes.count(hash)) {
+ if(fDebug) LogPrintf("mnw - seen vote %s Height %d bestHeight %d\n", hash.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight);
+ return;
+ }
+
+ if(winner.nBlockHeight < pindexBest->nHeight - 10 || winner.nBlockHeight > pindexBest->nHeight+20){
+ LogPrintf("mnw - winner out of range %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight);
+ return;
+ }
+
+ if(winner.vin.nSequence != std::numeric_limits::max()){
+ LogPrintf("mnw - invalid nSequence\n");
+ Misbehaving(pfrom->GetId(), 100);
+ return;
+ }
+
+ LogPrintf("mnw - winning vote %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight);
+
+ if(!masternodePayments.CheckSignature(winner)){
+ LogPrintf("mnw - invalid signature\n");
+ Misbehaving(pfrom->GetId(), 100);
+ return;
+ }
+
+ mapSeenMasternodeVotes.insert(make_pair(hash, winner));
+
+ if(masternodePayments.AddWinningMasternode(winner)){
+ masternodePayments.Relay(winner);
+ }
+ }
+}
struct CompareValueOnly
{
@@ -25,6 +412,140 @@ struct CompareValueOnly
}
};
+struct CompareValueOnly2
+{
+ bool operator()(const pair& t1,
+ const pair& t2) const
+ {
+ return t1.first < t2.first;
+ }
+};
+
+int CountMasternodesAboveProtocol(int protocolVersion)
+{
+ int i = 0;
+ LOCK(cs_masternodes);
+ BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
+ if(mn.protocolVersion < protocolVersion) continue;
+ i++;
+ }
+
+ return i;
+
+}
+
+
+int GetMasternodeByVin(CTxIn& vin)
+{
+ int i = 0;
+ LOCK(cs_masternodes);
+ BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
+ if (mn.vin == vin) return i;
+ i++;
+ }
+
+ return -1;
+}
+
+int GetCurrentMasterNode(int mod, int64_t nBlockHeight, int minProtocol)
+{
+ int i = 0;
+ unsigned int score = 0;
+ int winner = -1;
+ LOCK(cs_masternodes);
+ // scan for winner
+ BOOST_FOREACH(CMasterNode mn, vecMasternodes) {
+ mn.Check();
+ if(mn.protocolVersion < minProtocol) continue;
+ if(!mn.IsEnabled()) {
+ i++;
+ continue;
+ }
+
+ // calculate the score for each masternode
+ uint256 n = mn.CalculateScore(mod, nBlockHeight);
+ unsigned int n2 = 0;
+ memcpy(&n2, &n, sizeof(n2));
+
+ // determine the winner
+ if(n2 > score){
+ score = n2;
+ winner = i;
+ }
+ i++;
+ }
+
+ return winner;
+}
+
+int GetMasternodeByRank(int findRank, int64_t nBlockHeight, int minProtocol)
+{
+ LOCK(cs_masternodes);
+ int i = 0;
+
+ std::vector > vecMasternodeScores;
+
+ i = 0;
+ BOOST_FOREACH(CMasterNode mn, vecMasternodes) {
+ mn.Check();
+ if(mn.protocolVersion < minProtocol) continue;
+ if(!mn.IsEnabled()) {
+ i++;
+ continue;
+ }
+
+ uint256 n = mn.CalculateScore(1, nBlockHeight);
+ unsigned int n2 = 0;
+ memcpy(&n2, &n, sizeof(n2));
+
+ vecMasternodeScores.push_back(make_pair(n2, i));
+ i++;
+ }
+
+ sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareValueOnly2());
+
+ int rank = 0;
+ BOOST_FOREACH (PAIRTYPE(unsigned int, int)& s, vecMasternodeScores){
+ rank++;
+ if(rank == findRank) return s.second;
+ }
+
+ return -1;
+}
+
+int GetMasternodeRank(CTxIn& vin, int64_t nBlockHeight, int minProtocol)
+{
+ LOCK(cs_masternodes);
+ std::vector > vecMasternodeScores;
+
+ BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
+ mn.Check();
+
+ if(mn.protocolVersion < minProtocol) continue;
+ if(!mn.IsEnabled()) {
+ continue;
+ }
+
+ uint256 n = mn.CalculateScore(1, nBlockHeight);
+ unsigned int n2 = 0;
+ memcpy(&n2, &n, sizeof(n2));
+
+ vecMasternodeScores.push_back(make_pair(n2, mn.vin));
+ }
+
+ sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareValueOnly());
+
+ unsigned int rank = 0;
+ BOOST_FOREACH (PAIRTYPE(unsigned int, CTxIn)& s, vecMasternodeScores){
+ rank++;
+ if(s.second == vin) {
+ return rank;
+ }
+ }
+
+ return -1;
+}
+
//Get the last hash that matches the modulus given. Processed in reverse order
bool GetBlockHash(uint256& hash, int nBlockHeight)
{
@@ -63,94 +584,12 @@ bool GetBlockHash(uint256& hash, int nBlockHeight)
return false;
}
-CMasternode::CMasternode()
-{
- LOCK(cs);
- vin = CTxIn();
- addr = CService();
- pubkey = CPubKey();
- pubkey2 = CPubKey();
- sig = std::vector();
- activeState = MASTERNODE_ENABLED;
- sigTime = GetAdjustedTime();
- lastDseep = 0;
- lastTimeSeen = 0;
- cacheInputAge = 0;
- cacheInputAgeBlock = 0;
- unitTest = false;
- allowFreeTx = true;
- protocolVersion = MIN_PEER_PROTO_VERSION;
- nLastDsq = 0;
- donationAddress = CScript();
- donationPercentage = 0;
- nVote = 0;
- lastVote = 0;
- nScanningErrorCount = 0;
- nLastScanningErrorBlockHeight = 0;
- //mark last paid as current for new entries
- nLastPaid = GetAdjustedTime();
-}
-
-CMasternode::CMasternode(const CMasternode& other)
-{
- LOCK(cs);
- vin = other.vin;
- addr = other.addr;
- pubkey = other.pubkey;
- pubkey2 = other.pubkey2;
- sig = other.sig;
- activeState = other.activeState;
- sigTime = other.sigTime;
- lastDseep = other.lastDseep;
- lastTimeSeen = other.lastTimeSeen;
- cacheInputAge = other.cacheInputAge;
- cacheInputAgeBlock = other.cacheInputAgeBlock;
- unitTest = other.unitTest;
- allowFreeTx = other.allowFreeTx;
- protocolVersion = other.protocolVersion;
- nLastDsq = other.nLastDsq;
- donationAddress = other.donationAddress;
- donationPercentage = other.donationPercentage;
- nVote = other.nVote;
- lastVote = other.lastVote;
- nScanningErrorCount = other.nScanningErrorCount;
- nLastScanningErrorBlockHeight = other.nLastScanningErrorBlockHeight;
- nLastPaid = other.nLastPaid;
- nLastPaid = GetAdjustedTime();
-}
-
-CMasternode::CMasternode(CService newAddr, CTxIn newVin, CPubKey newPubkey, std::vector newSig, int64_t newSigTime, CPubKey newPubkey2, int protocolVersionIn, CScript newDonationAddress, int newDonationPercentage)
-{
- LOCK(cs);
- vin = newVin;
- addr = newAddr;
- pubkey = newPubkey;
- pubkey2 = newPubkey2;
- sig = newSig;
- activeState = MASTERNODE_ENABLED;
- sigTime = newSigTime;
- lastDseep = 0;
- lastTimeSeen = 0;
- cacheInputAge = 0;
- cacheInputAgeBlock = 0;
- unitTest = false;
- allowFreeTx = true;
- protocolVersion = protocolVersionIn;
- nLastDsq = 0;
- donationAddress = newDonationAddress;
- donationPercentage = newDonationPercentage;
- nVote = 0;
- lastVote = 0;
- nScanningErrorCount = 0;
- nLastScanningErrorBlockHeight = 0;
-}
-
//
// 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
//
-uint256 CMasternode::CalculateScore(int mod, int64_t nBlockHeight)
+uint256 CMasterNode::CalculateScore(int mod, int64_t nBlockHeight)
{
if(pindexBest == NULL) return 0;
@@ -160,47 +599,298 @@ uint256 CMasternode::CalculateScore(int mod, int64_t nBlockHeight)
if(!GetBlockHash(hash, nBlockHeight)) return 0;
uint256 hash2 = Hash(BEGIN(hash), END(hash));
- uint256 hash3 = Hash(BEGIN(hash), END(hash), BEGIN(aux), END(aux));
+ uint256 hash3 = Hash(BEGIN(hash), END(aux));
uint256 r = (hash3 > hash2 ? hash3 - hash2 : hash2 - hash3);
return r;
}
-void CMasternode::Check()
+void CMasterNode::Check()
{
- if(ShutdownRequested()) return;
-
- //TODO: Random segfault with this line removed
- TRY_LOCK(cs_main, lockRecv);
- if(!lockRecv) return;
-
//once spent, stop doing the checks
- if(activeState == MASTERNODE_VIN_SPENT) return;
+ if(enabled==3) return;
if(!UpdatedWithin(MASTERNODE_REMOVAL_SECONDS)){
- activeState = MASTERNODE_REMOVE;
+ enabled = 4;
return;
}
if(!UpdatedWithin(MASTERNODE_EXPIRATION_SECONDS)){
- activeState = MASTERNODE_EXPIRED;
+ enabled = 2;
return;
}
if(!unitTest){
CValidationState state;
CTransaction tx = CTransaction();
- CTxOut vout = CTxOut(DARKSEND_POOL_MAX, darkSendPool.collateralPubKey);
+ CTxOut vout = CTxOut(499*COIN, darkSendPool.collateralPubKey);
tx.vin.push_back(vin);
tx.vout.push_back(vout);
- if(!AcceptableInputs(mempool, tx, false, NULL)){
- activeState = MASTERNODE_VIN_SPENT;
+ //if(!AcceptableInputs(mempool, state, tx)){
+ bool* pfMissingInputs;
+
+ if(!AcceptableInputs(mempool, tx, false, pfMissingInputs)){
+ enabled = 3;
return;
}
}
- activeState = MASTERNODE_ENABLED; // OK
-}
\ No newline at end of file
+ enabled = 1; // OK
+}
+
+std::string CMasterNode::GetStatus()
+{
+ switch(enabled)
+ {
+ case 0:
+ return "Not Processed";
+ case 1:
+ return "Ok";
+ case 2:
+ return "Not Capable";
+ case 3:
+ return "Stopped";
+ case 4:
+ return "Input Too New";
+ case 6:
+ return "Port Not Open";
+ case 7:
+ return "Port Open";
+ case 8:
+ return "Syncing";
+ case 9:
+ return "Remotely Enabled";
+ }
+}
+
+bool CMasternodePayments::CheckSignature(CMasternodePaymentWinner& winner)
+{
+ //note: need to investigate why this is failing
+ std::string strMessage = winner.vin.ToString().c_str() + boost::lexical_cast(winner.nBlockHeight) + winner.payee.ToString();
+ std::string strPubKey = strMainPubKey ;
+ CPubKey pubkey(ParseHex(strPubKey));
+
+ std::string errorMessage = "";
+ if(!darkSendSigner.VerifyMessage(pubkey, winner.vchSig, strMessage, errorMessage)){
+ return false;
+ }
+
+ return true;
+}
+
+bool CMasternodePayments::Sign(CMasternodePaymentWinner& winner)
+{
+ std::string strMessage = winner.vin.ToString().c_str() + boost::lexical_cast(winner.nBlockHeight) + winner.payee.ToString();
+
+ CKey key2;
+ CPubKey pubkey2;
+ std::string errorMessage = "";
+
+ if(!darkSendSigner.SetKey(strMasterPrivKey, errorMessage, key2, pubkey2))
+ {
+ LogPrintf("CMasternodePayments::Sign - ERROR: Invalid masternodeprivkey: '%s'\n", errorMessage.c_str());
+ return false;
+ }
+
+ if(!darkSendSigner.SignMessage(strMessage, errorMessage, winner.vchSig, key2)) {
+ LogPrintf("CMasternodePayments::Sign - Sign message failed");
+ return false;
+ }
+
+ if(!darkSendSigner.VerifyMessage(pubkey2, winner.vchSig, strMessage, errorMessage)) {
+ LogPrintf("CMasternodePayments::Sign - Verify message failed");
+ return false;
+ }
+
+ return true;
+}
+
+uint64_t CMasternodePayments::CalculateScore(uint256 blockHash, CTxIn& vin)
+{
+ uint256 n1 = blockHash;
+ uint256 n2 = Hash(BEGIN(n1), END(n1));
+ uint256 n3 = Hash(BEGIN(vin.prevout.hash), END(vin.prevout.hash));
+ uint256 n4 = n3 > n2 ? (n3 - n2) : (n2 - n3);
+
+ //printf(" -- CMasternodePayments CalculateScore() n2 = %d \n", n2.Get64());
+ //printf(" -- CMasternodePayments CalculateScore() n3 = %d \n", n3.Get64());
+ //printf(" -- CMasternodePayments CalculateScore() n4 = %d \n", n4.Get64());
+
+ return n4.Get64();
+}
+
+bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
+{
+ BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
+ if(winner.nBlockHeight == nBlockHeight) {
+ payee = winner.payee;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CMasternodePayments::GetWinningMasternode(int nBlockHeight, CTxIn& vinOut)
+{
+ BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
+ if(winner.nBlockHeight == nBlockHeight) {
+ vinOut = winner.vin;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerIn)
+{
+ uint256 blockHash = 0;
+ if(!GetBlockHash(blockHash, winnerIn.nBlockHeight-576)) {
+ return false;
+ }
+
+ winnerIn.score = CalculateScore(blockHash, winnerIn.vin);
+
+ bool foundBlock = false;
+ BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
+ if(winner.nBlockHeight == winnerIn.nBlockHeight) {
+ foundBlock = true;
+ if(winner.score < winnerIn.score){
+ winner.score = winnerIn.score;
+ winner.vin = winnerIn.vin;
+ winner.payee = winnerIn.payee;
+ winner.vchSig = winnerIn.vchSig;
+
+ return true;
+ }
+ }
+ }
+
+ // if it's not in the vector
+ if(!foundBlock){
+ vWinning.push_back(winnerIn);
+ mapSeenMasternodeVotes.insert(make_pair(winnerIn.GetHash(), winnerIn));
+
+ return true;
+ }
+
+ return false;
+}
+
+void CMasternodePayments::CleanPaymentList()
+{
+ TRY_LOCK(cs_masternodes, lockMasternodes);
+ if(!lockMasternodes) return;
+
+ if(pindexBest == NULL) return;
+
+ int nLimit = std::max(((int)vecMasternodes.size())*2, 1000);
+
+ vector::iterator it;
+ for(it=vWinning.begin();itnHeight - (*it).nBlockHeight > nLimit){
+ if(fDebug) LogPrintf("CMasternodePayments::CleanPaymentList - Removing old masternode payment - block %d\n", (*it).nBlockHeight);
+ vWinning.erase(it);
+ break;
+ }
+ }
+}
+
+bool CMasternodePayments::ProcessBlock(int nBlockHeight)
+{
+ LOCK(cs_masternodes);
+ if(!enabled) return false;
+ CMasternodePaymentWinner winner;
+
+ std::vector vecLastPayments;
+ int c = 0;
+ BOOST_REVERSE_FOREACH(CMasternodePaymentWinner& winner, vWinning){
+ vecLastPayments.push_back(winner.vin);
+ //if we have one full payment cycle, break
+ if(++c > (int)vecMasternodes.size()) break;
+ }
+
+ std::random_shuffle ( vecMasternodes.begin(), vecMasternodes.end() );
+ BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
+ bool found = false;
+ BOOST_FOREACH(CTxIn& vin, vecLastPayments)
+ if(mn.vin == vin) found = true;
+
+ if(found) continue;
+
+ mn.Check();
+ if(!mn.IsEnabled()) {
+ continue;
+ }
+
+ winner.score = 0;
+ winner.nBlockHeight = nBlockHeight;
+ winner.vin = mn.vin;
+ winner.payee =GetScriptForDestination(mn.pubkey.GetID());
+
+ break;
+ }
+
+ //if we can't find someone to get paid, pick randomly
+ if(winner.nBlockHeight == 0 && vecMasternodes.size() > 0) {
+ winner.score = 0;
+ winner.nBlockHeight = nBlockHeight;
+ winner.vin = vecMasternodes[0].vin;
+ winner.payee =GetScriptForDestination(vecMasternodes[0].pubkey.GetID());
+ }
+
+ if(Sign(winner)){
+ if(AddWinningMasternode(winner)){
+ Relay(winner);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CMasternodePayments::Relay(CMasternodePaymentWinner& winner)
+{
+ if(!fLiteMode && !IsInitialBlockDownload() && !IsSyncing())
+ {
+ CInv inv(MSG_MASTERNODE_WINNER, winner.GetHash());
+
+ vector vInv;
+ vInv.push_back(inv);
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pnode, vNodes){
+ pnode->PushMessage("inv", vInv);
+ }
+ }
+}
+
+void CMasternodePayments::Sync(CNode* node)
+{
+ int a = 0;
+ BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning)
+ if(winner.nBlockHeight >= pindexBest->nHeight-10 && winner.nBlockHeight <= pindexBest->nHeight + 20)
+ node->PushMessage("mnw", winner, a);
+}
+
+
+bool CMasternodePayments::SetPrivKey(std::string strPrivKey)
+{
+ CMasternodePaymentWinner winner;
+
+ // Test signing successful, proceed
+ strMasterPrivKey = strPrivKey;
+
+ Sign(winner);
+
+ if(CheckSignature(winner)){
+ LogPrintf("CMasternodePayments::SetPrivKey - Successfully initialized as masternode payments master\n");
+ enabled = true;
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/src/masternode.h b/src/masternode.h
index 1172a93e..4c601123 100644
--- a/src/masternode.h
+++ b/src/masternode.h
@@ -1,3 +1,4 @@
+
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Darkcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
@@ -5,17 +6,22 @@
#ifndef MASTERNODE_H
#define MASTERNODE_H
+#include "uint256.h"
#include "uint256.h"
#include "sync.h"
#include "net.h"
#include "key.h"
+//#include "primitives/transaction.h"
+//#include "primitives/block.h"
#include "util.h"
+//#include "script/script.h"
#include "base58.h"
#include "main.h"
#include "timedata.h"
#include "script.h"
-#include "masternode.h"
+class CMasterNode;
+class CMasternodePayments;
class uint256;
#define MASTERNODE_NOT_PROCESSED 0 // initial state
@@ -28,7 +34,7 @@ class uint256;
#define MASTERNODE_SYNC_IN_PROCESS 8
#define MASTERNODE_REMOTELY_ENABLED 9
-#define MASTERNODE_MIN_CONFIRMATIONS 7
+#define MASTERNODE_MIN_CONFIRMATIONS 15
#define MASTERNODE_MIN_DSEEP_SECONDS (30*60)
#define MASTERNODE_MIN_DSEE_SECONDS (5*60)
#define MASTERNODE_PING_SECONDS (1*60)
@@ -37,147 +43,70 @@ class uint256;
using namespace std;
-class CMasternode;
+class CMasternodePaymentWinner;
extern CCriticalSection cs_masternodes;
+extern std::vector vecMasternodes;
+extern CMasternodePayments masternodePayments;
+extern std::vector vecMasternodeAskedFor;
+extern map mapSeenMasternodeVotes;
extern map mapCacheBlockHashes;
-bool GetBlockHash(uint256& hash, int nBlockHeight);
+
+// manage the masternode connections
+void ProcessMasternodeConnections();
+int CountMasternodesAboveProtocol(int protocolVersion);
+
+
+void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
//
-// The Masternode Class. For managing the darksend process. It contains the input of the 10000 Memetic, signature to prove
+// The Masternode Class. For managing the darksend process. It contains the input of the 1000DRK, signature to prove
// it's the one who own that ip address and code for calculating the payment election.
//
-class CMasternode
+class CMasterNode
{
-private:
- // critical section to protect the inner data structures
- mutable CCriticalSection cs;
-
public:
- enum state {
- MASTERNODE_ENABLED = 1,
- MASTERNODE_EXPIRED = 2,
- MASTERNODE_VIN_SPENT = 3,
- MASTERNODE_REMOVE = 4,
- MASTERNODE_POS_ERROR = 5
- };
-
- CTxIn vin;
+ static int minProtoVersion;
CService addr;
+ CTxIn vin;
+ int64_t lastTimeSeen;
CPubKey pubkey;
CPubKey pubkey2;
std::vector sig;
- int activeState;
- int64_t sigTime; //dsee message times
+ int64_t now; //dsee message times
int64_t lastDseep;
- int64_t lastTimeSeen;
int cacheInputAge;
int cacheInputAgeBlock;
+ int enabled;
bool unitTest;
bool allowFreeTx;
int protocolVersion;
- int64_t nLastDsq; //the dsq count from the last dsq broadcast of this node
- CScript donationAddress;
- int donationPercentage;
- int nVote;
- int64_t lastVote;
- int nScanningErrorCount;
- int nLastScanningErrorBlockHeight;
- int64_t nLastPaid;
-
- CMasternode();
- CMasternode(const CMasternode& other);
- CMasternode(CService newAddr, CTxIn newVin, CPubKey newPubkey, std::vector newSig, int64_t newSigTime, CPubKey newPubkey2, int protocolVersionIn, CScript donationAddress, int donationPercentage);
+ //the dsq count from the last dsq broadcast of this node
+ int64_t nLastDsq;
-
- void swap(CMasternode& first, CMasternode& second) // nothrow
- {
- // enable ADL (not necessary in our case, but good practice)
- using std::swap;
-
- // by swapping the members of two classes,
- // the two classes are effectively swapped
- swap(first.vin, second.vin);
- swap(first.addr, second.addr);
- swap(first.pubkey, second.pubkey);
- swap(first.pubkey2, second.pubkey2);
- swap(first.sig, second.sig);
- swap(first.activeState, second.activeState);
- swap(first.sigTime, second.sigTime);
- swap(first.lastDseep, second.lastDseep);
- swap(first.lastTimeSeen, second.lastTimeSeen);
- swap(first.cacheInputAge, second.cacheInputAge);
- swap(first.cacheInputAgeBlock, second.cacheInputAgeBlock);
- swap(first.unitTest, second.unitTest);
- swap(first.allowFreeTx, second.allowFreeTx);
- swap(first.protocolVersion, second.protocolVersion);
- swap(first.nLastDsq, second.nLastDsq);
- swap(first.donationAddress, second.donationAddress);
- swap(first.donationPercentage, second.donationPercentage);
- swap(first.nVote, second.nVote);
- swap(first.lastVote, second.lastVote);
- swap(first.nScanningErrorCount, second.nScanningErrorCount);
- swap(first.nLastScanningErrorBlockHeight, second.nLastScanningErrorBlockHeight);
- swap(first.nLastPaid, second.nLastPaid);
- }
-
- CMasternode& operator=(CMasternode from)
+ CMasterNode(CService newAddr, CTxIn newVin, CPubKey newPubkey, std::vector newSig, int64_t newNow, CPubKey newPubkey2, int protocolVersionIn)
{
- swap(*this, from);
- return *this;
- }
- friend bool operator==(const CMasternode& a, const CMasternode& b)
- {
- return a.vin == b.vin;
- }
- friend bool operator!=(const CMasternode& a, const CMasternode& b)
- {
- return !(a.vin == b.vin);
+ addr = newAddr;
+ vin = newVin;
+ pubkey = newPubkey;
+ pubkey2 = newPubkey2;
+ sig = newSig;
+ now = newNow;
+ enabled = 1;
+ lastTimeSeen = 0;
+ unitTest = false;
+ cacheInputAge = 0;
+ cacheInputAgeBlock = 0;
+ nLastDsq = 0;
+ lastDseep = 0;
+ allowFreeTx = true;
+ protocolVersion = protocolVersionIn;
}
uint256 CalculateScore(int mod=1, int64_t nBlockHeight=0);
- IMPLEMENT_SERIALIZE
- (
- // serialized format:
- // * version byte (currently 0)
- // * all fields (?)
- {
- LOCK(cs);
- unsigned char nVersion = 0;
- READWRITE(nVersion);
- READWRITE(vin);
- READWRITE(addr);
- READWRITE(pubkey);
- READWRITE(pubkey2);
- READWRITE(sig);
- READWRITE(activeState);
- READWRITE(sigTime);
- READWRITE(lastDseep);
- READWRITE(lastTimeSeen);
- READWRITE(cacheInputAge);
- READWRITE(cacheInputAgeBlock);
- READWRITE(unitTest);
- READWRITE(allowFreeTx);
- READWRITE(protocolVersion);
- READWRITE(nLastDsq);
- READWRITE(donationAddress);
- READWRITE(donationPercentage);
- READWRITE(nVote);
- READWRITE(lastVote);
- READWRITE(nScanningErrorCount);
- READWRITE(nLastScanningErrorBlockHeight);
- READWRITE(nLastPaid);
- }
- )
-
- int64_t SecondsSincePayment()
- {
- return (GetAdjustedTime() - nLastPaid);
- }
-
void UpdateLastSeen(int64_t override=0)
{
if(override == 0){
@@ -195,6 +124,7 @@ class CMasternode
}
void Check();
+ std::string GetStatus();
bool UpdatedWithin(int seconds)
{
@@ -210,7 +140,7 @@ class CMasternode
bool IsEnabled()
{
- return activeState == MASTERNODE_ENABLED;
+ return enabled == 1;
}
int GetMasternodeInputAge()
@@ -224,18 +154,99 @@ class CMasternode
return cacheInputAge+(pindexBest->nHeight-cacheInputAgeBlock);
}
+};
+
+
+// Get the current winner for this block
+int GetCurrentMasterNode(int mod=1, int64_t nBlockHeight=0, int minProtocol=CMasterNode::minProtoVersion);
- std::string Status() {
- std::string strStatus = "ACTIVE";
+int GetMasternodeByVin(CTxIn& vin);
+int GetMasternodeRank(CTxIn& vin, int64_t nBlockHeight=0, int minProtocol=CMasterNode::minProtoVersion);
+int GetMasternodeByRank(int findRank, int64_t nBlockHeight=0, int minProtocol=CMasterNode::minProtoVersion);
- if(activeState == CMasternode::MASTERNODE_ENABLED) strStatus = "ENABLED";
- if(activeState == CMasternode::MASTERNODE_EXPIRED) strStatus = "EXPIRED";
- if(activeState == CMasternode::MASTERNODE_VIN_SPENT) strStatus = "VIN_SPENT";
- if(activeState == CMasternode::MASTERNODE_REMOVE) strStatus = "REMOVE";
- if(activeState == CMasternode::MASTERNODE_POS_ERROR) strStatus = "POS_ERROR";
- return strStatus;
+// for storing the winning payments
+class CMasternodePaymentWinner
+{
+public:
+ int nBlockHeight;
+ CTxIn vin;
+ CScript payee;
+ std::vector vchSig;
+ uint64_t score;
+
+ CMasternodePaymentWinner() {
+ nBlockHeight = 0;
+ score = 0;
+ vin = CTxIn();
+ payee = CScript();
}
+
+ uint256 GetHash(){
+ uint256 n2 = Hash(BEGIN(nBlockHeight), END(nBlockHeight));
+ uint256 n3 = vin.prevout.hash > n2 ? (vin.prevout.hash - n2) : (n2 - vin.prevout.hash);
+
+ return n3;
+ }
+
+ ADD_SERIALIZE_METHODS;
+
+ template
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion){
+ unsigned int nSerSize = 0;
+ READWRITE(nBlockHeight);
+ READWRITE(payee);
+ READWRITE(vin);
+ READWRITE(score);
+ READWRITE(vchSig);
+ }
};
+//
+// Masternode Payments Class
+// Keeps track of who should get paid for which blocks
+//
+
+class CMasternodePayments
+{
+private:
+ std::vector vWinning;
+ int nSyncedFromPeer;
+ std::string strMasterPrivKey;
+ std::string strTestPubKey;
+ std::string strMainPubKey;
+ bool enabled;
+
+public:
+
+ CMasternodePayments() {
+ strMainPubKey = "0430a870a5a1e8a85b816c64cb86d6aa4955134efe72c458246fb84cfd5221c111ee84dfc0dbf160d339415044259519eae2840ab3ffe86368f3f9a93ec22e3f4d";
+ strTestPubKey = "0430a870a5a1e8a85b816c64cb86d6aa4955134efe72c458246fb84cfd5221c111ee84dfc0dbf160d339415044259519eae2840ab3ffe86368f3f9a93ec22e3f4d";
+ enabled = false;
+ }
+
+ bool SetPrivKey(std::string strPrivKey);
+ bool CheckSignature(CMasternodePaymentWinner& winner);
+ bool Sign(CMasternodePaymentWinner& winner);
+
+ // Deterministically calculate a given "score" for a masternode depending on how close it's hash is
+ // to the blockHeight. The further away they are the better, the furthest will win the election
+ // and get paid this block
+ //
+
+ uint64_t CalculateScore(uint256 blockHash, CTxIn& vin);
+ bool GetWinningMasternode(int nBlockHeight, CTxIn& vinOut);
+ bool AddWinningMasternode(CMasternodePaymentWinner& winner);
+ bool ProcessBlock(int nBlockHeight);
+ void Relay(CMasternodePaymentWinner& winner);
+ void Sync(CNode* node);
+ void CleanPaymentList();
+ int LastPayment(CMasterNode& mn);
+
+ //slow
+ bool GetBlockPayee(int nBlockHeight, CScript& payee);
+};
+
+
+
#endif
diff --git a/src/masternodeconfig.cpp b/src/masternodeconfig.cpp
index 75b4bc47..4f32dd56 100644
--- a/src/masternodeconfig.cpp
+++ b/src/masternodeconfig.cpp
@@ -2,16 +2,15 @@
#include "net.h"
#include "masternodeconfig.h"
#include "util.h"
-#include
CMasternodeConfig masternodeConfig;
-void CMasternodeConfig::add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex, std::string donationAddress, std::string donationPercent) {
- CMasternodeEntry cme(alias, ip, privKey, txHash, outputIndex, donationAddress, donationPercent);
+void CMasternodeConfig::add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex) {
+ CMasternodeEntry cme(alias, ip, privKey, txHash, outputIndex);
entries.push_back(cme);
}
-bool CMasternodeConfig::read(boost::filesystem::path path) {
+bool CMasternodeConfig::read(std::string& strErr) {
boost::filesystem::ifstream streamConfig(GetMasternodeConfigFile());
if (!streamConfig.good()) {
return true; // No masternode.conf file is OK
@@ -23,35 +22,20 @@ bool CMasternodeConfig::read(boost::filesystem::path path) {
continue;
}
std::istringstream iss(line);
- std::string alias, ip, privKey, txHash, outputIndex, donation, donationAddress, donationPercent;
- if (!(iss >> alias >> ip >> privKey >> txHash >> outputIndex >> donation)) {
- donationAddress = "";
- donationPercent = "";
- iss.str(line);
- iss.clear();
- if (!(iss >> alias >> ip >> privKey >> txHash >> outputIndex)) {
- LogPrintf("Could not parse masternode.conf line: %s\n", line.c_str());
- streamConfig.close();
- return false;
- }
- } else {
- size_t pos = donation.find_first_of(":");
- if(pos == string::npos) { // no ":" found
- donationPercent = "100";
- donationAddress = donation;
- } else {
- donationPercent = donation.substr(pos + 1);
- donationAddress = donation.substr(0, pos);
- }
- CBitcoinAddress address(donationAddress);
- if (!address.IsValid()) {
- LogPrintf("Invalid Memetic address in masternode.conf line: %s\n", line.c_str());
- streamConfig.close();
- return false;
- }
+ std::string alias, ip, privKey, txHash, outputIndex;
+ if (!(iss >> alias >> ip >> privKey >> txHash >> outputIndex)) {
+ strErr = "Could not parse masternode.conf line: " + line;
+ streamConfig.close();
+ return false;
}
- add(alias, ip, privKey, txHash, outputIndex, donationAddress, donationPercent);
+/* if(CService(ip).GetPort() != 19999 && CService(ip).GetPort() != 9999) {
+ strErr = "Invalid port (must be 9999 for mainnet or 19999 for testnet) detected in masternode.conf: " + line;
+ streamConfig.close();
+ return false;
+ }*/
+
+ add(alias, ip, privKey, txHash, outputIndex);
}
streamConfig.close();
diff --git a/src/masternodeconfig.h b/src/masternodeconfig.h
index 747af476..c5afb68e 100644
--- a/src/masternodeconfig.h
+++ b/src/masternodeconfig.h
@@ -1,5 +1,5 @@
-
-// Copyright (c) 2014-2015 The Dash developers
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,95 +19,84 @@ class CMasternodeConfig
{
public:
-
- class CMasternodeEntry {
-
- private:
- std::string alias;
- std::string ip;
- std::string privKey;
- std::string txHash;
- std::string outputIndex;
- std::string donationAddress;
- std::string donationPercent;
- public:
-
- CMasternodeEntry(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex, std::string donationAddress, std::string donationPercent) {
- this->alias = alias;
- this->ip = ip;
- this->privKey = privKey;
- this->txHash = txHash;
- this->outputIndex = outputIndex;
- this->donationAddress = donationAddress;
- this->donationPercent = donationPercent;
- }
-
- const std::string& getAlias() const {
- return alias;
- }
-
- void setAlias(const std::string& alias) {
- this->alias = alias;
- }
-
- const std::string& getOutputIndex() const {
- return outputIndex;
- }
-
- void setOutputIndex(const std::string& outputIndex) {
- this->outputIndex = outputIndex;
- }
-
- const std::string& getPrivKey() const {
- return privKey;
- }
-
- void setPrivKey(const std::string& privKey) {
- this->privKey = privKey;
- }
-
- const std::string& getTxHash() const {
- return txHash;
- }
-
- void setTxHash(const std::string& txHash) {
- this->txHash = txHash;
- }
-
- const std::string& getIp() const {
- return ip;
- }
-
- void setIp(const std::string& ip) {
- this->ip = ip;
- }
-
- const std::string& getDonationAddress() const {
- return donationAddress;
- }
-
- const std::string& getDonationPercentage() const {
- return donationPercent;
- }
- };
-
- CMasternodeConfig() {
- entries = std::vector();
- }
-
- void clear();
- bool read(boost::filesystem::path path);
- void add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex, std::string donationAddress, std::string donationPercent);
-
- std::vector