TeachMeBitcoin

IsStandard() Rules in Bitcoin Core

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

IsStandard() Rules in Bitcoin Core

IsStandard() is a function in Bitcoin Core that determines whether a transaction meets the node's relay policy requirements. It is a multi-part check that examines transaction structure, script types, sizes, and other properties.

Location in Bitcoin Core

src/policy/policy.cpp  → IsStandardTx(), IsStandard()
src/policy/policy.h    → Declarations and constants

The Full IsStandardTx() Check

// Simplified version of IsStandardTx() in policy.cpp:
bool IsStandardTx(const CTransaction& tx, std::string& reason) {

    // 1. Version check
    if (tx.nVersion > MAX_STANDARD_VERSION || tx.nVersion < 1) {
        reason = "version";
        return false;
    }

    // 2. Transaction size limit (weight)
    if (GetTransactionWeight(tx) > MAX_STANDARD_TX_WEIGHT) {
        reason = "tx-size";
        return false;
    }

    // 3. Check each input
    for (const CTxIn& txin : tx.vin) {
        // scriptSig size limit
        if (txin.scriptSig.size() > MAX_SCRIPT_ELEMENT_SIZE) {
            reason = "scriptsig-size";
            return false;
        }
        // scriptSig must only use push opcodes
        if (!txin.scriptSig.IsPushOnly()) {
            reason = "scriptsig-not-pushonly";
            return false;
        }
    }

    // 4. Check each output
    int nDataOut = 0;
    for (const CTxOut& txout : tx.vout) {
        TxoutType whichType;
        if (!IsStandard(txout.scriptPubKey, whichType)) {
            reason = "scriptpubkey";
            return false;
        }
        if (whichType == TxoutType::NULL_DATA) {
            nDataOut++;
        }
        // Dust check
        if (IsDust(txout, dustRelayFee)) {
            reason = "dust";
            return false;
        }
    }

    // Only one OP_RETURN output allowed
    if (nDataOut > 1) {
        reason = "multi-op-return";
        return false;
    }

    return true;
}

Key Policy Constants

// From src/policy/policy.h:
static const unsigned int MAX_STANDARD_TX_WEIGHT = 400000;
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
static const unsigned int MAX_STANDARD_VERSION = 2;
static const unsigned int MAX_OP_RETURN_RELAY = 83; // OP_RETURN + 80 bytes data
static const CFeeRate DUST_RELAY_TX_FEE(3000); // 3000 sat/kB dust threshold

The scriptSig Push-Only Requirement

One of the most important standardness rules is that scriptSig must be push-only — it can only contain data push opcodes, not execution opcodes. This prevents a scriptSig from manipulating the execution environment before the locking script runs:

// STANDARD scriptSig (push-only):
<sig_bytes> <pubKey_bytes>

// NON-STANDARD scriptSig (contains OP_DUP):
OP_DUP <sig_bytes>

// Nodes would reject the second transaction from relay

The Dust Limit

An output is considered "dust" if the cost of spending it (in transaction fees) exceeds its value. Dust outputs are economically irrational — they cost more to spend than they're worth. Bitcoin Core refuses to relay transactions with dust outputs.

# Dust calculation (simplified):
def is_dust(output, dust_relay_fee):
    # Estimate the input size needed to spend this output type
    spend_size = estimate_input_size(output.scriptPubKey)
    # Cost to spend = spend_size * dust_relay_fee / 1000
    spend_cost = spend_size * dust_relay_fee / 1000
    return output.value < spend_cost

# Typical dust thresholds:
# P2PKH: ~546 satoshis
# P2WPKH: ~294 satoshis
# P2TR: ~330 satoshis
☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!