X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=e229063ac64503c70aac01fc8c31a6ad124f277c;hb=a350e812fc913378759c61bd06cde1b749a3fb0d;hp=fc7ae08b97ff0fd8dfa9205a9ffd1731edec0bf9;hpb=842acb70ed327ed76124758782825c0ce340141d;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index fc7ae08..e229063 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -731,13 +731,27 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 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 @@ -1526,9 +1540,18 @@ bool CBlock::AcceptBlock() CBlockIndex* pindexPrev = (*mi).second; int nHeight = pindexPrev->nHeight+1; - // Check proof of work - if (nBits != GetNextWorkRequired(pindexPrev)) - return DoS(100, error("AcceptBlock() : incorrect proof of work")); + // ppcoin: check for coinstake duplicate + if (IsProofOfStake()) + { // check if coinstake is already connected; that would imply the owner + // of the coinstake sent multiple blocks with the same coinstake + CTxIndex txindex; + if (CTxDB("r").ReadTxIndex(vtx[1].GetHash(), txindex)) + return error("AcceptBlock() : block %s has duplicate coinstake %s", hash.ToString().c_str(), vtx[1].GetHash().ToString().c_str()); + } + + // Check proof-of-work or proof-of-stake + 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()) @@ -1594,7 +1617,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) bnNewBlock.SetCompact(pblock->nBits); CBigNum bnRequired; bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); - if (bnNewBlock > bnRequired) + if (pblock->IsProofOfWork() && bnNewBlock > bnRequired) { pfrom->Misbehaving(100); return error("ProcessBlock() : block with too little proof-of-work"); @@ -2969,9 +2992,25 @@ CBlock* CreateNewBlock(CWallet* pwallet) pblock->vtx.push_back(txNew); // ppcoin: if coinstake available add coinstake tx - CTransaction txCoinStake; - if (pwallet->CreateCoinStake(txNew.vout[0].scriptPubKey, txCoinStake)) - pblock->vtx.push_back(txCoinStake); + static unsigned int nLastCoinStakeCheckTime = GetAdjustedTime() - nMaxClockDrift; // only initialized at startup + pblock->nBits = GetNextTargetRequired(pindexPrev, true); + while (nLastCoinStakeCheckTime < GetAdjustedTime()) + { + static CCriticalSection cs; + CTransaction txCoinStake; + CRITICAL_BLOCK(cs) + { + nLastCoinStakeCheckTime++; + txCoinStake.nTime = nLastCoinStakeCheckTime; + } + if (pwallet->CreateCoinStake(txNew.vout[0].scriptPubKey, pblock->nBits, txCoinStake)) + { + pblock->vtx.push_back(txCoinStake); + break; + } + } + if (pblock->IsProofOfWork()) + pblock->nBits = GetNextTargetRequired(pindexPrev, false); // Collect memory pool transactions into the block int64 nFees = 0; @@ -3092,7 +3131,6 @@ CBlock* CreateNewBlock(CWallet* pwallet) } } } - pblock->nBits = GetNextWorkRequired(pindexPrev); pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward(pblock->nBits); // Fill in header @@ -3173,12 +3211,12 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) uint256 hash = pblock->GetHash(); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); - if (hash > hashTarget) - return false; + if (hash > hashTarget && pblock->IsProofOfWork()) + return error("BitcoinMiner : proof-of-work not meeting target"); //// debug print printf("BitcoinMiner:\n"); - printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str()); + printf("new block found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str()); pblock->print(); printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str()); printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str()); @@ -3240,6 +3278,19 @@ void static BitcoinMiner(CWallet *pwallet) auto_ptr pblock(CreateNewBlock(pwallet)); if (!pblock.get()) return; + + // ppcoin: if proof-of-stake block found then process block + if (pblock->IsProofOfStake()) + { + // should be able to sign block - assert here for now + assert(pblock->SignBlock(*pwalletMain)); + printf("BitcoinMiner : proof-of-stake block found %s\n", pblock->GetHash().ToString().c_str()); + SetThreadPriority(THREAD_PRIORITY_NORMAL); + CheckWork(pblock.get(), *pwalletMain, reservekey); + SetThreadPriority(THREAD_PRIORITY_LOWEST); + continue; + } + IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce); printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size());