diff --git a/README.md b/README.md index d341f29..786fff5 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ Website: https://mnpcoin.pro Utility: https://masternodes.pro +#### 01-24-19 +- Implemented fix for "fake staking" bug + #### 01-19-19 - Implemented BIP130 diff --git a/configure.ac b/configure.ac index b1d1f5c..cc6e5dd 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,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_REVISION, 1) +define(_CLIENT_VERSION_REVISION, 2) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2019) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 563f0b3..cd8f406 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -76,12 +76,20 @@ static Checkpoints::MapCheckpoints mapCheckpoints = ( 80000, uint256("49fb6da4cbc4e834312985bfa44b08537a4c4573bbca6a37626b46e66ea246d6")) ( 90000, uint256("4035ca075e6a5759d15edd9494fd925da415baec9058dd04664b119f7a319fe9")) ( 100000, uint256("0d593545ea7f76f3012d131da70b449218b24a0eaf88db661149b08589f8b925")) + ( 120000, uint256("da0954bd8915e44d2c6406bbd82a4e302b7f6620e457f73044a88897b418710e")) + ( 140000, uint256("669330f0b31e937d0ce0fc18f05de4eced1da84456bd5d72e34ba6ee69ff0d25")) + ( 160000, uint256("af8612d5c1c0beebd5cd168127dc6f27a025d4f9fdfedf8bca48551c144e9da1")) + ( 180000, uint256("ae972cd58079c9a26d5d68b8375ab2bf3e93789bddf2c3c1e48f4bd08bdd2565")) + ( 200000, uint256("b8f878e27bfee6eb63911ca0d85aa8c9c9666e4512dd8682b83d67d679f0b5c8")) + ( 220000, uint256("6d55a17c276ab12b14b6b8d13fb33e733613b25c600c220a457ed6a054c137cf")) + ( 240000, uint256("85469fe3a2b8130e163f1e0b1c324c405dc84f91a62d001de1cdbf465f056dcd")) + ( 248000, uint256("b7934ead9db1c2444e591060d46dfcbf1330ccba04524d1b46ef164b991adc9d")) ; static const Checkpoints::CCheckpointData data = { &mapCheckpoints, - 1539232472, // * UNIX timestamp of last checkpoint block - 194131, // * total number of transactions between genesis and last checkpoint + 1548362685, // * UNIX timestamp of last checkpoint block + 506447, // * total number of transactions between genesis and last checkpoint // (the tx=... number in the SetBestChain debug.log lines) 2000 // * estimated number of transactions per day after checkpoint }; @@ -301,11 +309,11 @@ class CTestNetParams : public CMainParams nBlockEnforceInvalidUTXO = 1600; //Start enforcing the invalid UTXO's //! Modify the testnet genesis block so the timestamp is valid for a later start. - genesis.nTime = 1535229300; // GMT: 2018-08-25T20:35:00.000Z - genesis.nNonce = 83001552; + genesis.nTime = 1547942400; // GMT: 2019-01-20T00:00:00.000Z + genesis.nNonce = 83435947; hashGenesisBlock = genesis.GetHash(); - if(genesis.GetHash() != uint256("00000c8d8a5dc8021a5d70eef326b71fd05360747169cfb4bd7ce7095c812139")) + if(genesis.GetHash() != uint256("00000bcb79d73d227ed5d0daf1d9f25b64b09978a14261c6b1a6318a1d80a4ef")) { printf("Searching for genesis block...\n"); uint256 hashTarget = CBigNum().SetCompact(genesis.nBits).getuint256(); @@ -328,14 +336,15 @@ class CTestNetParams : public CMainParams printf("block.GetHash = %s\n", genesis.GetHash().ToString().c_str()); printf("block.hashMerkleRoot = %s\n", genesis.hashMerkleRoot.ToString().c_str()); } - assert(hashGenesisBlock == uint256("00000c8d8a5dc8021a5d70eef326b71fd05360747169cfb4bd7ce7095c812139")); + assert(hashGenesisBlock == uint256("00000bcb79d73d227ed5d0daf1d9f25b64b09978a14261c6b1a6318a1d80a4ef")); vFixedSeeds.clear(); vSeeds.clear(); - vSeeds.push_back(CDNSSeedData("149.28.82.70", "149.28.82.70")); - vSeeds.push_back(CDNSSeedData("149.28.248.6", "149.28.248.6")); - vSeeds.push_back(CDNSSeedData("144.202.17.23", "144.202.17.23")); - vSeeds.push_back(CDNSSeedData("45.32.210.33", "45.32.210.33")); + vSeeds.push_back(CDNSSeedData("199.223.253.96", "199.223.253.96")); + vSeeds.push_back(CDNSSeedData("104.238.179.224", "104.238.179.224")); + vSeeds.push_back(CDNSSeedData("45.76.63.197", "45.76.63.197")); + vSeeds.push_back(CDNSSeedData("45.76.253.208", "45.76.253.208")); + vSeeds.push_back(CDNSSeedData("24.35.240.224", "24.35.240.224")); base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 88); // Testnet mnpcoin addresses start with 'w' base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 112); // Testnet mnpcoin script addresses start with '7' diff --git a/src/config/mnpcoin-config.h b/src/config/mnpcoin-config.h index b64e529..b3ecadb 100644 --- a/src/config/mnpcoin-config.h +++ b/src/config/mnpcoin-config.h @@ -21,7 +21,7 @@ #define CLIENT_VERSION_MINOR 2 /* Build revision */ -#define CLIENT_VERSION_REVISION 1 +#define CLIENT_VERSION_REVISION 2 /* Version is release */ #define COPYRIGHT_YEAR 2019 diff --git a/src/main.cpp b/src/main.cpp index cfd4c5f..10137d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,6 +63,7 @@ CCriticalSection cs_main; BlockMap mapBlockIndex; map mapProofOfStake; +map mapStakeSpent; set > setStakeSeen; map mapHashedBlocks; CChain chainActive; @@ -2739,6 +2740,10 @@ 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 + if(IsSporkActive(SPORK_17_FAKE_STAKE_FIX) && block.GetBlockTime() >= GetSporkValue(SPORK_17_FAKE_STAKE_FIX)) + mapStakeSpent.erase(out); } } } @@ -3310,6 +3315,27 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!pblocktree->WriteTxIndex(vPos)) return state.Abort("Failed to write transaction index"); + if(IsSporkActive(SPORK_17_FAKE_STAKE_FIX) && block.GetBlockTime() >= GetSporkValue(SPORK_17_FAKE_STAKE_FIX)){ + // add new entries + for (const CTransaction tx:block.vtx) { + if (tx.IsCoinBase()) + 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()); @@ -4566,6 +4592,57 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, int nHeight = pindex->nHeight; + if(IsSporkActive(SPORK_17_FAKE_STAKE_FIX) && block.GetBlockTime() >= GetSporkValue(SPORK_17_FAKE_STAKE_FIX)) { + + 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) && pindexPrev != 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 = pindexPrev->pprev; + } + } + } + } + // Write block to history file try { unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); diff --git a/src/spork.cpp b/src/spork.cpp index f35f788..93e8f32 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -128,6 +128,7 @@ int64_t GetSporkValue(int nSporkID) if (nSporkID == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) r = SPORK_14_NEW_PROTOCOL_ENFORCEMENT_DEFAULT; if (nSporkID == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) r = SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2_DEFAULT; if (nSporkID == SPORK_16_ZEROCOIN_MAINTENANCE_MODE) r = SPORK_16_ZEROCOIN_MAINTENANCE_MODE_DEFAULT; + if (nSporkID == SPORK_17_FAKE_STAKE_FIX) r = SPORK_17_FAKE_STAKE_FIX_DEFAULT; if (r == -1) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID); } diff --git a/src/spork.h b/src/spork.h index c4bc20e..fc641a3 100644 --- a/src/spork.h +++ b/src/spork.h @@ -42,6 +42,7 @@ using namespace boost; #define SPORK_14_NEW_PROTOCOL_ENFORCEMENT 10013 #define SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2 10014 #define SPORK_16_ZEROCOIN_MAINTENANCE_MODE 10015 +#define SPORK_17_FAKE_STAKE_FIX 10016 #define SPORK_2_SWIFTTX_DEFAULT 978307200 //2001-1-1 #define SPORK_3_SWIFTTX_BLOCK_FILTERING_DEFAULT 1424217600 //2015-2-18 @@ -55,6 +56,7 @@ using namespace boost; #define SPORK_14_NEW_PROTOCOL_ENFORCEMENT_DEFAULT 4070908800 //OFF #define SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2_DEFAULT 4070908800 //OFF #define SPORK_16_ZEROCOIN_MAINTENANCE_MODE_DEFAULT 4070908800 //OFF +#define SPORK_17_FAKE_STAKE_FIX_DEFAULT 4070908800 //OFF class CSporkMessage; class CSporkManager;