set<pair<COutPoint, unsigned int> > setStakeSeen;
uint256 hashGenesisBlock = hashGenesisBlockOfficial;
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
-static CBigNum bnInitialHashTarget(~uint256(0) >> 36);
+static CBigNum bnInitialHashTarget(~uint256(0) >> 40);
CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
-uint64 nBestChainTrust = 0;
-uint64 nBestInvalidTrust = 0;
+CBigNum bnBestChainTrust = 0;
+CBigNum bnBestInvalidTrust = 0;
uint256 hashBestChain = 0;
CBlockIndex* pindexBest = NULL;
int64 nTimeBestReceived = 0;
void static InvalidChainFound(CBlockIndex* pindexNew)
{
- if (pindexNew->nChainTrust > nBestInvalidTrust)
+ if (pindexNew->bnChainTrust > bnBestInvalidTrust)
{
- nBestInvalidTrust = pindexNew->nChainTrust;
- CTxDB().WriteBestInvalidTrust(nBestInvalidTrust);
+ bnBestInvalidTrust = pindexNew->bnChainTrust;
+ CTxDB().WriteBestInvalidTrust(bnBestInvalidTrust);
MainFrameRepaint();
}
- printf("InvalidChainFound: invalid block=%s height=%d trust=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, CBigNum(pindexNew->nChainTrust).ToString().c_str());
- printf("InvalidChainFound: current best=%s height=%d trust=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).ToString().c_str());
+ printf("InvalidChainFound: invalid block=%s height=%d trust=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, CBigNum(pindexNew->bnChainTrust).ToString().c_str());
+ printf("InvalidChainFound: current best=%s height=%d trust=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(bnBestChainTrust).ToString().c_str());
// ppcoin: should not enter safe mode for longer invalid chain
}
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);
// Reorganize is costly in terms of db load, as it works in a single db transaction.
// Try to limit how much needs to be done inside
- while (pindexIntermediate->pprev && pindexIntermediate->pprev->nChainTrust > pindexBest->nChainTrust)
+ while (pindexIntermediate->pprev && pindexIntermediate->pprev->bnChainTrust > pindexBest->bnChainTrust)
{
vpindexSecondary.push_back(pindexIntermediate);
pindexIntermediate = pindexIntermediate->pprev;
hashBestChain = hash;
pindexBest = pindexNew;
nBestHeight = pindexBest->nHeight;
- nBestChainTrust = pindexNew->nChainTrust;
+ bnBestChainTrust = pindexNew->bnChainTrust;
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
- printf("SetBestChain: new best=%s height=%d trust=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).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", "");
}
// ppcoin: compute chain trust score
- uint64 nCoinAge;
- if (!GetCoinAge(nCoinAge))
- return error("AddToBlockIndex() : invalid transaction in block");
- pindexNew->nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + nCoinAge;
+ pindexNew->bnChainTrust = (pindexNew->pprev ? pindexNew->pprev->bnChainTrust : 0) + pindexNew->GetBlockTrust();
CTxDB txdb;
if (!txdb.TxnBegin())
return false;
// New best
- if (pindexNew->nChainTrust > nBestChainTrust)
+ if (pindexNew->bnChainTrust > bnBestChainTrust)
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);