|
|
@@ -1717,10 +1717,10 @@ void ThreadScriptCheck() { |
|
|
|
scriptcheckqueue.Thread(); |
|
|
|
} |
|
|
|
|
|
|
|
bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsViewCache &view, bool fJustCheck) |
|
|
|
bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) |
|
|
|
{ |
|
|
|
// Check it again in case a previous version let a bad block in |
|
|
|
if (!CheckBlock(state, !fJustCheck, !fJustCheck)) |
|
|
|
if (!block.CheckBlock(state, !fJustCheck, !fJustCheck)) |
|
|
|
return false; |
|
|
|
|
|
|
|
// verify that the view's current state corresponds to the previous block |
|
|
@@ -1728,7 +1728,7 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi |
|
|
|
|
|
|
|
// Special case for the genesis block, skipping connection of its transactions |
|
|
|
// (its coinbase is unspendable) |
|
|
|
if (GetHash() == Params().HashGenesisBlock()) { |
|
|
|
if (block.GetHash() == Params().HashGenesisBlock()) { |
|
|
|
view.SetBestBlock(pindex); |
|
|
|
pindexGenesisBlock = pindex; |
|
|
|
return true; |
|
|
@@ -1752,8 +1752,8 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi |
|
|
|
!((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) || |
|
|
|
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"))); |
|
|
|
if (fEnforceBIP30) { |
|
|
|
for (unsigned int i=0; i<vtx.size(); i++) { |
|
|
|
uint256 hash = GetTxHash(i); |
|
|
|
for (unsigned int i = 0; i < block.vtx.size(); i++) { |
|
|
|
uint256 hash = block.GetTxHash(i); |
|
|
|
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned()) |
|
|
|
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction")); |
|
|
|
} |
|
|
@@ -1774,12 +1774,12 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi |
|
|
|
int64 nFees = 0; |
|
|
|
int nInputs = 0; |
|
|
|
unsigned int nSigOps = 0; |
|
|
|
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(vtx.size())); |
|
|
|
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); |
|
|
|
std::vector<std::pair<uint256, CDiskTxPos> > vPos; |
|
|
|
vPos.reserve(vtx.size()); |
|
|
|
for (unsigned int i=0; i<vtx.size(); i++) |
|
|
|
vPos.reserve(block.vtx.size()); |
|
|
|
for (unsigned int i = 0; i < block.vtx.size(); i++) |
|
|
|
{ |
|
|
|
const CTransaction &tx = vtx[i]; |
|
|
|
const CTransaction &tx = block.vtx[i]; |
|
|
|
|
|
|
|
nInputs += tx.vin.size(); |
|
|
|
nSigOps += GetLegacySigOpCount(tx); |
|
|
@@ -1810,19 +1810,19 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi |
|
|
|
} |
|
|
|
|
|
|
|
CTxUndo txundo; |
|
|
|
UpdateCoins(tx, state, view, txundo, pindex->nHeight, GetTxHash(i)); |
|
|
|
UpdateCoins(tx, state, view, txundo, pindex->nHeight, block.GetTxHash(i)); |
|
|
|
if (!tx.IsCoinBase()) |
|
|
|
blockundo.vtxundo.push_back(txundo); |
|
|
|
|
|
|
|
vPos.push_back(std::make_pair(GetTxHash(i), pos)); |
|
|
|
vPos.push_back(std::make_pair(block.GetTxHash(i), pos)); |
|
|
|
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); |
|
|
|
} |
|
|
|
int64 nTime = GetTimeMicros() - nStart; |
|
|
|
if (fBenchmark) |
|
|
|
printf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)vtx.size(), 0.001 * nTime, 0.001 * nTime / vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1)); |
|
|
|
printf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)block.vtx.size(), 0.001 * nTime, 0.001 * nTime / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1)); |
|
|
|
|
|
|
|
if (GetValueOut(vtx[0]) > GetBlockValue(pindex->nHeight, nFees)) |
|
|
|
return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", GetValueOut(vtx[0]), GetBlockValue(pindex->nHeight, nFees))); |
|
|
|
if (GetValueOut(block.vtx[0]) > GetBlockValue(pindex->nHeight, nFees)) |
|
|
|
return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", GetValueOut(block.vtx[0]), GetBlockValue(pindex->nHeight, nFees))); |
|
|
|
|
|
|
|
if (!control.Wait()) |
|
|
|
return state.DoS(100, false); |
|
|
@@ -1863,8 +1863,8 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi |
|
|
|
assert(view.SetBestBlock(pindex)); |
|
|
|
|
|
|
|
// Watch for transactions paying to me |
|
|
|
for (unsigned int i=0; i<vtx.size(); i++) |
|
|
|
SyncWithWallets(GetTxHash(i), vtx[i], this, true); |
|
|
|
for (unsigned int i = 0; i < block.vtx.size(); i++) |
|
|
|
SyncWithWallets(block.GetTxHash(i), block.vtx[i], &block, true); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
@@ -1933,7 +1933,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew) |
|
|
|
if (!ReadBlockFromDisk(block, pindex)) |
|
|
|
return state.Abort(_("Failed to read block")); |
|
|
|
int64 nStart = GetTimeMicros(); |
|
|
|
if (!block.ConnectBlock(state, pindex, view)) { |
|
|
|
if (!ConnectBlock(block, state, pindex, view)) { |
|
|
|
if (state.IsInvalid()) { |
|
|
|
InvalidChainFound(pindexNew); |
|
|
|
InvalidBlockFound(pindex); |
|
|
@@ -2799,7 +2799,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth) |
|
|
|
CBlock block; |
|
|
|
if (!ReadBlockFromDisk(block, pindex)) |
|
|
|
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str()); |
|
|
|
if (!block.ConnectBlock(state, pindex, coins)) |
|
|
|
if (!ConnectBlock(block, state, pindex, coins)) |
|
|
|
return error("VerifyDB() : *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str()); |
|
|
|
} |
|
|
|
} |
|
|
@@ -4454,7 +4454,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey) |
|
|
|
indexDummy.nHeight = pindexPrev->nHeight + 1; |
|
|
|
CCoinsViewCache viewNew(*pcoinsTip, true); |
|
|
|
CValidationState state; |
|
|
|
if (!pblock->ConnectBlock(state, &indexDummy, viewNew, true)) |
|
|
|
if (!ConnectBlock(*pblock, state, &indexDummy, viewNew, true)) |
|
|
|
throw std::runtime_error("CreateNewBlock() : ConnectBlock failed"); |
|
|
|
} |
|
|
|
|