From: Sunny King Date: Thu, 23 Aug 2012 18:16:05 +0000 (+0100) Subject: PPCoin: Switch main chain protocol to score with proof-of-stake difficulty X-Git-Tag: v0.4.0-unstable~86 X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=4bb6099ac6e2554ab652eb89a0c71f6929184c87 PPCoin: Switch main chain protocol to score with proof-of-stake difficulty Upgrade requirement: backup wallet and redownload block chain --- diff --git a/src/db.cpp b/src/db.cpp index 04f400e..bc9c216 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -488,14 +488,14 @@ bool CTxDB::WriteHashBestChain(uint256 hashBestChain) return Write(string("hashBestChain"), hashBestChain); } -bool CTxDB::ReadBestInvalidTrust(uint64& nBestInvalidTrust) +bool CTxDB::ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust) { - return Read(string("nBestInvalidTrust"), nBestInvalidTrust); + return Read(string("bnBestInvalidTrust"), bnBestInvalidTrust); } -bool CTxDB::WriteBestInvalidTrust(uint64 nBestInvalidTrust) +bool CTxDB::WriteBestInvalidTrust(CBigNum bnBestInvalidTrust) { - return Write(string("nBestInvalidTrust"), nBestInvalidTrust); + return Write(string("bnBestInvalidTrust"), bnBestInvalidTrust); } bool CTxDB::ReadSyncCheckpoint(uint256& hashCheckpoint) @@ -577,7 +577,6 @@ bool CTxDB::LoadBlockIndex() pindexNew->pnext = InsertBlockIndex(diskindex.hashNext); pindexNew->nFile = diskindex.nFile; pindexNew->nBlockPos = diskindex.nBlockPos; - pindexNew->nChainTrust = diskindex.nChainTrust; pindexNew->nHeight = diskindex.nHeight; pindexNew->fProofOfStake = diskindex.fProofOfStake; pindexNew->prevoutStake = diskindex.prevoutStake; @@ -612,6 +611,21 @@ bool CTxDB::LoadBlockIndex() if (fRequestShutdown) return true; + // Calculate bnChainTrust + vector > vSortedByHeight; + vSortedByHeight.reserve(mapBlockIndex.size()); + BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + { + CBlockIndex* pindex = item.second; + vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); + } + sort(vSortedByHeight.begin(), vSortedByHeight.end()); + BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) + { + CBlockIndex* pindex = item.second; + pindex->bnChainTrust = (pindex->pprev ? pindex->pprev->bnChainTrust : 0) + pindex->GetBlockTrust(); + } + // Load hashBestChain pointer to end of best chain if (!ReadHashBestChain(hashBestChain)) { @@ -623,16 +637,16 @@ bool CTxDB::LoadBlockIndex() return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index"); pindexBest = mapBlockIndex[hashBestChain]; nBestHeight = pindexBest->nHeight; - nBestChainTrust = pindexBest->nChainTrust; - printf("LoadBlockIndex(): hashBestChain=%s height=%d trust=%d\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, nBestChainTrust); + bnBestChainTrust = pindexBest->bnChainTrust; + printf("LoadBlockIndex(): hashBestChain=%s height=%d trust=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str()); // ppcoin: load hashSyncCheckpoint if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint)) return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded"); printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str()); - // Load nBestInvalidTrust, OK if it doesn't exist - ReadBestInvalidTrust(nBestInvalidTrust); + // Load bnBestInvalidTrust, OK if it doesn't exist + ReadBestInvalidTrust(bnBestInvalidTrust); // Verify blocks in the best chain int nCheckLevel = GetArg("-checklevel", 1); diff --git a/src/db.h b/src/db.h index 792d5ca..db9fb8a 100644 --- a/src/db.h +++ b/src/db.h @@ -294,8 +294,8 @@ public: bool EraseBlockIndex(uint256 hash); bool ReadHashBestChain(uint256& hashBestChain); bool WriteHashBestChain(uint256 hashBestChain); - bool ReadBestInvalidTrust(uint64& nBestInvalidTrust); - bool WriteBestInvalidTrust(uint64 nBestInvalidTrust); + bool ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust); + bool WriteBestInvalidTrust(CBigNum bnBestInvalidTrust); bool ReadSyncCheckpoint(uint256& hashCheckpoint); bool WriteSyncCheckpoint(uint256 hashCheckpoint); bool ReadCheckpointPubKey(std::string& strPubKey); diff --git a/src/main.cpp b/src/main.cpp index 2a633f6..7b11741 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,8 +35,8 @@ static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32); 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; @@ -965,14 +965,14 @@ bool IsInitialBlockDownload() 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 } @@ -1597,7 +1597,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) // 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; @@ -1645,10 +1645,10 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) 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\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str()); std::string strCmd = GetArg("-blocknotify", ""); @@ -1818,10 +1818,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) } // 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()) @@ -1831,7 +1828,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) return false; // New best - if (pindexNew->nChainTrust > nBestChainTrust) + if (pindexNew->bnChainTrust > bnBestChainTrust) if (!SetBestChain(txdb, pindexNew)) return false; diff --git a/src/main.h b/src/main.h index 6ea3269..67bc8a7 100644 --- a/src/main.h +++ b/src/main.h @@ -63,8 +63,8 @@ extern std::set > setStakeSeen; extern uint256 hashGenesisBlock; extern CBlockIndex* pindexGenesisBlock; extern int nBestHeight; -extern uint64 nBestChainTrust; -extern uint64 nBestInvalidTrust; +extern CBigNum bnBestChainTrust; +extern CBigNum bnBestInvalidTrust; extern uint256 hashBestChain; extern CBlockIndex* pindexBest; extern unsigned int nTransactionsUpdated; @@ -1126,7 +1126,7 @@ public: CBlockIndex* pnext; unsigned int nFile; unsigned int nBlockPos; - uint64 nChainTrust;// ppcoin: trust score of chain, in the unit of coin-days + CBigNum bnChainTrust; // ppcoin: trust score of block chain int nHeight; bool fProofOfStake; // ppcoin: is the block of proof-of-stake type COutPoint prevoutStake; @@ -1148,7 +1148,7 @@ public: nFile = 0; nBlockPos = 0; nHeight = 0; - nChainTrust = 0; + bnChainTrust = 0; fProofOfStake = true; prevoutStake.SetNull(); nStakeTime = 0; @@ -1168,7 +1168,7 @@ public: nFile = nFileIn; nBlockPos = nBlockPosIn; nHeight = 0; - nChainTrust = 0; + bnChainTrust = 0; fProofOfStake = block.IsProofOfStake(); if (fProofOfStake) { @@ -1211,9 +1211,13 @@ public: return (int64)nTime; } - int64 GetBlockTrust() const + CBigNum GetBlockTrust() const { - return (nChainTrust - (pprev? pprev->nChainTrust : 0)); + CBigNum bnTarget; + bnTarget.SetCompact(nBits); + if (bnTarget <= 0) + return 0; + return (fProofOfStake? (CBigNum(1)<<256) / (bnTarget+1) : 1); } bool IsInMainChain() const @@ -1281,8 +1285,8 @@ public: std::string ToString() const { - return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nChainTrust=%"PRI64d" nHeight=%d, fProofOfStake=%d prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", - pprev, pnext, nFile, nBlockPos, nChainTrust, nHeight, + return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, fProofOfStake=%d prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", + pprev, pnext, nFile, nBlockPos, nHeight, fProofOfStake, prevoutStake.ToString().c_str(), nStakeTime, hashMerkleRoot.ToString().substr(0,10).c_str(), GetBlockHash().ToString().substr(0,20).c_str()); @@ -1323,7 +1327,6 @@ public: READWRITE(hashNext); READWRITE(nFile); READWRITE(nBlockPos); - READWRITE(nChainTrust); READWRITE(nHeight); READWRITE(fProofOfStake); if (fProofOfStake)