X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=20f499defc6b925a2f2e9c4d3f8903d1aadabc04;hb=f7e0391e3fc1cd71f62e6fa289cdea6b6093dc9b;hp=26e89f0ea0019e05e8daf8193aa61b824cfff78c;hpb=b22defc501d9eb8f227567fe2c7d279e243ba6be;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index 26e89f0..20f499d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -77,7 +77,7 @@ int64 nHPSTimerStart; // Settings int64 nTransactionFee = MIN_TX_FEE; - +bool fStakeUsePooledKeys = false; ////////////////////////////////////////////////////////////////////////////// // @@ -1104,13 +1104,10 @@ int64 inline GetTargetSpacingWorkMax(int nHeight, unsigned int nTime) } // -// minimum amount of work that could possibly be required nTime after -// minimum work required was nBase +// maximum nBits value could possible be required nTime after // -unsigned int ComputeMinWork(unsigned int nBase, int64 nTime) +unsigned int ComputeMaxBits(CBigNum bnTargetLimit, unsigned int nBase, int64 nTime) { - CBigNum bnTargetLimit = bnProofOfWorkLimit; - CBigNum bnResult; bnResult.SetCompact(nBase); bnResult *= 2; @@ -1125,6 +1122,25 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime) return bnResult.GetCompact(); } +// +// minimum amount of work that could possibly be required nTime after +// minimum proof-of-work required was nBase +// +unsigned int ComputeMinWork(unsigned int nBase, int64 nTime) +{ + return ComputeMaxBits(bnProofOfWorkLimit, nBase, nTime); +} + +// +// minimum amount of stake that could possibly be required nTime after +// minimum proof-of-stake required was nBase +// +unsigned int ComputeMinStake(unsigned int nBase, int64 nTime, unsigned int nBlockTime) +{ + return ComputeMaxBits(GetProofOfStakeLimit(0, nBlockTime), nBase, nTime); +} + + // ppcoin: find last block index up to pindex const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake) { @@ -2108,24 +2124,6 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) return DoS(100, error("CheckBlock() : size limits failed")); - // Special short-term limits to avoid 10,000 BDB lock limit: - if (GetBlockTime() < LOCKS_SWITCH_TIME) - { - // Rule is: #unique txids referenced <= 4,500 - // ... to prevent 10,000 BDB lock exhaustion on old clients - set setTxIn; - for (size_t i = 0; i < vtx.size(); i++) - { - setTxIn.insert(vtx[i].GetHash()); - if (i == 0) continue; // skip coinbase txin - BOOST_FOREACH(const CTxIn& txin, vtx[i].vin) - setTxIn.insert(txin.prevout.hash); - } - size_t nTxids = setTxIn.size(); - if (nTxids > 4500) - return error("CheckBlock() : maxlocks violation"); - } - // Check proof of work matches claimed amount if (fCheckPOW && IsProofOfWork() && !CheckProofOfWork(GetHash(), nBits)) return DoS(50, error("CheckBlock() : proof of work failed")); @@ -2263,18 +2261,9 @@ bool CBlock::AcceptBlock() if (!Checkpoints::CheckHardened(nHeight, hash)) return DoS(100, error("AcceptBlock() : rejected by hardened checkpoint lock-in at %d", nHeight)); - // ppcoin: check that the block satisfies synchronized checkpoint - if (!Checkpoints::CheckSync(hash, pindexPrev)) - { - if(!GetBoolArg("-nosynccheckpoints", false)) - { - return error("AcceptBlock() : rejected by synchronized checkpoint"); - } - else - { - strMiscWarning = _("WARNING: syncronized checkpoint violation detected, but skipped!"); - } - } + // Check that the block satisfies synchronized checkpoint + if (!GetBoolArg("-nosynccheckpoints", false) && !Checkpoints::CheckSync(hash, pindexPrev)) + return error("AcceptBlock() : rejected by synchronized checkpoint"); // Enforce rule that the coinbase starts with serialized block height CScript expect = CScript() << nHeight; @@ -2425,8 +2414,8 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) // ppcoin: verify hash target and signature of coinstake tx if (pblock->IsProofOfStake()) { - uint256 hashProofOfStake = 0; - if (!CheckProofOfStake(pblock->vtx[1], pblock->nBits, hashProofOfStake)) + uint256 hashProofOfStake = 0, targetProofOfStake = 0; + if (!CheckProofOfStake(pblock->vtx[1], pblock->nBits, hashProofOfStake, targetProofOfStake)) { printf("WARNING: ProcessBlock(): check proof-of-stake failed for block %s\n", hash.ToString().c_str()); return false; // do not error here as we expect this during initial block download @@ -2443,7 +2432,12 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) CBigNum bnNewBlock; bnNewBlock.SetCompact(pblock->nBits); CBigNum bnRequired; - bnRequired.SetCompact(ComputeMinWork(GetLastBlockIndex(pcheckpoint, pblock->IsProofOfStake())->nBits, deltaTime)); + + if (pblock->IsProofOfStake()) + bnRequired.SetCompact(ComputeMinStake(GetLastBlockIndex(pcheckpoint, true)->nBits, deltaTime, pblock->nTime)); + else + bnRequired.SetCompact(ComputeMinWork(GetLastBlockIndex(pcheckpoint, false)->nBits, deltaTime)); + if (bnNewBlock > bnRequired) { if (pfrom) @@ -2980,9 +2974,10 @@ string GetWarnings(string strFor) strStatusBar = strMiscWarning; } - // ppcoin: should not enter safe mode for longer invalid chain - // ppcoin: if sync-checkpoint is too old do not enter safe mode - if (Checkpoints::IsSyncCheckpointTooOld(60 * 60 * 24 * 10) && !fTestNet && !IsInitialBlockDownload()) + // * Should not enter safe mode for longer invalid chain + // * If sync-checkpoint is too old do not enter safe mode + // * Do not display warning if -nosynccheckpoints specified + if (!GetBoolArg("-nosynccheckpoints", false) && Checkpoints::IsSyncCheckpointTooOld(60 * 60 * 24 * 10) && !fTestNet && !IsInitialBlockDownload()) { nPriority = 100; strStatusBar = "WARNING: Checkpoint is too old. Wait for block chain to download, or notify developers."; @@ -3006,7 +3001,7 @@ string GetWarnings(string strFor) nPriority = alert.nPriority; strStatusBar = alert.strStatusBar; if (nPriority > 1000) - strRPC = strStatusBar; // ppcoin: safe mode for high alert + strRPC = strStatusBar; } } } @@ -4124,8 +4119,6 @@ public: // fProofOfStake: try (best effort) to make a proof-of-stake block CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake) { - CReserveKey reservekey(pwallet); - // Create new block auto_ptr pblock(new CBlock()); if (!pblock.get()) @@ -4136,7 +4129,14 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake) txNew.vin.resize(1); txNew.vin[0].prevout.SetNull(); txNew.vout.resize(1); - txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG; + + if (!fProofOfStake) + { + CReserveKey reservekey(pwallet); + txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG; + } + else + txNew.vout[0].SetEmpty(); // Add our coinbase tx as first transaction pblock->vtx.push_back(txNew); @@ -4146,10 +4146,6 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake) // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); - // Special compatibility rule before 20 Aug: limit size to 500,000 bytes: - if (GetAdjustedTime() < LOCKS_SWITCH_TIME) - nBlockMaxSize = std::min(nBlockMaxSize, (unsigned int)(MAX_BLOCK_SIZE_GEN)); - // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000); @@ -4185,7 +4181,6 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake) if (txCoinStake.nTime >= max(pindexPrev->GetMedianTimePast()+1, pindexPrev->GetBlockTime() - nMaxClockDrift)) { // make sure coinstake would meet timestamp protocol // as it would be the same as the block timestamp - pblock->vtx[0].vout[0].SetEmpty(); pblock->vtx[0].nTime = txCoinStake.nTime; pblock->vtx.push_back(txCoinStake); } @@ -4476,12 +4471,14 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) uint256 hash = pblock->GetHash(); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); - if (hash > hashTarget && pblock->IsProofOfWork()) - return error("BitcoinMiner : proof-of-work not meeting target"); + if(!pblock->IsProofOfWork()) + return error("CheckWork() : %s is not a proof-of-work block", hash.GetHex().c_str()); + + if (hash > hashTarget) + return error("CheckWork() : proof-of-work not meeting target"); //// debug print - printf("BitcoinMiner:\n"); - printf("new block found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str()); + printf("CheckWork() : new proof-of-stake block found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str()); pblock->print(); printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str()); @@ -4489,7 +4486,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) { LOCK(cs_main); if (pblock->hashPrevBlock != hashBestChain) - return error("BitcoinMiner : generated block is stale"); + return error("CheckWork() : generated block is stale"); // Remove key from key pool reservekey.KeepKey(); @@ -4502,24 +4499,60 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) // Process this block the same as if we had received it from another node if (!ProcessBlock(NULL, pblock)) - return error("BitcoinMiner : ProcessBlock, block not accepted"); + return error("CheckWork() : ProcessBlock, block not accepted"); + } + + return true; +} + +bool CheckStake(CBlock* pblock, CWallet& wallet) +{ + uint256 proofHash = 0, hashTarget = 0; + uint256 hash = pblock->GetHash(); + + if(!pblock->IsProofOfStake()) + return error("CheckStake() : %s is not a proof-of-stake block", hash.GetHex().c_str()); + + // verify hash target and signature of coinstake tx + if (!CheckProofOfStake(pblock->vtx[1], pblock->nBits, proofHash, hashTarget)) + return error("CheckStake() : proof-of-stake checking failed"); + + //// debug print + printf("CheckStake() : new proof-of-stake block found \n hash: %s \nproofhash: %s \ntarget: %s\n", hash.GetHex().c_str(), proofHash.GetHex().c_str(), hashTarget.GetHex().c_str()); + pblock->print(); + printf("out %s\n", FormatMoney(pblock->vtx[1].GetValueOut()).c_str()); + + // Found a solution + { + LOCK(cs_main); + if (pblock->hashPrevBlock != hashBestChain) + return error("CheckStake() : generated block is stale"); + + // Track how many getdata requests this block gets + { + LOCK(wallet.cs_wallet); + wallet.mapRequestCount[pblock->GetHash()] = 0; + } + + // Process this block the same as if we had received it from another node + if (!ProcessBlock(NULL, pblock)) + return error("CheckStake() : ProcessBlock, block not accepted"); } return true; } -void BitcoinMiner(CWallet *pwallet, bool fProofOfStake) +void StakeMiner(CWallet *pwallet) { SetThreadPriority(THREAD_PRIORITY_LOWEST); // Make this thread recognisable as the mining thread - RenameThread("bitcoin-miner"); + RenameThread("novacoin-miner"); - // Each thread has its own key and counter - CReserveKey reservekey(pwallet); + // Each thread has its own counter unsigned int nExtraNonce = 0; - while (fProofOfStake) + while (true) { if (fShutdown) return; @@ -4528,8 +4561,6 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake) Sleep(1000); if (fShutdown) return; - if (!fProofOfStake) - return; } while (pwallet->IsLocked()) @@ -4544,30 +4575,28 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake) // CBlockIndex* pindexPrev = pindexBest; - auto_ptr pblock(CreateNewBlock(pwallet, fProofOfStake)); + auto_ptr pblock(CreateNewBlock(pwallet, true)); if (!pblock.get()) return; IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce); - if (fProofOfStake) + if(pblock->IsProofOfStake()) { - // ppcoin: if proof-of-stake block found then process block - if (pblock->IsProofOfStake()) + // Trying to sign a block + if (!pblock->SignBlock(*pwalletMain)) { - if (!pblock->SignBlock(*pwalletMain)) - { - strMintWarning = strMintMessage; - continue; - } - strMintWarning = ""; - printf("StakeMiner : 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); + strMintWarning = strMintMessage; + continue; } - Sleep(500); - continue; + + strMintWarning = ""; + SetThreadPriority(THREAD_PRIORITY_NORMAL); + CheckStake(pblock.get(), *pwalletMain); + SetThreadPriority(THREAD_PRIORITY_LOWEST); } + + Sleep(500); + continue; } }