Today I was reading bitcoind src, and trying to find out where scriptPubKey is executed when a node received new block with transaction, for example transaction from new block may not be exist in mempool.

  1. Find function that execute script:


    • src/script/interpreter.cpp in this file source code of EvalScript function

    Used only in this 2 files:

    • src/policy/policy.cpp

    • src/script/sign.cpp

  2. Review sign.cpp

    Evalscript -> CombineSignatures -> /src/bitcoin-tx.cpp: MutateTxSign -> MutateTx -> CommandLineRawTx -> main

    This functions used when we create new transactions

  3. Review policy.cpp

    Evalscript -> AreInputsStandard -> /src/main.cpp: AcceptToMemoryPool


    • src/main.cpp later

    • src/wallet/wallet.cpp -> CommitTransaction - this is create own transaction functional

    • src/rpcrawtransaction.cpp -> sendrawtrnsaction - rpc function send rawtx

    • src/txmempool.cpp -> no calls only comments

Last one is src/main.cpp

AcceptToMemoryPool -> ProcessMessage on message "tx" , new single tx to pool received AcceptToMemoryPool -> DisconnectTip

DisconnectTip -> InvalidateBlock invaludate block and send all transaction back to pool with all verifications and script eval

DisconnectTip -> ActivateBestChainStep :

  // Disconnect active blocks which are no longer in the best chain.
bool fBlocksDisconnected = false;
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
    if (!DisconnectTip(state))
        return false;
    fBlocksDisconnected = true;

If we have orphan take out transactions from orphan to pool with all verifications

NO more other links found

From this I can conclude that in case node with bitcoind received new block with transactions that not in mempool we add this tx to blockchain without scriptPubKey executing.

Consequently if same "honest" miner include tx with invalid script, at example incorrect signature that spent same one coins, all bitcoind nodes add it to blockchain without eval script and not detect this

It is not possible to be true! Where is my error?

1 Answer 1


The behaviour of the mempool or orphan tx pool should not influence the validity of blocks at all.

When a block comes in:

  • main.cpp:ProcessMessage deals with processing messages, and dispatches to:
  • main.cpp:ProcessNewBlock deals with specifically processing block messages, which stores it on disk using AcceptBlock and then calls:
  • main.cpp:ActivateBestChain tries to verify the potentially new best chain and switch to it. For every atomic "reorganization" step, it calls:
  • main.cpp:ActivatebestChainStep which will try to verify new blocks to be added to the tip of the chain using:
  • main.cpp:ConnectTip which does the actual processing using:
  • main.cpp:ConnectBlock, which will iterate through the block's transactions and verify their inputs using:
  • main.cpp:CheckInputs which builds up a list of CScriptCheck objects for each script execution to be performed, which are verified from another thread. ConnectBlock waits for these threads to finish and deal with the result. In those threads, we call:
  • main.cpp:CScriptCheck::operator() which performs a single encapsulated script execution, using:
  • script/interpreter.cpp:VerifyScript to do a verification of script, which consists of executing a scriptPubKey + its spending scriptSig using:
  • script/interpreter.cpp:EvalScript.

So, EvalScript() should be executed for all scriptPubKeys which are spent by a block, before that blocks ends up being accepted as a tip.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.