X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=e8b8c61614e141e08621e9e378e3b44ebf76493e;hb=16580f9e77f54d9fcbf53a9af99c26d1e3eea5d3;hp=e99e95f75c05f228071a4e2ec20ccc1ec6e99b12;hpb=b0847bc4b54229f1f16494a44aae00057f2a2d52;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index e99e95f..e8b8c61 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,14 +52,13 @@ map > mapOrphanTransactionsByPrev; // Constant stuff for coinbase transactions we create: CScript COINBASE_FLAGS; -const string strMessageMagic = "Bitcoin Signed Message:\n"; +const string strMessageMagic = "PPCoin Signed Message:\n"; double dHashesPerSec; int64 nHPSTimerStart; // Settings int64 nTransactionFee = MIN_TX_FEE; -int64 nBalanceReserve = 0; @@ -456,8 +455,9 @@ bool CTransaction::CheckTransaction() const const CTxOut& txout = vout[i]; if (txout.IsEmpty() && (!IsCoinBase()) && (!IsCoinStake())) return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction")); - if (txout.nValue < 0) - return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue negative")); + // ppcoin: enforce minimum output amount + if ((!txout.IsEmpty()) && txout.nValue < MIN_TXOUT_AMOUNT) + return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue below minimum")); if (txout.nValue > MAX_MONEY) return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high")); nValueOut += txout.nValue; @@ -823,7 +823,7 @@ uint256 WantedByOrphan(const CBlock* pblockOrphan) int64 static GetProofOfWorkReward(unsigned int nBits) { - CBigNum bnSubsidyLimit = 9999 * COIN; // subsidy amount for difficulty 1 + CBigNum bnSubsidyLimit = MAX_MINT_PROOF_OF_WORK; CBigNum bnTarget; bnTarget.SetCompact(nBits); CBigNum bnTargetLimit = bnProofOfWorkLimit; @@ -891,7 +891,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime) // ppcoin: find last block index up to pindex const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake) { - while (pindex && (pindex->IsProofOfStake() != fProofOfStake)) + while (pindex && pindex->pprev && (pindex->IsProofOfStake() != fProofOfStake)) pindex = pindex->pprev; return pindex; } @@ -972,8 +972,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) } 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()); - if (pindexBest && nBestInvalidTrust > nBestChainTrust + pindexBest->GetBlockTrust() * 6) - printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n"); + // ppcoin: should not enter safe mode for longer invalid chain } void CBlock::UpdateTime(const CBlockIndex* pindexPrev) @@ -1380,7 +1379,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); MapPrevTx mapInputs; - if (!(tx.IsCoinBase() || tx.IsCoinStake())) + if (!tx.IsCoinBase()) { bool fInvalid; if (!tx.FetchInputs(txdb, mapQueuedChanges, true, false, mapInputs, fInvalid)) @@ -1396,7 +1395,8 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) return DoS(100, error("ConnectBlock() : too many sigops")); } - nFees += tx.GetValueIn(mapInputs)-tx.GetValueOut(); + if (!tx.IsCoinStake()) + nFees += tx.GetValueIn(mapInputs)-tx.GetValueOut(); if (!tx.ConnectInputs(txdb, mapInputs, mapQueuedChanges, posThisTx, pindex, true, false, fStrictPayToScriptHash)) return false; @@ -2013,7 +2013,10 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) // ppcoin: verify hash target and signature of coinstake tx if (pblock->IsProofOfStake() && !pblock->vtx[1].CheckProofOfStake(pblock->nBits)) - return error("ProcessBlock() : check proof-of-stake failed for block %s", hash.ToString().c_str()); + { + 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 + } CBlockIndex* pcheckpoint = Checkpoints::GetLastSyncCheckpoint(); if (pcheckpoint && pblock->hashPrevBlock != hashBestChain && !Checkpoints::WantedByPendingSyncCheckpoint(hash)) @@ -2091,6 +2094,11 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) } printf("ProcessBlock: ACCEPTED\n"); + + // ppcoin: if responsible for sync-checkpoint send it + if (pfrom && !CSyncCheckpoint::strMasterPrivKey.empty()) + Checkpoints::SendSyncCheckpoint(Checkpoints::AutoSelectSyncCheckpoint()); + return true; } @@ -2158,7 +2166,7 @@ bool CheckDiskSpace(uint64 nAdditionalBytes) string strMessage = _("Warning: Disk space is low"); strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); - ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION | wxMODAL); + ThreadSafeMessageBox(strMessage, "PPCoin", wxOK | wxICON_EXCLAMATION | wxMODAL); StartShutdown(); return false; } @@ -2361,7 +2369,7 @@ void PrintBlockTree() pindex->nBlockPos, block.GetHash().ToString().substr(0,20).c_str(), block.nBits, - DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(), + DateTimeStrFormat(block.GetBlockTime()).c_str(), block.vtx.size()); PrintWallets(block); @@ -2400,6 +2408,9 @@ void PrintBlockTree() map mapAlerts; CCriticalSection cs_mapAlerts; +static string strMintMessage = _("Info: Minting suspended due to locked wallet."); +static string strMintWarning; + string GetWarnings(string strFor) { int nPriority = 0; @@ -2408,6 +2419,13 @@ string GetWarnings(string strFor) if (GetBoolArg("-testsafemode")) strRPC = "test"; + // ppcoin: wallet lock warning for minting + if (strMintWarning != "") + { + nPriority = 0; + strStatusBar = strMintWarning; + } + // Misc warnings like out of disk space and clock is wrong if (strMiscWarning != "") { @@ -2415,17 +2433,19 @@ string GetWarnings(string strFor) strStatusBar = strMiscWarning; } - // Longer invalid proof-of-work chain - if (pindexBest && nBestInvalidTrust > nBestChainTrust + pindexBest->GetBlockTrust() * 6) + // ppcoin: should not enter safe mode for longer invalid chain + // ppcoin: if sync-checkpoint too old enter safe mode + if (Checkpoints::IsMatureSyncCheckpoint()) { nPriority = 2000; - strStatusBar = strRPC = "WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."; + strStatusBar = strRPC = "WARNING: Checkpoint is too old. Wait for block chain to download, or notify developers of the issue."; } + // ppcoin: if detected invalid checkpoint enter safe mode if (Checkpoints::hashInvalidCheckpoint != 0) { nPriority = 3000; - strStatusBar = strRPC = "WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."; + strStatusBar = strRPC = "WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers of the issue."; } // Alerts @@ -2438,6 +2458,8 @@ string GetWarnings(string strFor) { nPriority = alert.nPriority; strStatusBar = alert.strStatusBar; + if (nPriority > 1000) + strRPC = strStatusBar; // ppcoin: safe mode for high alert } } } @@ -2548,7 +2570,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) static map > mapReuseKey; RandAddSeedPerfmon(); if (fDebug) { - printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); + printf("%s ", DateTimeStrFormat(GetTime()).c_str()); printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size()); } if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) @@ -2840,8 +2862,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // Bypass PushInventory, this must send even if redundant, // and we want it right after the last block so they don't // wait for other stuff first. + // ppcoin: send latest proof-of-work block to allow the + // download node to accept as orphan (proof-of-stake + // block might be rejected by stake connection check) vector vInv; - vInv.push_back(CInv(MSG_BLOCK, hashBestChain)); + vInv.push_back(CInv(MSG_BLOCK, GetLastBlockIndex(pindexBest, false)->GetBlockHash())); pfrom->PushMessage("inv", vInv); pfrom->hashContinue = 0; } @@ -3539,7 +3564,9 @@ public: uint64 nLastBlockTx = 0; uint64 nLastBlockSize = 0; -CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfWorkOnly) +// CreateNewBlock: +// fProofOfStake: try (best effort) to make a proof-of-stake block +CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake) { CReserveKey reservekey(pwallet); @@ -3559,10 +3586,10 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfWorkOnly) pblock->vtx.push_back(txNew); // ppcoin: if coinstake available add coinstake tx - static unsigned int nLastCoinStakeCheckTime = GetAdjustedTime() - nMaxClockDrift + 60; // only initialized at startup + static unsigned int nLastCoinStakeCheckTime = GetAdjustedTime() - nMaxClockDrift / 2; // only initialized at startup CBlockIndex* pindexPrev = pindexBest; - if (!fProofOfWorkOnly) + if (fProofOfStake) // attemp to find a coinstake { while (nLastCoinStakeCheckTime < GetAdjustedTime()) { @@ -3575,7 +3602,7 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfWorkOnly) // mining may have been suspended for a while so // need to take max to satisfy the timestamp protocol nLastCoinStakeCheckTime++; - nLastCoinStakeCheckTime = max(nLastCoinStakeCheckTime, (unsigned int) (GetAdjustedTime() - nMaxClockDrift + 60)); + nLastCoinStakeCheckTime = max(nLastCoinStakeCheckTime, (unsigned int) (GetAdjustedTime() - nMaxClockDrift / 2)); txCoinStake.nTime = nLastCoinStakeCheckTime; } if (pwallet->CreateCoinStake(pblock->nBits, txCoinStake)) @@ -3736,8 +3763,7 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfWorkOnly) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); - pblock->nTime = max(pblock->GetBlockTime(), pblock->GetMaxTransactionTime()); + pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, pblock->GetMaxTransactionTime()); pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime() - nMaxClockDrift); pblock->UpdateTime(pindexPrev); pblock->nNonce = 0; @@ -3821,7 +3847,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) printf("BitcoinMiner:\n"); 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("%s ", DateTimeStrFormat(GetTime()).c_str()); printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str()); // Found a solution @@ -3853,16 +3879,16 @@ static bool fGenerateBitcoins = false; static bool fLimitProcessors = false; static int nLimitProcessors = -1; -void static BitcoinMiner(CWallet *pwallet) +void BitcoinMiner(CWallet *pwallet, bool fProofOfStake) { - printf("BitcoinMiner started\n"); + printf("CPUMiner started for proof-of-%s\n", fProofOfStake? "stake" : "work"); SetThreadPriority(THREAD_PRIORITY_LOWEST); // Each thread has its own key and counter CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; - while (fGenerateBitcoins) + while (fGenerateBitcoins || fProofOfStake) { if (fShutdown) return; @@ -3871,10 +3897,16 @@ void static BitcoinMiner(CWallet *pwallet) Sleep(1000); if (fShutdown) return; - if (!fGenerateBitcoins) + if ((!fGenerateBitcoins) && !fProofOfStake) return; } + while (pwallet->IsLocked()) + { + strMintWarning = strMintMessage; + Sleep(1000); + } + strMintWarning = ""; // // Create new block @@ -3882,24 +3914,29 @@ void static BitcoinMiner(CWallet *pwallet) unsigned int nTransactionsUpdatedLast = nTransactionsUpdated; CBlockIndex* pindexPrev = pindexBest; - auto_ptr pblock(CreateNewBlock(pwallet)); + auto_ptr pblock(CreateNewBlock(pwallet, fProofOfStake)); if (!pblock.get()) return; IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce); // ppcoin: if proof-of-stake block found then process block - if (pblock->IsProofOfStake()) + if (fProofOfStake) { - if (!pblock->SignBlock(*pwalletMain)) + if (pblock->IsProofOfStake()) { - error("BitcoinMiner: Unable to sign new proof-of-stake block"); - return; + if (!pblock->SignBlock(*pwalletMain)) + { + strMintWarning = strMintMessage; + continue; + } + strMintWarning = ""; + printf("CPUMiner : 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); } - 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); + Sleep(500); continue; } @@ -3948,10 +3985,10 @@ void static BitcoinMiner(CWallet *pwallet) assert(hash == pblock->GetHash()); if (!pblock->SignBlock(*pwalletMain)) { - error("BitcoinMiner: Unable to sign new proof-of-work block"); - return; + strMintWarning = strMintMessage; + break; } - + strMintWarning = ""; SetThreadPriority(THREAD_PRIORITY_NORMAL); CheckWork(pblock.get(), *pwalletMain, reservekey); SetThreadPriority(THREAD_PRIORITY_LOWEST); @@ -3982,7 +4019,7 @@ void static BitcoinMiner(CWallet *pwallet) if (GetTime() - nLogTime > 30 * 60) { nLogTime = GetTime(); - printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str()); + printf("%s ", DateTimeStrFormat(GetTime()).c_str()); printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[THREAD_MINER], dHashesPerSec/1000.0); } } @@ -4006,8 +4043,7 @@ void static BitcoinMiner(CWallet *pwallet) break; // Update nTime every few seconds - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); - pblock->nTime = max(pblock->GetBlockTime(), pblock->GetMaxTransactionTime()); + pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, pblock->GetMaxTransactionTime()); pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime() - nMaxClockDrift); pblock->UpdateTime(pindexPrev); nBlockTime = ByteReverse(pblock->nTime); @@ -4023,7 +4059,7 @@ void static ThreadBitcoinMiner(void* parg) try { vnThreadsRunning[THREAD_MINER]++; - BitcoinMiner(pwallet); + BitcoinMiner(pwallet, false); vnThreadsRunning[THREAD_MINER]--; } catch (std::exception& e) {