diff --git a/configure.ac b/configure.ac index 2a1cc6b..a8f0f36 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 1) -define(_CLIENT_VERSION_MINOR, 2) +define(_CLIENT_VERSION_MINOR, 3) define(_CLIENT_VERSION_REVISION, 0) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 9a8708f..bde1c89 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -472,7 +472,7 @@ vector CActiveMasternode::SelectCoinsMasternode() // Filter BOOST_FOREACH (const COutput& out, vCoins) { - if (out.tx->vout[out.i].nValue == 200000 * COIN) { //exactly + if (out.tx->vout[out.i].nValue == GetMstrNodCollateral(chainActive.Height()) * COIN) { //exactly filteredCoins.push_back(out); } } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1ba20be..04b6eae 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -152,10 +152,8 @@ class CMainParams : public CChainParams vFixedSeeds.clear(); vSeeds.clear(); - vSeeds.push_back(CDNSSeedData("149.28.16.126", "149.28.16.126")); - vSeeds.push_back(CDNSSeedData("149.28.158.146", "149.28.158.146")); - vSeeds.push_back(CDNSSeedData("149.28.158.224", "149.28.158.224")); - vSeeds.push_back(CDNSSeedData("149.28.158.213", "149.28.158.213")); + vSeeds.push_back(CDNSSeedData("149.28.208.172", "149.28.208.172")); + vSeeds.push_back(CDNSSeedData("45.77.213.145", "45.77.213.145")); base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 75); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 80); diff --git a/src/clientversion.h b/src/clientversion.h index 789322e..41ce18f 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -16,7 +16,7 @@ //! These need to be macros, as clientversion.cpp's and indinode*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 1 -#define CLIENT_VERSION_MINOR 2 +#define CLIENT_VERSION_MINOR 3 #define CLIENT_VERSION_REVISION 0 #define CLIENT_VERSION_BUILD 0 diff --git a/src/main.cpp b/src/main.cpp index 22a6477..d0b1313 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,6 +64,7 @@ CCriticalSection cs_main; BlockMap mapBlockIndex; map mapProofOfStake; set > setStakeSeen; +map mapStakeSpent; map mapHashedBlocks; CChain chainActive; CBlockIndex* pindexBestHeader = NULL; @@ -2125,16 +2126,12 @@ int64_t GetBlockValue(int nHeight) nSubsidy = 150000000 * COIN; } else if (nHeight < 100001) { nSubsidy = 10 * COIN; - } else if (nHeight < 518400) { + } else if (nHeight < 400000) { nSubsidy = 2500 * COIN; - } else if (nHeight < 1036800) { - nSubsidy = 750 * COIN; - } else if (nHeight < 1555200) { - nSubsidy = 350 * COIN; } else { - nSubsidy = 150 * COIN; + nSubsidy = 250 * COIN; } - + // Check if we reached the coin max supply. int64_t nMoneySupply = chainActive.Tip()->nMoneySupply; @@ -2534,6 +2531,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex if (coins->vout.size() < out.n + 1) coins->vout.resize(out.n + 1); coins->vout[out.n] = undo.txout; + // erase the spent input + mapStakeSpent.erase(out); } } } @@ -3007,6 +3006,29 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (fTxIndex) if (!pblocktree->WriteTxIndex(vPos)) return state.Abort("Failed to write transaction index"); + + // add new entries + for (const CTransaction tx: block.vtx) { + if (tx.IsCoinBase() || tx.IsZerocoinSpend()) + continue; + for (const CTxIn in: tx.vin) { + LogPrint("map", "mapStakeSpent: Insert %s | %u\n", in.prevout.ToString(), pindex->nHeight); + mapStakeSpent.insert(std::make_pair(in.prevout, pindex->nHeight)); + } + } + + + // delete old entries + for (auto it = mapStakeSpent.begin(); it != mapStakeSpent.end();) { + if (it->second < pindex->nHeight - Params().MaxReorganizationDepth()) { + LogPrint("map", "mapStakeSpent: Erase %s | %u\n", it->first.ToString(), it->second); + it = mapStakeSpent.erase(it); + } + else { + it++; + } + } + // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); @@ -4173,6 +4195,55 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, } int nHeight = pindex->nHeight; + + if (block.IsProofOfStake()) { + LOCK(cs_main); + + CCoinsViewCache coins(pcoinsTip); + + if (!coins.HaveInputs(block.vtx[1])) { + // the inputs are spent at the chain tip so we should look at the recently spent outputs + + for (CTxIn in : block.vtx[1].vin) { + auto it = mapStakeSpent.find(in.prevout); + if (it == mapStakeSpent.end()) { + return false; + } + if (it->second < pindexPrev->nHeight) { + return false; + } + } + } + + // if this is on a fork + if (!chainActive.Contains(pindexPrev) && pindexPrev != NULL) { + // start at the block we're adding on to + CBlockIndex *last = pindexPrev; + + // while that block is not on the main chain + while (!chainActive.Contains(last) && last != NULL) { + CBlock bl; + ReadBlockFromDisk(bl, last); + // loop through every spent input from said block + for (CTransaction t : bl.vtx) { + for (CTxIn in: t.vin) { + // loop through every spent input in the staking transaction of the new block + for (CTxIn stakeIn : block.vtx[1].vin) { + // if they spend the same input + if (stakeIn.prevout == in.prevout) { + // reject the block + return false; + } + } + } + } + + // go to the parent block + last = last->pprev; + } + } + } + // Write block to history file try { diff --git a/src/main.h b/src/main.h index 74f8a1c..490163f 100644 --- a/src/main.h +++ b/src/main.h @@ -57,6 +57,18 @@ class CValidationState; struct CBlockTemplate; struct CNodeStateStats; +inline int64_t GetMstrNodCollateral(int nHeight) +{ + if(nHeight < 350000) + { + return 200000; + } + else + { + return 1000000; + } +} + /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; diff --git a/src/masternode.cpp b/src/masternode.cpp index 213ee71..683c90f 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -211,7 +211,7 @@ void CMasternode::Check(bool forceCheck) if (!unitTest) { CValidationState state; CMutableTransaction tx = CMutableTransaction(); - CTxOut vout = CTxOut(199999.99 * COIN, obfuScationPool.collateralPubKey); + CTxOut vout = CTxOut((GetMstrNodCollateral(chainActive.Height())-0.01) * COIN, obfuScationPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); @@ -571,7 +571,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) CValidationState state; CMutableTransaction tx = CMutableTransaction(); - CTxOut vout = CTxOut(199999.99 * COIN, obfuScationPool.collateralPubKey); + CTxOut vout = CTxOut((GetMstrNodCollateral(chainActive.Height())-0.01) * COIN, obfuScationPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 4f4758c..b0af2c9 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -986,7 +986,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData CValidationState state; CMutableTransaction tx = CMutableTransaction(); - CTxOut vout = CTxOut(199999.99 * COIN, obfuScationPool.collateralPubKey); + CTxOut vout = CTxOut((GetMstrNodCollateral(chainActive.Height())-0.01) * COIN, obfuScationPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); diff --git a/src/obfuscation.cpp b/src/obfuscation.cpp index d3a9c95..0c8766d 100644 --- a/src/obfuscation.cpp +++ b/src/obfuscation.cpp @@ -2111,7 +2111,7 @@ bool CObfuScationSigner::IsVinAssociatedWithPubkey(CTxIn& vin, CPubKey& pubkey) uint256 hash; if (GetTransaction(vin.prevout.hash, txVin, hash, true)) { BOOST_FOREACH (CTxOut out, txVin.vout) { - if (out.nValue == 200000 * COIN) { + if (out.nValue == GetMstrNodCollateral(chainActive.Height()) * COIN) { if (out.scriptPubKey == payee2) return true; } } diff --git a/src/pow.cpp b/src/pow.cpp index cfd2630..5d1196c 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -32,10 +32,18 @@ unsigned int static DarkGravityWave(const CBlockIndex* pindexLast) if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) { return Params().ProofOfWorkLimit().GetCompact(); } - + if (pindexLast->nHeight > Params().LAST_POW_BLOCK()) { uint256 bnTargetLimit = (~uint256(0) >> 24); - int64_t nTargetSpacing = 60; + + int64_t nTargetSpacing = 60; + + if (pindexLast->nHeight < 350000) { + int64_t nTargetSpacing = 60; + } else { + int64_t nTargetSpacing = 60 * 3; + } + int64_t nTargetTimespan = 60 * 40; int64_t nActualSpacing = 0; diff --git a/src/version.h b/src/version.h index fb3a334..08d7353 100644 --- a/src/version.h +++ b/src/version.h @@ -12,7 +12,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 70014; +static const int PROTOCOL_VERSION = 70015; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; @@ -22,7 +22,7 @@ static const int GETHEADERS_VERSION = 70000; //! disconnect from peers older than this proto version static const int MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT = 70004; -static const int MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT = 70014; +static const int MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT = 70015; //! nTime field added to CAddress, starting with this version; //! if possible, avoid requesting addresses nodes older than this diff --git a/src/wallet.cpp b/src/wallet.cpp index f863dc8..5ae6721 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1625,13 +1625,13 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const if (nCoinType == ONLY_DENOMINATED) { found = IsDenominatedAmount(pcoin->vout[i].nValue); } else if (nCoinType == ONLY_NOT10000IFMN) { - found = !(fMasterNode && pcoin->vout[i].nValue == 200000 * COIN); + found = !(fMasterNode && pcoin->vout[i].nValue == GetMstrNodCollateral(chainActive.Height()) * COIN); } else if (nCoinType == ONLY_NONDENOMINATED_NOT10000IFMN) { if (IsCollateralAmount(pcoin->vout[i].nValue)) continue; // do not use collateral amounts found = !IsDenominatedAmount(pcoin->vout[i].nValue); - if (found && fMasterNode) found = pcoin->vout[i].nValue != 200000 * COIN; // do not use Hot MN funds + if (found && fMasterNode) found = pcoin->vout[i].nValue != GetMstrNodCollateral(chainActive.Height()) * COIN; // do not use Hot MN funds } else if (nCoinType == ONLY_10000) { - found = pcoin->vout[i].nValue == 200000 * COIN; + found = pcoin->vout[i].nValue == GetMstrNodCollateral(chainActive.Height()) * COIN; } else { found = true; }