From c2fe447df2ccd8c49dfecca018523b2378e5cf03 Mon Sep 17 00:00:00 2001 From: barrystyle Date: Sat, 20 Feb 2021 06:58:45 +0800 Subject: [PATCH] implement supply accounting, max supply limit and associated rpc commands --- src/amount.h | 1 + src/chain.h | 11 +++++++++++ src/rpc/misc.cpp | 29 +++++++++++++++++++++++++++++ src/txdb.cpp | 3 +++ src/validation.cpp | 37 ++++++++++++++++++++++++++++++++++++- src/validation.h | 2 ++ 6 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/amount.h b/src/amount.h index 3cad29d4e..fb4ba0ec3 100644 --- a/src/amount.h +++ b/src/amount.h @@ -24,6 +24,7 @@ static const CAmount CENT = 1000000; * for the creation of coins out of thin air modification could lead to a fork. * */ static const CAmount MAX_MONEY = 21000000 * COIN; +static const CAmount MAX_SUPPLY = 350000000 * COIN; inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } #endif // BITCOIN_AMOUNT_H diff --git a/src/chain.h b/src/chain.h index ba96632fb..ebce6055f 100644 --- a/src/chain.h +++ b/src/chain.h @@ -213,6 +213,10 @@ class CBlockIndex uint32_t nBits; uint32_t nNonce; + // supply accounting + int64_t nMint; + int64_t nMoneySupply; + //! (memory only) Sequential id assigned to distinguish order in which blocks are received. int32_t nSequenceId; @@ -240,6 +244,9 @@ class CBlockIndex nTime = 0; nBits = 0; nNonce = 0; + + nMint = 0; + nMoneySupply = 0; } CBlockIndex() @@ -410,6 +417,10 @@ class CDiskBlockIndex : public CBlockIndex READWRITE(nTime); READWRITE(nBits); READWRITE(nNonce); + + // supply accounting + READWRITE(nMint); + READWRITE(nMoneySupply); } uint256 GetBlockHash() const diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index d7ff5d73f..b75c34fca 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -79,6 +79,33 @@ UniValue debug(const JSONRPCRequest& request) return "Debug mode: " + ListActiveLogCategoriesString(); } +UniValue currentsupply(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() > 0) + throw std::runtime_error( + "currentsupply\n" + "Display the current supply in LQX.\n" + ); + + LOCK(cs_main); + + CBlockIndex* pindex = chainActive.Tip(); + CAmount currentSupply = pindex->nMoneySupply; + + return (currentSupply / COIN); +} + +UniValue maxsupply(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() > 0) + throw std::runtime_error( + "maxsupply\n" + "Display the maximum allowable supply in LQX.\n" + ); + + return (MAX_SUPPLY / COIN); +} + UniValue mnsync(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) @@ -1218,6 +1245,8 @@ static const CRPCCommand commands[] = { "addressindex", "getaddressbalance", &getaddressbalance, {"addresses"} }, /* Dash features */ + { "lqx", "currentsupply", ¤tsupply, {} }, + { "lqx", "maxsupply", &maxsupply, {} }, { "lqx", "mnsync", &mnsync, {} }, { "lqx", "spork", &spork, {"arg0","value"} }, diff --git a/src/txdb.cpp b/src/txdb.cpp index b80210bd2..cccf3eede 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -440,6 +440,9 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, pindexNew->nNonce = diskindex.nNonce; pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; + // supply accounting + pindexNew->nMint = diskindex.nMint; + pindexNew->nMoneySupply = diskindex.nMoneySupply; if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString()); diff --git a/src/validation.cpp b/src/validation.cpp index e9a7a954e..6fc478b8d 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -249,6 +249,9 @@ CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; CBlockPolicyEstimator feeEstimator; CTxMemPool mempool(&feeEstimator); +CAmount getCurrentSupply(); +void setCurrentSupply(CAmount supply); + void CheckBlockIndex(const Consensus::Params& consensusParams); /** Constant stuff for coinbase transactions we create: */ @@ -1107,6 +1110,10 @@ NOTE: unlike bitcoin we are using PREVIOUS block height here, */ CAmount GetBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params& consensusParams, bool fSuperblockPartOnly) { + //! enforce supply max of 350mil + if (getCurrentSupply() >= MAX_SUPPLY) + return 0 * COIN; + if (nPrevHeight + 1 > consensusParams.nNewPaymentSchemaHeight) { CAmount baseSubsidy = 5 * COIN; @@ -2092,6 +2099,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl std::vector prevheights; CAmount nFees = 0; + CAmount nValueIn = 0; + CAmount nValueOut = 0; int nInputs = 0; unsigned int nSigOps = 0; blockundo.vtxundo.reserve(block.vtx.size() - 1); @@ -2111,12 +2120,16 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl nInputs += tx.vin.size(); - if (!tx.IsCoinBase()) + if (tx.IsCoinBase()) + nValueOut += tx.GetValueOut(); + else { CAmount txfee = 0; if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, txfee)) { return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state)); } + nValueIn += view.GetValueIn(tx); + nValueOut += tx.GetValueOut(); nFees += txfee; if (!MoneyRange(nFees)) { return state.DoS(100, error("%s: accumulated fee in the block out of range.", __func__), @@ -2323,6 +2336,11 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl if (fJustCheck) return true; + // peercoin: track money supply and mint amount info + pindex->nMint = nValueOut - nValueIn + nFees; + pindex->nMoneySupply = (pindex->pprev? pindex->pprev->nMoneySupply : 0) + nValueOut - nValueIn; + setCurrentSupply(pindex->nMoneySupply); + if (!WriteUndoDataForBlock(blockundo, state, pindex, chainparams)) return false; @@ -5019,6 +5037,23 @@ bool isCollateralValidNow(const CBlockIndex* pindexPrev, CAmount proCollateral) return false; } +int currentHeight() { + return chainActive.Height(); +} + +//! note; these are here simply to avoid having to bash through several locks +//! when getting a rough estimate for current supply at any given time +CAmount currentSupply{0}; + +CAmount getCurrentSupply() { + return currentSupply; +} + +void setCurrentSupply(CAmount supply) { + if (supply > currentSupply) + currentSupply = supply; +} + class CMainCleanup { public: diff --git a/src/validation.h b/src/validation.h index 51d9f48eb..759ee1cc0 100644 --- a/src/validation.h +++ b/src/validation.h @@ -496,4 +496,6 @@ bool LoadMempool(); bool isCollateralValidNow(const CBlockIndex* pindexPrev, CAmount proCollateral); +int currentHeight(); + #endif // BITCOIN_VALIDATION_H