From 2a4202a1545f86a78afc41d5641ed596f90356b2 Mon Sep 17 00:00:00 2001 From: Sunny King Date: Thu, 23 Aug 2012 23:29:44 +0100 Subject: [PATCH] PPCoin: Fix coinbase mint checks Track mint amount and money supply Upgrade Requirement: backup wallet and redownload block chain --- src/bitcoinrpc.cpp | 1 + src/db.cpp | 2 ++ src/main.cpp | 38 +++++++++++++++++++++++++++++++------- src/main.h | 11 ++++++++++- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 61f09c6..e1f2285 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -345,6 +345,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint()))); obj.push_back(Pair("stake", ValueFromAmount(pwalletMain->GetStake()))); obj.push_back(Pair("blocks", (int)nBestHeight)); + obj.push_back(Pair("moneysupply", ValueFromAmount(pindexBest->nMoneySupply))); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); diff --git a/src/db.cpp b/src/db.cpp index bc9c216..e8c066a 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -578,6 +578,8 @@ bool CTxDB::LoadBlockIndex() pindexNew->nFile = diskindex.nFile; pindexNew->nBlockPos = diskindex.nBlockPos; pindexNew->nHeight = diskindex.nHeight; + pindexNew->nMint = diskindex.nMint; + pindexNew->nMoneySupply = diskindex.nMoneySupply; pindexNew->fProofOfStake = diskindex.fProofOfStake; pindexNew->prevoutStake = diskindex.prevoutStake; pindexNew->nVersion = diskindex.nVersion; diff --git a/src/main.cpp b/src/main.cpp index 7b11741..2be1fef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1369,6 +1369,8 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) map mapQueuedChanges; int64 nFees = 0; + int64 nValueIn = 0; + int64 nValueOut = 0; unsigned int nSigOps = 0; BOOST_FOREACH(CTransaction& tx, vtx) { @@ -1380,7 +1382,9 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); MapPrevTx mapInputs; - if (!tx.IsCoinBase()) + if (tx.IsCoinBase()) + nValueOut += tx.GetValueOut(); + else { bool fInvalid; if (!tx.FetchInputs(txdb, mapQueuedChanges, true, false, mapInputs, fInvalid)) @@ -1396,8 +1400,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) return DoS(100, error("ConnectBlock() : too many sigops")); } + int64 nTxValueIn = tx.GetValueIn(mapInputs); + int64 nTxValueOut = tx.GetValueOut(); + nValueIn += nTxValueIn; + nValueOut += nTxValueOut; if (!tx.IsCoinStake()) - nFees += tx.GetValueIn(mapInputs)-tx.GetValueOut(); + nFees += nTxValueIn - nTxValueOut; if (!tx.ConnectInputs(txdb, mapInputs, mapQueuedChanges, posThisTx, pindex, true, false, fStrictPayToScriptHash)) return false; @@ -1406,6 +1414,10 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) mapQueuedChanges[tx.GetHash()] = CTxIndex(posThisTx, tx.vout.size()); } + // ppcoin: track money supply + pindex->nMint = nValueOut - nValueIn + nFees; + pindex->nMoneySupply = (pindex->pprev? pindex->pprev->nMoneySupply : 0) + nValueOut - nValueIn; + // Write queued txindex changes for (map::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi) { @@ -1415,8 +1427,6 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) // ppcoin: fees are not collected by miners as in bitcoin // ppcoin: fees are destroyed to compensate the entire network - if (IsProofOfWork() && vtx[0].GetValueOut() > GetProofOfWorkReward(nBits)) - return false; if (fDebug && GetBoolArg("-printcreation")) printf("ConnectBlock() : destroy=%s nFees=%"PRI64d"\n", FormatMoney(nFees).c_str(), nFees); @@ -1648,7 +1658,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) bnBestChainTrust = pindexNew->bnChainTrust; nTimeBestReceived = GetTime(); nTransactionsUpdated++; - printf("SetBestChain: new best=%s height=%d trust=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str()); + printf("SetBestChain: new best=%s height=%d trust=%s moneysupply=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str(), FormatMoney(pindexBest->nMoneySupply).c_str()); std::string strCmd = GetArg("-blocknotify", ""); @@ -1832,6 +1842,13 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) if (!SetBestChain(txdb, pindexNew)) return false; + // ppcoin: got mint/moneysupply info in block index, write to db + if (!txdb.TxnBegin()) + return false; + txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew)); + if (!txdb.TxnCommit()) + return false; + txdb.Close(); if (pindexNew == pindexBest) @@ -1879,7 +1896,7 @@ bool CBlock::CheckBlock() const return DoS(100, error("CheckBlock() : coinstake in wrong position")); // ppcoin: coinbase output should be empty if proof-of-stake block - if (IsProofOfStake() && !vtx[0].vout[0].IsEmpty()) + if (IsProofOfStake() && (vtx[0].vout.size() != 1 || !vtx[0].vout[0].IsEmpty())) return error("CheckBlock() : coinbase output not empty for proof-of-stake block"); // Check coinbase timestamp @@ -1890,6 +1907,12 @@ bool CBlock::CheckBlock() const if (IsProofOfStake() && GetBlockTime() > (int64)vtx[1].nTime + nMaxClockDrift) return DoS(50, error("CheckBlock() : coinstake timestamp is too early")); + // Check coinbase reward + if (vtx[0].GetValueOut() > (IsProofOfWork()? GetProofOfWorkReward(nBits) : 0)) + return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", + FormatMoney(vtx[0].GetValueOut()).c_str(), + FormatMoney(IsProofOfWork()? GetProofOfWorkReward(nBits) : 0).c_str())); + // Check transactions BOOST_FOREACH(const CTransaction& tx, vtx) { @@ -2361,13 +2384,14 @@ void PrintBlockTree() // print item CBlock block; block.ReadFromDisk(pindex); - printf("%d (%u,%u) %s %08lx %s tx %d", + printf("%d (%u,%u) %s %08lx %s mint %s tx %d", pindex->nHeight, pindex->nFile, pindex->nBlockPos, block.GetHash().ToString().substr(0,20).c_str(), block.nBits, DateTimeStrFormat(block.GetBlockTime()).c_str(), + FormatMoney(pindex->nMint).c_str(), block.vtx.size()); PrintWallets(block); diff --git a/src/main.h b/src/main.h index 67bc8a7..43a8b70 100644 --- a/src/main.h +++ b/src/main.h @@ -1128,6 +1128,8 @@ public: unsigned int nBlockPos; CBigNum bnChainTrust; // ppcoin: trust score of block chain int nHeight; + int64 nMint; + int64 nMoneySupply; bool fProofOfStake; // ppcoin: is the block of proof-of-stake type COutPoint prevoutStake; unsigned int nStakeTime; @@ -1149,6 +1151,8 @@ public: nBlockPos = 0; nHeight = 0; bnChainTrust = 0; + nMint = 0; + nMoneySupply = 0; fProofOfStake = true; prevoutStake.SetNull(); nStakeTime = 0; @@ -1169,6 +1173,8 @@ public: nBlockPos = nBlockPosIn; nHeight = 0; bnChainTrust = 0; + nMint = 0; + nMoneySupply = 0; fProofOfStake = block.IsProofOfStake(); if (fProofOfStake) { @@ -1285,8 +1291,9 @@ public: std::string ToString() const { - return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, fProofOfStake=%d prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", + return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, nMint=%s, nMoneySupply=%s, fProofOfStake=%d prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", pprev, pnext, nFile, nBlockPos, nHeight, + FormatMoney(nMint).c_str(), FormatMoney(nMoneySupply).c_str(), fProofOfStake, prevoutStake.ToString().c_str(), nStakeTime, hashMerkleRoot.ToString().substr(0,10).c_str(), GetBlockHash().ToString().substr(0,20).c_str()); @@ -1328,6 +1335,8 @@ public: READWRITE(nFile); READWRITE(nBlockPos); READWRITE(nHeight); + READWRITE(nMint); + READWRITE(nMoneySupply); READWRITE(fProofOfStake); if (fProofOfStake) { -- 1.7.1