aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp155
1 files changed, 75 insertions, 80 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 0940260f9..4c2115688 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -719,7 +719,7 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs,
// are the actual inputs available?
if (!tx.HaveInputs(view))
return error("CTxMemPool::accept() : inputs already spent");
-
+
// Bring the best block into scope
view.GetBestBlock();
@@ -771,7 +771,7 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs,
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
- if (!tx.CheckInputs(view, CS_ALWAYS, true, false))
+ if (!tx.CheckInputs(view, CS_ALWAYS, SCRIPT_VERIFY_P2SH))
{
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
}
@@ -998,21 +998,16 @@ CBlockIndex* FindBlockByHeight(int nHeight)
return pblockindex;
}
-bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
+bool CBlock::ReadFromDisk(const CBlockIndex* pindex)
{
- if (!fReadTransactions)
- {
- *this = pindex->GetBlockHeader();
- return true;
- }
- if (!ReadFromDisk(pindex->GetBlockPos(), fReadTransactions))
+ if (!ReadFromDisk(pindex->GetBlockPos()))
return false;
if (GetHash() != pindex->GetBlockHash())
return error("CBlock::ReadFromDisk() : GetHash() doesn't match index");
return true;
}
-uint256 static GetOrphanRoot(const CBlock* pblock)
+uint256 static GetOrphanRoot(const CBlockHeader* pblock)
{
// Work back to the first block in the orphan chain
while (mapOrphanBlocks.count(pblock->hashPrevBlock))
@@ -1059,7 +1054,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime)
return bnResult.GetCompact();
}
-unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlock *pblock)
+unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
{
unsigned int nProofOfWorkLimit = bnProofOfWorkLimit.GetCompact();
@@ -1168,11 +1163,11 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
uiInterface.NotifyBlocksChanged();
}
printf("InvalidChainFound: invalid block=%s height=%d work=%s date=%s\n",
- pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight,
+ BlockHashStr(pindexNew->GetBlockHash()).c_str(), pindexNew->nHeight,
pindexNew->bnChainWork.ToString().c_str(), DateTimeStrFormat("%x %H:%M:%S",
pindexNew->GetBlockTime()).c_str());
printf("InvalidChainFound: current best=%s height=%d work=%s date=%s\n",
- hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(),
+ BlockHashStr(hashBestChain).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(),
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)
printf("InvalidChainFound: Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
@@ -1198,7 +1193,7 @@ bool ConnectBestBlock() {
pindexNewBest = *it;
}
- if (pindexNewBest == pindexBest)
+ if (pindexNewBest == pindexBest || (pindexBest && pindexNewBest->bnChainWork == pindexBest->bnChainWork))
return true; // nothing to do
// check ancestry
@@ -1233,7 +1228,7 @@ bool ConnectBestBlock() {
} while(true);
}
-void CBlock::UpdateTime(const CBlockIndex* pindexPrev)
+void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev)
{
nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
@@ -1327,7 +1322,7 @@ bool CTransaction::HaveInputs(CCoinsViewCache &inputs) const
return true;
}
-bool CTransaction::CheckInputs(CCoinsViewCache &inputs, enum CheckSig_mode csmode, bool fStrictPayToScriptHash, bool fStrictEncodings) const
+bool CTransaction::CheckInputs(CCoinsViewCache &inputs, enum CheckSig_mode csmode, unsigned int flags) const
{
if (!IsCoinBase())
{
@@ -1338,7 +1333,7 @@ bool CTransaction::CheckInputs(CCoinsViewCache &inputs, enum CheckSig_mode csmod
// While checking, GetBestBlock() refers to the parent block.
// This is also true for mempool checks.
- int nSpendHeight = inputs.GetBestBlock()->nHeight + 1;
+ int nSpendHeight = inputs.GetBestBlock()->nHeight + 1;
int64 nValueIn = 0;
int64 nFees = 0;
for (unsigned int i = 0; i < vin.size(); i++)
@@ -1384,7 +1379,7 @@ bool CTransaction::CheckInputs(CCoinsViewCache &inputs, enum CheckSig_mode csmod
const CCoins &coins = inputs.GetCoins(prevout.hash);
// Verify signature
- if (!VerifySignature(coins, *this, i, fStrictPayToScriptHash, fStrictEncodings, 0))
+ if (!VerifySignature(coins, *this, i, flags, 0))
return DoS(100,error("CheckInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,10).c_str()));
}
}
@@ -1415,7 +1410,7 @@ bool CTransaction::ClientCheckInputs() const
return false;
// Verify signature
- if (!VerifySignature(CCoins(txPrev, -1), *this, i, true, false, 0))
+ if (!VerifySignature(CCoins(txPrev, -1), *this, i, SCRIPT_VERIFY_P2SH, 0))
return error("ConnectInputs() : VerifySignature failed");
///// this is redundant with the mempool.mapNextTx stuff,
@@ -1598,7 +1593,7 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
nFees += tx.GetValueIn(view)-tx.GetValueOut();
- if (!tx.CheckInputs(view, CS_AFTER_CHECKPOINT, fStrictPayToScriptHash, false))
+ if (!tx.CheckInputs(view, CS_AFTER_CHECKPOINT, fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE))
return false;
}
@@ -1610,7 +1605,7 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
}
if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
- return false;
+ return error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees));
if (fJustCheck)
return true;
@@ -1693,8 +1688,8 @@ bool SetBestChain(CBlockIndex* pindexNew)
reverse(vConnect.begin(), vConnect.end());
if (vDisconnect.size() > 0) {
- printf("REORGANIZE: Disconnect %"PRIszu" blocks; %s..%s\n", vDisconnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexBest->GetBlockHash().ToString().substr(0,20).c_str());
- printf("REORGANIZE: Connect %"PRIszu" blocks; %s..%s\n", vConnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->GetBlockHash().ToString().substr(0,20).c_str());
+ printf("REORGANIZE: Disconnect %"PRIszu" blocks; %s..%s\n", vDisconnect.size(), BlockHashStr(pfork->GetBlockHash()).c_str(), BlockHashStr(pindexBest->GetBlockHash()).c_str());
+ printf("REORGANIZE: Connect %"PRIszu" blocks; %s..%s\n", vConnect.size(), BlockHashStr(pfork->GetBlockHash()).c_str(), BlockHashStr(pindexNew->GetBlockHash()).c_str());
}
// Disconnect shorter branch
@@ -1705,7 +1700,7 @@ bool SetBestChain(CBlockIndex* pindexNew)
return error("SetBestBlock() : ReadFromDisk for disconnect failed");
CCoinsViewCache viewTemp(view, true);
if (!block.DisconnectBlock(pindex, viewTemp))
- return error("SetBestBlock() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().substr(0,20).c_str());
+ return error("SetBestBlock() : DisconnectBlock %s failed", BlockHashStr(pindex->GetBlockHash()).c_str());
if (!viewTemp.Flush())
return error("SetBestBlock() : Cache flush failed after disconnect");
@@ -1725,7 +1720,7 @@ bool SetBestChain(CBlockIndex* pindexNew)
if (!block.ConnectBlock(pindex, viewTemp)) {
InvalidChainFound(pindexNew);
InvalidBlockFound(pindex);
- return error("SetBestBlock() : ConnectBlock %s failed", pindex->GetBlockHash().ToString().substr(0,20).c_str());
+ return error("SetBestBlock() : ConnectBlock %s failed", BlockHashStr(pindex->GetBlockHash()).c_str());
}
if (!viewTemp.Flush())
return error("SetBestBlock() : Cache flush failed after connect");
@@ -1781,7 +1776,7 @@ bool SetBestChain(CBlockIndex* pindexNew)
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
printf("SetBestChain: new best=%s height=%d work=%s tx=%lu date=%s\n",
- hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(), (unsigned long)pindexNew->nChainTx,
+ BlockHashStr(hashBestChain).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(), (unsigned long)pindexNew->nChainTx,
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
// Check the version of the last 100 blocks to see if we need to upgrade:
@@ -1819,7 +1814,7 @@ bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos)
// Check for duplicate
uint256 hash = GetHash();
if (mapBlockIndex.count(hash))
- return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,20).c_str());
+ return error("AddToBlockIndex() : %s already exists", BlockHashStr(hash).c_str());
// Construct new block index object
CBlockIndex* pindexNew = new CBlockIndex(*this);
@@ -1899,8 +1894,8 @@ bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeigh
if (file) {
printf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile);
AllocateFileRange(file, pos.nPos, nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos);
+ fclose(file);
}
- fclose(file);
}
}
@@ -1941,8 +1936,8 @@ bool FindUndoPos(int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
if (file) {
printf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile);
AllocateFileRange(file, pos.nPos, nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos);
+ fclose(file);
}
- fclose(file);
}
return true;
@@ -2018,52 +2013,51 @@ bool CBlock::AcceptBlock(CDiskBlockPos *dbp)
CBlockIndex* pindexPrev = NULL;
int nHeight = 0;
if (hash != hashGenesisBlock) {
-
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
- if (mi == mapBlockIndex.end())
- return DoS(10, error("AcceptBlock() : prev block not found"));
- pindexPrev = (*mi).second;
- nHeight = pindexPrev->nHeight+1;
-
- // Check proof of work
- if (nBits != GetNextWorkRequired(pindexPrev, this))
- return DoS(100, error("AcceptBlock() : incorrect proof of work"));
-
- // Check timestamp against prev
- if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
- return error("AcceptBlock() : block's timestamp is too early");
-
- // Check that all transactions are finalized
- BOOST_FOREACH(const CTransaction& tx, vtx)
- if (!tx.IsFinal(nHeight, GetBlockTime()))
- return DoS(10, error("AcceptBlock() : contains a non-final transaction"));
-
- // Check that the block chain matches the known block chain up to a checkpoint
- if (!Checkpoints::CheckBlock(nHeight, hash))
- return DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight));
-
- // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded:
- if (nVersion < 2)
- {
- if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) ||
- (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
+ map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
+ if (mi == mapBlockIndex.end())
+ return DoS(10, error("AcceptBlock() : prev block not found"));
+ pindexPrev = (*mi).second;
+ nHeight = pindexPrev->nHeight+1;
+
+ // Check proof of work
+ if (nBits != GetNextWorkRequired(pindexPrev, this))
+ return DoS(100, error("AcceptBlock() : incorrect proof of work"));
+
+ // Check timestamp against prev
+ if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
+ return error("AcceptBlock() : block's timestamp is too early");
+
+ // Check that all transactions are finalized
+ BOOST_FOREACH(const CTransaction& tx, vtx)
+ if (!tx.IsFinal(nHeight, GetBlockTime()))
+ return DoS(10, error("AcceptBlock() : contains a non-final transaction"));
+
+ // Check that the block chain matches the known block chain up to a checkpoint
+ if (!Checkpoints::CheckBlock(nHeight, hash))
+ return DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight));
+
+ // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded:
+ if (nVersion < 2)
{
- return error("AcceptBlock() : rejected nVersion=1 block");
+ if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) ||
+ (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
+ {
+ return error("AcceptBlock() : rejected nVersion=1 block");
+ }
}
- }
- // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
- if (nVersion >= 2)
- {
- // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
- if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) ||
- (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100)))
+ // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
+ if (nVersion >= 2)
{
- CScript expect = CScript() << nHeight;
- if (!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin()))
- return DoS(100, error("AcceptBlock() : block height mismatch in coinbase"));
+ // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
+ if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) ||
+ (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100)))
+ {
+ CScript expect = CScript() << nHeight;
+ if (!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin()))
+ return DoS(100, error("AcceptBlock() : block height mismatch in coinbase"));
+ }
}
}
- }
// Write block to history file
unsigned int nBlockSize = ::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION);
@@ -2112,9 +2106,9 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
// Check for duplicate
uint256 hash = pblock->GetHash();
if (mapBlockIndex.count(hash))
- return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,20).c_str());
+ return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, BlockHashStr(hash).c_str());
if (mapOrphanBlocks.count(hash))
- return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,20).c_str());
+ return error("ProcessBlock() : already have block (orphan) %s", BlockHashStr(hash).c_str());
// Preliminary checks
if (!pblock->CheckBlock())
@@ -2147,7 +2141,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
// If we don't already have its previous block, shunt it off to holding area until we get it
if (pblock->hashPrevBlock != 0 && !mapBlockIndex.count(pblock->hashPrevBlock))
{
- printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,20).c_str());
+ printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", BlockHashStr(pblock->hashPrevBlock).c_str());
// Accept orphans as long as there is a node to request its parents from
if (pfrom) {
@@ -2319,7 +2313,7 @@ bool static LoadBlockIndexDB()
pindex = pindexPrev;
}
printf("LoadBlockIndex(): hashBestChain=%s height=%d date=%s\n",
- hashBestChain.ToString().substr(0,20).c_str(), nBestHeight,
+ BlockHashStr(hashBestChain).c_str(), nBestHeight,
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
// Load bnBestInvalidWork, OK if it doesn't exist
@@ -3029,12 +3023,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (pindex)
pindex = pindex->pnext;
int nLimit = 500;
- printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit);
+ printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), BlockHashStr(hashStop).c_str(), nLimit);
for (; pindex; pindex = pindex->pnext)
{
if (pindex->GetBlockHash() == hashStop)
{
- printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str());
+ printf(" getblocks stopping at %d %s\n", pindex->nHeight, BlockHashStr(pindex->GetBlockHash()).c_str());
break;
}
pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
@@ -3042,7 +3036,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
// When this block is requested, we'll send an inv that'll make them
// getblocks the next batch of inventory.
- printf(" getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str());
+ printf(" getblocks stopping at limit %d %s\n", pindex->nHeight, BlockHashStr(pindex->GetBlockHash()).c_str());
pfrom->hashContinue = pindex->GetBlockHash();
break;
}
@@ -3073,9 +3067,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pindex = pindex->pnext;
}
+ // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
vector<CBlock> vHeaders;
int nLimit = 2000;
- printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str());
+ printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), BlockHashStr(hashStop).c_str());
for (; pindex; pindex = pindex->pnext)
{
vHeaders.push_back(pindex->GetBlockHeader());
@@ -3159,7 +3154,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CBlock block;
vRecv >> block;
- printf("received block %s\n", block.GetHash().ToString().substr(0,20).c_str());
+ printf("received block %s\n", BlockHashStr(block.GetHash()).c_str());
// block.print();
CInv inv(MSG_BLOCK, block.GetHash());
@@ -3864,7 +3859,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
- if (!tx.CheckInputs(viewTemp, CS_ALWAYS, true, false))
+ if (!tx.CheckInputs(viewTemp, CS_ALWAYS, SCRIPT_VERIFY_P2SH))
continue;
CTxUndo txundo;