X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.cpp;h=2be1fefb544b71257f34f57b7fae2f7f818164d8;hb=2a4202a1545f86a78afc41d5641ed596f90356b2;hp=e8b8c61614e141e08621e9e378e3b44ebf76493e;hpb=16580f9e77f54d9fcbf53a9af99c26d1e3eea5d3;p=novacoin.git diff --git a/src/main.cpp b/src/main.cpp index e8b8c61..2be1fef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,10 +32,11 @@ map mapBlockIndex; set > setStakeSeen; uint256 hashGenesisBlock = hashGenesisBlockOfficial; 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; @@ -850,7 +851,7 @@ int64 static GetProofOfWorkReward(unsigned int nBits) if (fDebug && GetBoolArg("-printcreation")) printf("GetProofOfWorkReward() : create=%s nBits=0x%08x nSubsidy=%"PRI64d"\n", FormatMoney(nSubsidy).c_str(), nBits, nSubsidy); - return nSubsidy; + return min(nSubsidy, MAX_MINT_PROOF_OF_WORK); } // ppcoin: miner's coin stake is rewarded based on coin age spent (coin-days) @@ -898,16 +899,16 @@ const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfSta unsigned int static GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake) { - // Genesis block and first block - if (pindexLast == NULL || pindexLast->pprev == NULL) - return bnProofOfWorkLimit.GetCompact(); + if (pindexLast == NULL) + return bnProofOfWorkLimit.GetCompact(); // genesis block const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake); - if (pindexPrev == NULL) - return bnProofOfWorkLimit.GetCompact(); + if (pindexPrev->pprev == NULL) + return bnInitialHashTarget.GetCompact(); // first block const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake); - if (pindexPrevPrev == NULL) - return bnProofOfWorkLimit.GetCompact(); + if (pindexPrevPrev->pprev == NULL) + return bnInitialHashTarget.GetCompact(); // second block + int64 nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime(); // ppcoin: target change every block @@ -964,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 } @@ -1368,6 +1369,8 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) map mapQueuedChanges; int64 nFees = 0; + int64 nValueIn = 0; + int64 nValueOut = 0; unsigned int nSigOps = 0; BOOST_FOREACH(CTransaction& tx, vtx) { @@ -1379,7 +1382,9 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); MapPrevTx mapInputs; - if (!tx.IsCoinBase()) + if (tx.IsCoinBase()) + nValueOut += tx.GetValueOut(); + else { bool fInvalid; if (!tx.FetchInputs(txdb, mapQueuedChanges, true, false, mapInputs, fInvalid)) @@ -1395,8 +1400,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) return DoS(100, error("ConnectBlock() : too many sigops")); } + int64 nTxValueIn = tx.GetValueIn(mapInputs); + int64 nTxValueOut = tx.GetValueOut(); + nValueIn += nTxValueIn; + nValueOut += nTxValueOut; if (!tx.IsCoinStake()) - nFees += tx.GetValueIn(mapInputs)-tx.GetValueOut(); + nFees += nTxValueIn - nTxValueOut; if (!tx.ConnectInputs(txdb, mapInputs, mapQueuedChanges, posThisTx, pindex, true, false, fStrictPayToScriptHash)) return false; @@ -1405,6 +1414,10 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) mapQueuedChanges[tx.GetHash()] = CTxIndex(posThisTx, tx.vout.size()); } + // ppcoin: track money supply + pindex->nMint = nValueOut - nValueIn + nFees; + pindex->nMoneySupply = (pindex->pprev? pindex->pprev->nMoneySupply : 0) + nValueOut - nValueIn; + // Write queued txindex changes for (map::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi) { @@ -1414,8 +1427,6 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) // ppcoin: fees are not collected by miners as in bitcoin // ppcoin: fees are destroyed to compensate the entire network - if (IsProofOfWork() && vtx[0].GetValueOut() > GetProofOfWorkReward(nBits)) - return false; if (fDebug && GetBoolArg("-printcreation")) printf("ConnectBlock() : destroy=%s nFees=%"PRI64d"\n", FormatMoney(nFees).c_str(), nFees); @@ -1596,7 +1607,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; @@ -1644,10 +1655,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 moneysupply=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str(), FormatMoney(pindexBest->nMoneySupply).c_str()); std::string strCmd = GetArg("-blocknotify", ""); @@ -1817,10 +1828,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()) @@ -1830,10 +1838,17 @@ 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; + // ppcoin: got mint/moneysupply info in block index, write to db + if (!txdb.TxnBegin()) + return false; + txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew)); + if (!txdb.TxnCommit()) + return false; + txdb.Close(); if (pindexNew == pindexBest) @@ -1881,7 +1896,7 @@ bool CBlock::CheckBlock() const return DoS(100, error("CheckBlock() : coinstake in wrong position")); // ppcoin: coinbase output should be empty if proof-of-stake block - if (IsProofOfStake() && !vtx[0].vout[0].IsEmpty()) + if (IsProofOfStake() && (vtx[0].vout.size() != 1 || !vtx[0].vout[0].IsEmpty())) return error("CheckBlock() : coinbase output not empty for proof-of-stake block"); // Check coinbase timestamp @@ -1892,6 +1907,12 @@ bool CBlock::CheckBlock() const if (IsProofOfStake() && GetBlockTime() > (int64)vtx[1].nTime + nMaxClockDrift) return DoS(50, error("CheckBlock() : coinstake timestamp is too early")); + // Check coinbase reward + if (vtx[0].GetValueOut() > (IsProofOfWork()? GetProofOfWorkReward(nBits) : 0)) + return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s", + FormatMoney(vtx[0].GetValueOut()).c_str(), + FormatMoney(IsProofOfWork()? GetProofOfWorkReward(nBits) : 0).c_str())); + // Check transactions BOOST_FOREACH(const CTransaction& tx, vtx) { @@ -2064,7 +2085,8 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2)); // ppcoin: getblocks may not obtain the ancestor block rejected // earlier by duplicate-stake check so we ask for it again directly - pfrom->AskFor(CInv(MSG_BLOCK, WantedByOrphan(pblock2))); + if (!IsInitialBlockDownload()) + pfrom->AskFor(CInv(MSG_BLOCK, WantedByOrphan(pblock2))); } return true; } @@ -2250,34 +2272,33 @@ bool LoadBlockIndex(bool fAllowNew) // vMerkleTree: 4a5e1e // Genesis block - const char* pszTimestamp = "MarketWatch 07/Nov/2011 Gold tops $1,790 to end at over six-week high"; + const char* pszTimestamp = "Matonis 07-AUG-2012 Parallel Currencies And The Roadmap To Monetary Freedom"; CTransaction txNew; - txNew.nTime = 1339538219; + txNew.nTime = 1345083810; txNew.vin.resize(1); txNew.vout.resize(1); - txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); + txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(9999) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].SetEmpty(); CBlock block; block.vtx.push_back(txNew); block.hashPrevBlock = 0; block.hashMerkleRoot = block.BuildMerkleTree(); block.nVersion = 1; - block.nTime = 1339540307; + block.nTime = 1345084287; block.nBits = bnProofOfWorkLimit.GetCompact(); - block.nNonce = 1281822831; + block.nNonce = 2179302059; if (fTestNet) { - block.nTime = 1296688602; - block.nBits = 0x1d07fff8; - block.nNonce = 384568319; + block.nTime = 1345090000; + block.nNonce = 122894938; } //// debug print printf("%s\n", block.GetHash().ToString().c_str()); printf("%s\n", hashGenesisBlock.ToString().c_str()); printf("%s\n", block.hashMerkleRoot.ToString().c_str()); - assert(block.hashMerkleRoot == uint256("0x1557f46a17fcf8843dbe4c0c0edfd1d17eeff2c3c48d73a59d11f5d176e4b54d")); + assert(block.hashMerkleRoot == uint256("0x3c2d8f85fab4d17aac558cc648a1a58acff0de6deb890c29985690052c5993c2")); block.print(); assert(block.GetHash() == hashGenesisBlock); assert(block.CheckBlock()); @@ -2363,13 +2384,14 @@ void PrintBlockTree() // print item CBlock block; block.ReadFromDisk(pindex); - printf("%d (%u,%u) %s %08lx %s tx %d", + printf("%d (%u,%u) %s %08lx %s mint %s tx %d", pindex->nHeight, pindex->nFile, pindex->nBlockPos, block.GetHash().ToString().substr(0,20).c_str(), block.nBits, DateTimeStrFormat(block.GetBlockTime()).c_str(), + FormatMoney(pindex->nMint).c_str(), block.vtx.size()); PrintWallets(block); @@ -2909,6 +2931,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (pindex->GetBlockHash() == hashStop) { printf(" getblocks stopping at %d %s (%u bytes)\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str(), nBytes); + // ppcoin: tell downloading node about the latest block if it's + // without risk being rejected due to stake connection check + if (hashStop != hashBestChain && pindex->GetBlockTime() + STAKE_MIN_AGE > pindexBest->GetBlockTime()) + pfrom->PushInventory(CInv(MSG_BLOCK, hashBestChain)); break; } pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash())); @@ -3754,7 +3780,8 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake) nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; - printf("CreateNewBlock(): total size %lu\n", nBlockSize); + if (fDebug && GetBoolArg("-printpriority")) + printf("CreateNewBlock(): total size %lu\n", nBlockSize); } if (pblock->IsProofOfWork())