pindexNew->nBlockPos = diskindex.nBlockPos;
pindexNew->nChainTrust = diskindex.nChainTrust;
pindexNew->nHeight = diskindex.nHeight;
+ pindexNew->nCheckpoint = diskindex.nCheckpoint;
+ pindexNew->fProofOfStake = diskindex.fProofOfStake;
pindexNew->nVersion = diskindex.nVersion;
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
pindexNew->nTime = diskindex.nTime;
return bnResult.GetCompact();
}
-unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast)
+// ppcoin: find last block index up to pindex
+const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake)
+{
+ while (pindex && (pindex->IsProofOfStake() != fProofOfStake))
+ pindex = pindex->pprev;
+ return pindex;
+}
+
+unsigned int static GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
{
// Genesis block and first block
if (pindexLast == NULL || pindexLast->pprev == NULL)
return bnProofOfWorkLimit.GetCompact();
- int64 nActualSpacing = pindexLast->GetBlockTime() - pindexLast->pprev->GetBlockTime();
+ const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
+ if (pindexPrev == NULL)
+ return bnProofOfWorkLimit.GetCompact();
+ const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
+ if (pindexPrevPrev == NULL)
+ return bnProofOfWorkLimit.GetCompact();
+ int64 nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();
// ppcoin: target change every block
// ppcoin: retarget with exponential moving toward target spacing
int nHeight = pindexPrev->nHeight+1;
// Check proof of work
- if (nBits != GetNextWorkRequired(pindexPrev))
- return DoS(100, error("AcceptBlock() : incorrect proof of work"));
+ if (nBits != GetNextTargetRequired(pindexPrev, IsProofOfStake()))
+ return DoS(100, error("AcceptBlock() : incorrect proof-of-work/proof-of-stake"));
// Check timestamp against prev
if (GetBlockTime() <= pindexPrev->GetMedianTimePast() || GetBlockTime() + nMaxClockDrift < pindexPrev->GetBlockTime())
if (!pblock.get())
return NULL;
- pblock->nBits = GetNextWorkRequired(pindexPrev);
-
// Create coinbase tx
CTransaction txNew;
txNew.vin.resize(1);
pblock->vtx.push_back(txNew);
// ppcoin: if coinstake available add coinstake tx
+ pblock->nBits = GetNextTargetRequired(pindexPrev, true);
CTransaction txCoinStake;
if (pwallet->CreateCoinStake(txNew.vout[0].scriptPubKey, pblock->nBits, txCoinStake))
pblock->vtx.push_back(txCoinStake);
+ else
+ pblock->nBits = GetNextTargetRequired(pindexPrev, false);
// Collect memory pool transactions into the block
int64 nFees = 0;
uint64 nChainTrust;// ppcoin: trust score of chain, in the unit of coin-days
int nHeight;
int nCheckpoint; // ppcoin: chain auto checkpoint height
+ bool fProofOfStake; // ppcoin: is the block of proof-of-stake type
// block header
int nVersion;
nHeight = 0;
nChainTrust = 0;
nCheckpoint = 0;
+ fProofOfStake = true;
nVersion = 0;
hashMerkleRoot = 0;
nHeight = 0;
nChainTrust = 0;
nCheckpoint = 0;
+ fProofOfStake = block.IsProofOfStake();
nVersion = block.nVersion;
hashMerkleRoot = block.hashMerkleRoot;
return pindex->GetMedianTimePast();
}
+ bool IsProofOfWork() const
+ {
+ return !fProofOfStake;
+ }
+ bool IsProofOfStake() const
+ {
+ return fProofOfStake;
+ }
std::string ToString() const
{
- return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nChainTrust=%"PRI64d" nHeight=%d, nCheckpoint=%d, merkle=%s, hashBlock=%s)",
- pprev, pnext, nFile, nBlockPos, nChainTrust, nHeight, nCheckpoint,
+ return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nChainTrust=%"PRI64d" nHeight=%d, nCheckpoint=%d, fProofOfStake=%d merkle=%s, hashBlock=%s)",
+ pprev, pnext, nFile, nBlockPos, nChainTrust, nHeight, nCheckpoint, fProofOfStake,
hashMerkleRoot.ToString().substr(0,10).c_str(),
GetBlockHash().ToString().substr(0,20).c_str());
}
READWRITE(nChainTrust);
READWRITE(nHeight);
READWRITE(nCheckpoint);
+ READWRITE(fProofOfStake);
// block header
READWRITE(this->nVersion);