map<uint256, CTxIndex> mapQueuedChanges;
int64 nFees = 0;
+ int64 nValueIn = 0;
+ int64 nValueOut = 0;
unsigned int nSigOps = 0;
BOOST_FOREACH(CTransaction& tx, vtx)
{
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))
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;
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<uint256, CTxIndex>::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi)
{
// 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);
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", "");
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)
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
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)
{
// 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);
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;
nBlockPos = 0;
nHeight = 0;
bnChainTrust = 0;
+ nMint = 0;
+ nMoneySupply = 0;
fProofOfStake = true;
prevoutStake.SetNull();
nStakeTime = 0;
nBlockPos = nBlockPosIn;
nHeight = 0;
bnChainTrust = 0;
+ nMint = 0;
+ nMoneySupply = 0;
fProofOfStake = block.IsProofOfStake();
if (fProofOfStake)
{
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());
READWRITE(nFile);
READWRITE(nBlockPos);
READWRITE(nHeight);
+ READWRITE(nMint);
+ READWRITE(nMoneySupply);
READWRITE(fProofOfStake);
if (fProofOfStake)
{