<p>I suspect this is an artifact of the way the code used to work. As to why it hasn't been taken out, it's probably just out of caution, or a "Don't fix it if it's not broken" mindset. Bitcoin Core coders are very cautious, and reasonably so since it's a piece of software that is the main interface to the network for many big players in the industry.</p>

<p>In addition, on master right now, <code>CheckBlock</code> contains a check at the beginning to avoid doing the same work twice. (Added in <a href="https://github.com/bitcoin/bitcoin/commit/3b33ec85ed00ba7e7525858e3701f9f55071c58b" rel="nofollow">this commit</a>.)</p>

<pre><code>if (block.fChecked)
    return true;
</code></pre>

CC BY-SA 3.0
2015-11-19T16:26:03.343Z
2015-11-19T16:34:25.660Z
2015-11-19T16:34:25.660Z
morsecoder
<p>Once the Bitcoin node receives a message with a new block, it calls the <code>ProcessNewBlock</code> function:</p>

<pre><code> else if (strCommand == "block" &amp;&amp; !fImporting &amp;&amp; !fReindex) // Ignore blocks received while importing
{
    CBlock block;
    vRecv &gt;&gt; block;

    CInv inv(MSG_BLOCK, block.GetHash());
    LogPrint("net", "received block %s peer=%d\n", inv.hash.ToString(), pfrom-&gt;id);

    pfrom-&gt;AddInventoryKnown(inv);

    CValidationState state;
    // Process all blocks from whitelisted peers, even if not requested,
    // unless we're still syncing with the network.
    // Such an unrequested block may still be processed, subject to the
    // conditions in AcceptBlock().
    bool forceProcessing = pfrom-&gt;fWhitelisted &amp;&amp; !IsInitialBlockDownload();
    ProcessNewBlock(state, pfrom, &amp;block, forceProcessing, NULL);
    int nDoS;
    if (state.IsInvalid(nDoS)) {
        assert (state.GetRejectCode() &lt; REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
        pfrom-&gt;PushMessage("reject", strCommand, state.GetRejectCode(),
                           state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
        if (nDoS &gt; 0) {
            LOCK(cs_main);
            Misbehaving(pfrom-&gt;GetId(), nDoS);
        }
    }
</code></pre>

<p>Inside this function, <code>CheckBlock</code> and <code>AcceptBlock</code> are called:</p>

<pre><code>// Preliminary checks
bool checked = CheckBlock(*pblock, state);

{
    LOCK(cs_main);
    bool fRequested = MarkBlockAsReceived(pblock-&gt;GetHash());
    fRequested |= fForceProcessing;
    if (!checked) {
        return error("%s: CheckBlock FAILED", __func__);
    }

    // Store to disk
    CBlockIndex *pindex = NULL;
    bool ret = AcceptBlock(*pblock, state, &amp;pindex, fRequested, dbp);
    if (pindex &amp;&amp; pfrom) {
        mapBlockSource[pindex-&gt;GetBlockHash()] = pfrom-&gt;GetId();
    }
    CheckBlockIndex();
    if (!ret)
        return error("%s: AcceptBlock FAILED", __func__);
}
</code></pre>

<p>Inside the <code>AcceptBlock</code> function <code>CheckBlock</code> is called again:</p>

<pre><code>if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex-&gt;pprev)) {
    if (state.IsInvalid() &amp;&amp; !state.CorruptionPossible()) {
        pindex-&gt;nStatus |= BLOCK_FAILED_VALID;
        setDirtyBlockIndex.insert(pindex);
    }
    return false;
</code></pre>

<p>Why is the <code>CheckBlock</code> function called two times when processing a new block?</p>

<block><bitcoin-core-development>
Why is CheckBlock called twice when processing a new block?
bitaps.com
# Why is CheckBlock called twice when processing a new block?

(Asked by: username_0 on 2015-10-24)

Once the Bitcoin node receives a message with a new block, it calls the `ProcessNewBlock` function:

```
 else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing
{
    CBlock block;
    vRecv >> block;

    CInv inv(MSG_BLOCK, block.GetHash());
    LogPrint("net", "received block %s peer=%d\n", inv.hash.ToString(), pfrom->id);

    pfrom->AddInventoryKnown(inv);

    CValidationState state;
    // Process all blocks from whitelisted peers, even if not requested,
    // unless we're still syncing with the network.
    // Such an unrequested block may still be processed, subject to the
    // conditions in AcceptBlock().
    bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
    ProcessNewBlock(state, pfrom, &block, forceProcessing, NULL);
    int nDoS;
    if (state.IsInvalid(nDoS)) {
        assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
        pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
                           state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
        if (nDoS > 0) {
            LOCK(cs_main);
            Misbehaving(pfrom->GetId(), nDoS);
        }
    }

```

Inside this function, `CheckBlock` and `AcceptBlock` are called:

```
// Preliminary checks
bool checked = CheckBlock(*pblock, state);

{
    LOCK(cs_main);
    bool fRequested = MarkBlockAsReceived(pblock->GetHash());
    fRequested |= fForceProcessing;
    if (!checked) {
        return error("%s: CheckBlock FAILED", __func__);
    }

    // Store to disk
    CBlockIndex *pindex = NULL;
    bool ret = AcceptBlock(*pblock, state, &pindex, fRequested, dbp);
    if (pindex && pfrom) {
        mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
    }
    CheckBlockIndex();
    if (!ret)
        return error("%s: AcceptBlock FAILED", __func__);
}

```

Inside the `AcceptBlock` function `CheckBlock` is called again:

```
if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) {
    if (state.IsInvalid() && !state.CorruptionPossible()) {
        pindex->nStatus |= BLOCK_FAILED_VALID;
        setDirtyBlockIndex.insert(pindex);
    }
    return false;

```

Why is the `CheckBlock` function called two times when processing a new block?

**Tags:** block, bitcoin-core-development


---

## 1 answers

### Answer by username_1 on 2015-11-19. Score: 1

I suspect this is an artifact of the way the code used to work. As to why it hasn't been taken out, it's probably just out of caution, or a "Don't fix it if it's not broken" mindset. Bitcoin Core coders are very cautious, and reasonably so since it's a piece of software that is the main interface to the network for many big players in the industry.

In addition, on master right now, `CheckBlock` contains a check at the beginning to avoid doing the same work twice. (Added in [this commit](https://github.com/bitcoin/bitcoin/commit/3b33ec85ed00ba7e7525858e3701f9f55071c58b).)

```
if (block.fChecked)
    return true;

```


---

