From 095641f673ff5a453368dfb1495a4b8e5b324f82 Mon Sep 17 00:00:00 2001 From: Jordan Earls Date: Fri, 25 Aug 2017 17:37:39 -0400 Subject: [PATCH 1/2] Add money supply tracking and emergency assert for insane conditions --- src/chain.h | 4 ++++ src/rpc/misc.cpp | 1 + src/txdb.cpp | 1 + src/validation.cpp | 19 +++++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/src/chain.h b/src/chain.h index 1ed420d818..5cddacb21f 100644 --- a/src/chain.h +++ b/src/chain.h @@ -209,6 +209,7 @@ class CBlockIndex // proof-of-stake specific fields COutPoint prevoutStake; uint256 hashProof; // qtum + uint64_t nMoneySupply; //! (memory only) Sequential id assigned to distinguish order in which blocks are received. int32_t nSequenceId; @@ -244,6 +245,7 @@ class CBlockIndex nStakeModifier = uint256(); hashProof = uint256(); prevoutStake.SetNull(); + nMoneySupply = 0; } CBlockIndex() @@ -260,6 +262,7 @@ class CBlockIndex nTime = block.nTime; nBits = block.nBits; nNonce = block.nNonce; + nMoneySupply = 0; hashStateRoot = block.hashStateRoot; // qtum hashUTXORoot = block.hashUTXORoot; // qtum nStakeModifier = uint256(); @@ -418,6 +421,7 @@ class CDiskBlockIndex : public CBlockIndex READWRITE(VARINT(nDataPos)); if (nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(nUndoPos)); + READWRITE(VARINT(nMoneySupply)); // block header READWRITE(this->nVersion); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 795c1b40c0..eb13e6550c 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -99,6 +99,7 @@ UniValue getinfo(const JSONRPCRequest& request) diff.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBestHeader, true)))); obj.push_back(Pair("difficulty", diff)); obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET)); + obj.push_back(Pair("moneysupply", pindexBestHeader->nMoneySupply)); #ifdef ENABLE_WALLET if (pwalletMain) { obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); diff --git a/src/txdb.cpp b/src/txdb.cpp index 71fa8b7114..1d1d1e66a4 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -195,6 +195,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::functionnTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; pindexNew->nNonce = diskindex.nNonce; + pindexNew->nMoneySupply = diskindex.nMoneySupply; pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; pindexNew->hashStateRoot = diskindex.hashStateRoot; // qtum diff --git a/src/validation.cpp b/src/validation.cpp index ac979a5e23..9c80b9392f 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2579,6 +2579,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated uint64_t blockGasUsed = 0; CAmount gasRefunds=0; + + uint64_t nValueOut=0; + uint64_t nValueIn=0; + for (unsigned int i = 0; i < block.vtx.size(); i++) { const CTransaction &tx = *(block.vtx[i]); @@ -2645,6 +2649,15 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } } + if(tx.IsCoinBase()){ + nValueOut += tx.GetValueOut(); + }else{ + int64_t nTxValueIn = view.GetValueIn(tx); + int64_t nTxValueOut = tx.GetValueOut(); + nValueIn += nTxValueIn; + nValueOut += nTxValueOut; + } + ///////////////////////////////////////////////////////////////////////////////////////// qtum if(!tx.HasOpSpend()){ checkBlock.vtx.push_back(block.vtx[i]); @@ -2833,6 +2846,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } ////////////////////////////////////////////////////////////////// + pindex->nMoneySupply = (pindex->pprev? pindex->pprev->nMoneySupply : 0) + nValueOut - nValueIn; + //only start checking this assert after block 5000 and only on testnet and mainnet, not regtest + if(pindex->nHeight > 5000 && !Params().GetConsensus().fPoSNoRetargeting) { + //sanity check to shut down the network in case an exploit happens that allows new coins to be minted + assert(pindex->nMoneySupply < 100000000 + ((pindex->nHeight - 5000) * 4) * COIN); + } // Write undo information to disk if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) { From caeb5327e58b8a13041ef0a471d42414dd046953 Mon Sep 17 00:00:00 2001 From: Jordan Earls Date: Fri, 25 Aug 2017 18:08:06 -0400 Subject: [PATCH 2/2] Fix parens in assert, and make moneysupply display in COINS --- src/rpc/misc.cpp | 2 +- src/validation.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index eb13e6550c..7366854192 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -99,7 +99,7 @@ UniValue getinfo(const JSONRPCRequest& request) diff.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBestHeader, true)))); obj.push_back(Pair("difficulty", diff)); obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET)); - obj.push_back(Pair("moneysupply", pindexBestHeader->nMoneySupply)); + obj.push_back(Pair("moneysupply", pindexBestHeader->nMoneySupply / COIN)); #ifdef ENABLE_WALLET if (pwalletMain) { obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); diff --git a/src/validation.cpp b/src/validation.cpp index 9c80b9392f..2dc72450ed 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2850,7 +2850,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin //only start checking this assert after block 5000 and only on testnet and mainnet, not regtest if(pindex->nHeight > 5000 && !Params().GetConsensus().fPoSNoRetargeting) { //sanity check to shut down the network in case an exploit happens that allows new coins to be minted - assert(pindex->nMoneySupply < 100000000 + ((pindex->nHeight - 5000) * 4) * COIN); + assert(pindex->nMoneySupply <= (uint64_t)(100000000 + ((pindex->nHeight - 5000) * 4)) * COIN); } // Write undo information to disk if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS))