Appendices Appendix F

Consensus vs. Relay Policy

"Policy is what my node does. Consensus is what the network enforces. They are very different things."—common refrain among Bitcoin Core contributors

Bitcoin has two completely separate rule sets, enforced at two different layers. A transaction can be perfectly valid and still be refused by every node on the network — because validity and relayability are not the same question. This appendix draws the line between them precisely, walks through every check in Bitcoin Core's IsStandardTx, and provides an in-browser tool that tells you exactly which of those checks a given transaction would pass or fail.

F.1The Two Rule Sets

Every Bitcoin node runs two filters on every transaction it sees:

FilterQuestion askedEnforced byChanging it requires…
ConsensusIs this transaction allowed in a valid block?Every full node, foreverA network-wide fork
Standardness (relay policy)Will this node relay it and accept it into its mempool?Only nodes running that policyJust a Bitcoin Core upgrade

A transaction is valid if it passes consensus — the signatures verify, the inputs exist, the scripts execute to true, the weight fits, and all the BIP-defined rules hold. A transaction is standard if, in addition, it matches a narrower set of conservative patterns that Bitcoin Core considers safe to gossip across the p2p network.

Every standard transaction is valid. Not every valid transaction is standard. A valid-but-non-standard transaction cannot propagate through the default p2p network, but if a miner directly includes it in a block, every node will accept that block. This asymmetry is the whole point.

A Concrete Example

A bare multisig scriptPubKey with 20 keys (a 3-of-20 OP_CHECKMULTISIG) is perfectly valid under consensus — it just evaluates OP_CHECKMULTISIG in the normal way. But Bitcoin Core's IsStandard rejects bare multisig with n > 3. If you try to broadcast it, every default-policy node will refuse to relay it. But if a miner constructs such an output in a block directly, no node will reject the block. The UTXO exists, it's spendable, and consensus has no objection.

Two directories in the Bitcoin Core source tree mirror this separation:

F.2Consensus Rules

Consensus rules are the invariants that define Bitcoin itself. They govern what makes a block (and the transactions inside it) valid. A handful of the important ones:

RuleValueSource
Max block weight4,000,000 WUMAX_BLOCK_WEIGHT in consensus/consensus.h
Max block sigops cost80,000MAX_BLOCK_SIGOPS_COST
Coinbase maturity100 blocksCOINBASE_MATURITY (see §14.6)
Subsidy schedulehalving every 210,000 blocksGetBlockSubsidy in validation.cpp
P2SH activationBIP 16 / block 173,805CheckInputScripts
Block version ≥ 4 enforcementBIP 65 (CLTV)IsSuperMajority (BIP 34-style) deployment
SegWitBIP 141/143/144Activated Aug 2017
TaprootBIP 341/342Activated Nov 2021

The consensus filter is unforgiving: if a block violates any of these rules, every full node on the network rejects it — forever. Historical consensus changes have required either a soft fork (tightening of the rules, backward-compatible) or a hard fork (loosening or incompatible change, not backward-compatible). Soft forks are the only mechanism Bitcoin has used to add new features (SegWit, Taproot, CLTV, CSV) since the early days.

F.3Standardness: What Nodes Will Relay

Standardness is a mempool policy. Every transaction a node receives over the p2p network is passed through IsStandardTx in src/policy/policy.cpp; failing transactions are dropped without being stored, relayed, or considered for inclusion in a block template.

The full function, reproduced from Bitcoin Core master:

bool IsStandardTx(const CTransaction& tx,
                  const std::optional<unsigned>& max_datacarrier_bytes,
                  bool permit_bare_multisig,
                  const CFeeRate& dust_relay_fee,
                  std::string& reason)
{
    if (tx.version > TX_MAX_STANDARD_VERSION ||
        tx.version < 1) {
        reason = "version";
        return false;
    }

    // Extremely large transactions with lots of inputs can cost the network
    // almost as much to process as they cost the sender in fees...
    unsigned int sz = GetTransactionWeight(tx);
    if (sz > MAX_STANDARD_TX_WEIGHT) {
        reason = "tx-size";
        return false;
    }

    for (const CTxIn& txin : tx.vin) {
        if (txin.scriptSig.size() > MAX_STANDARD_SCRIPTSIG_SIZE) {
            reason = "scriptsig-size";
            return false;
        }
        if (!txin.scriptSig.IsPushOnly()) {
            reason = "scriptsig-not-pushonly";
            return false;
        }
    }

    unsigned int datacarrier_bytes_left = max_datacarrier_bytes.value_or(0);
    TxoutType whichType;
    for (const CTxOut& txout : tx.vout) {
        if (!::IsStandard(txout.scriptPubKey, whichType)) {
            reason = "scriptpubkey";
            return false;
        }
        if (whichType == TxoutType::NULL_DATA) {
            unsigned int size = txout.scriptPubKey.size();
            if (size > datacarrier_bytes_left) {
                reason = "datacarrier";
                return false;
            }
            datacarrier_bytes_left -= size;
        } else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
            reason = "bare-multisig";
            return false;
        }
    }

    // Only MAX_DUST_OUTPUTS_PER_TX dust is permitted (on otherwise valid ephemeral dust)
    if (GetDust(tx, dust_relay_fee).size() > MAX_DUST_OUTPUTS_PER_TX) {
        reason = "dust";
        return false;
    }

    return true;
}

Every reason string corresponds to one of the standardness checks your node applies before it will gossip the transaction. The sections below walk through each category in turn.

F.3.1Version (reason = "version")

The transaction's version field must be between 1 and TX_MAX_STANDARD_VERSION = 3. Versions 1 and 2 are the historical norm; version 3 is the TRUC (Topologically Restricted Until Confirmation) policy introduced to give Lightning-Network fee-bumping tighter guarantees. Consensus itself places no constraint on the 4-byte version field — any value is consensus-valid; only relay policy narrows the range.

F.3.2Weight (reason = "tx-size")

MAX_STANDARD_TX_WEIGHT = 400,000 WU — exactly 10% of a block. Consensus allows a single transaction to fill 100% of a block (i.e., 4,000,000 WU), but relay policy caps each transaction at 400,000 WU to limit the damage a single adversarial transaction can do to the p2p network. If you want to broadcast a transaction above 400k WU, a miner must include it directly.

F.3.3ScriptSig Constraints

Two checks on every input's scriptSig:

F.3.4ScriptPubKey Type (reason = "scriptpubkey")

Each output's scriptPubKey must classify as one of a fixed list of TxoutTypes. Anything else — custom scripts, bare OP_CHECKLOCKTIMEVERIFY scripts, unclassified multi-op scripts — fails standardness. The allowed types:

TxoutTypePatternNotes
PUBKEY (P2PK)<pubkey> OP_CHECKSIGLegacy; rarely used
PUBKEYHASH (P2PKH)OP_DUP OP_HASH160 <h160> OP_EQUALVERIFY OP_CHECKSIGCh. 5
SCRIPTHASH (P2SH)OP_HASH160 <h160> OP_EQUALCh. 6 (BIP 16)
WITNESS_V0_KEYHASH (P2WPKH)OP_0 <h160>Ch. 9 (BIP 141)
WITNESS_V0_SCRIPTHASH (P2WSH)OP_0 <h256>Ch. 10
WITNESS_V1_TAPROOT (P2TR)OP_1 <h256>Ch. 12 (BIP 341)
MULTISIG (bare)OP_m <k1>..<kn> OP_n OP_CHECKMULTISIGOnly n ≤ 3 is standard
NULL_DATA (OP_RETURN)OP_RETURN <push>See §F.5

The classification itself happens in Solver() (src/script/solver.cpp), which matches the scriptPubKey bytes against these known templates.

F.3.5Bare Multisig (reason = "bare-multisig")

Bare multisig (MULTISIG) outputs are standard only when n ≤ 3:

if (whichType == TxoutType::MULTISIG) {
    unsigned char m = vSolutions.front()[0];
    unsigned char n = vSolutions.back()[0];
    // Support up to x-of-3 multisig txns as standard
    if (n < 1 || n > 3) return false;
    if (m < 1 || m > n) return false;
}

Larger multisig setups (5-of-7, 3-of-5, etc.) should use P2SH or P2WSH to move the multisig script into a witness/redeem script, where the scriptPubKey is a constant-size hash. This keeps UTXO set entries small — a 1-of-15 bare multisig creates a scriptPubKey of 15×34 + 3 = 513 bytes, while the equivalent P2WSH scriptPubKey is always 34 bytes.

F.4Dust and Output Values

An output is dust if its value is less than the cost to spend it. Bitcoin Core computes the threshold dynamically, based on output type and the dustRelayFee (default 3,000 sat/kvB):

CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
{
    // A typical spendable non-segwit txout is 34 bytes big, and will
    // need a CTxIn of at least 148 bytes to spend:
    // so dust is a spendable txout less than
    // 182 * dustRelayFee / 1000 (in satoshis).
    // 546 satoshis at the default rate of 3000 sat/kvB.
    // A typical spendable segwit P2WPKH txout is 31 bytes big, and will
    // need a CTxIn of at least 67 bytes to spend:
    // so dust is a spendable txout less than
    // 98 * dustRelayFee / 1000 (in satoshis).
    // 294 satoshis at the default rate of 3000 sat/kvB.
    ...
}

At the default fee rate, the common thresholds are:

Output typeDust threshold
P2PKH, P2SH (legacy)546 sats
P2WPKH (SegWit v0)294 sats
P2WSH (SegWit v0)330 sats
P2TR (SegWit v1)330 sats
OP_RETURN0 (always 0-value)

Current policy permits at most one dust output per transaction (MAX_DUST_OUTPUTS_PER_TX = 1), and only when that dust is ephemeral (spent within the same package). The dust rule is a policy guardrail against UTXO-set bloat — every unspent output lives in every node's chainstate database indefinitely (with a bounded RAM cache), and an output worth fewer sats than it costs to spend is economically a permanent liability for the network.

F.5OP_RETURN: A Policy in Flux

OP_RETURN outputs have always been consensus-valid (see §15.2) — they simply become prunable from the UTXO set. What's changed is the size Bitcoin Core is willing to relay.

VersionYearDefault datacarrier limit
0.9.0201440 bytes
0.11.0201583 bytes (80 data + push header)
30.0 mastercurrentMAX_STANDARD_TX_WEIGHT / 4 = 100,000 bytes

In current Bitcoin Core master, the default carrier size is:

static const unsigned int MAX_OP_RETURN_RELAY =
    MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR;

This relaxation is one of the most controversial policy changes in recent memory. Proponents argue that the previous 83-byte limit was trivially circumvented (ordinals, witness embedding) and served only to push data into worse locations. Opponents argue that any increase invites more "spam" on-chain. Notably, neither side is arguing about consensus — the debate is entirely about relay policy, which every node operator can override locally with -datacarriersize.

This is the standardness paradigm in miniature: the consensus rules haven't changed (they haven't needed to), but the social question of "what do we relay" is fought out release by release.

F.6Interactive: Would This Transaction Relay?

The tool below runs the same sequence of checks that IsStandardTx performs — in your browser, against whatever raw transaction hex you paste. It reports every pass and fail with the exact reason string Bitcoin Core would emit. Try pasting our Chapter 1 specimen (the 275-byte Block 170 P2PK spend), or any transaction from mempool.space's "raw hex" view.

Standardness Checker

Paste a raw transaction (hex):

Paste a hex transaction and click Check.
What the Checker Captures (and What It Doesn't)

This tool implements the main IsStandardTx checks: version, weight, scriptSig size and push-only, scriptPubKey classification, OP_RETURN data carrier, bare-multisig limits, and dust thresholds. It does not evaluate the full set of Bitcoin Core checks — missing are: mempool sigops cost (MAX_STANDARD_TX_SIGOPS_COST), non-mandatory script-verification flags (CLEANSTACK, MINIMALDATA, LOW_S), ancestor/descendant package limits, minimum feerate, and Taproot-specific witness constraints. A transaction that passes here is likely standard, not certified standard — the authoritative verdict comes from running it against a real bitcoind with testmempoolaccept.

F.7The Escape Hatches

A non-standard transaction cannot enter the public mempool, but it can still reach a block. Several pathways exist:

These escape hatches are why the OP_RETURN debate is mostly symbolic: a datacarrier limit is relaxed in one release, but even before the relaxation, anyone willing to pay a miner directly could already embed data by other means. Policy is a default, not a gate.

F.8Historical Evolution

Relay policy is always in motion. Selected milestones:

YearChangeEffect
2014OP_RETURN made standard (Core 0.9.0)Prunable data channel (40 B)
2015OP_RETURN limit raised to 83 BMore room for anchor-style protocols
2016SegWit v0 standardness (deployed with BIP 141)Pre-activation relay for P2WPKH/P2WSH
2022–2024mempoolfullrbf option (Core 24.0), default from 28.0Fee-bumping clarity
2021Taproot v1 standardness (with BIP 341/342)Pre-activation relay for P2TR
2024TRUC (v3) transactions addedLN fee-bumping safety
2024–2026Package relay + ephemeral dustCoordinated multi-tx submission
2025OP_RETURN datacarrier default relaxed to MAX_STANDARD_TX_WEIGHT / 4Policy-level concession to de facto on-chain data usage

None of these changes touched consensus. They all shipped as default-policy adjustments in successive Bitcoin Core releases, and any node operator can override them with command-line flags.

F.9Why This Distinction Matters

Three consequences follow from the consensus-vs-policy split:

  1. A standardness tightening is not a soft fork. When Core stops relaying bare multisig with n = 3, nothing changes at the consensus layer — miners can still include such outputs in blocks, and nodes accept those blocks. A soft fork requires adding new consensus rules that reject previously-valid blocks, not just refusing to relay some transactions.
  2. Policy changes do not require coordination. A miner who relaxes their local policy mines non-standard transactions alone — no network-wide signaling or majority is required. Conversely, a miner who tightens policy simply misses revenue the rest of the network happily collects.
  3. Consensus is a floor, policy is a ceiling. Consensus defines the outer boundary of what is possible. Policy defines the inner boundary of what most nodes are willing to participate in. The gap between the two is where every interesting debate about Bitcoin's direction happens.

F.10What We Learned

← Previous Next →