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.
Every Bitcoin node runs two filters on every transaction it sees:
| Filter | Question asked | Enforced by | Changing it requires… |
|---|---|---|---|
| Consensus | Is this transaction allowed in a valid block? | Every full node, forever | A network-wide fork |
| Standardness (relay policy) | Will this node relay it and accept it into its mempool? | Only nodes running that policy | Just 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 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:
src/consensus/ — rules that determine block validity. Changes here require a network-wide fork.src/policy/ — rules that determine what a node will relay and mempool. Changes here ship in any release and affect only nodes that adopt them.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:
| Rule | Value | Source |
|---|---|---|
| Max block weight | 4,000,000 WU | MAX_BLOCK_WEIGHT in consensus/consensus.h |
| Max block sigops cost | 80,000 | MAX_BLOCK_SIGOPS_COST |
| Coinbase maturity | 100 blocks | COINBASE_MATURITY (see §14.6) |
| Subsidy schedule | halving every 210,000 blocks | GetBlockSubsidy in validation.cpp |
| P2SH activation | BIP 16 / block 173,805 | CheckInputScripts |
| Block version ≥ 4 enforcement | BIP 65 (CLTV) | IsSuperMajority (BIP 34-style) deployment |
| SegWit | BIP 141/143/144 | Activated Aug 2017 |
| Taproot | BIP 341/342 | Activated 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.
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.
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.
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.
Two checks on every input's scriptSig:
scriptSig.size() ≤ MAX_STANDARD_SCRIPTSIG_SIZE = 1650 bytes. Derived from the worst-case of a 15-of-15 P2SH multisig. Consensus allows scriptSigs up to 10,000 bytes; policy caps at 1650.scriptSig.IsPushOnly(). The scriptSig may only contain push opcodes — no arithmetic, no control flow, no anything else. The rationale, from the days before SegWit, was to prevent malleability and keep spending logic entirely in the scriptPubKey.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:
| TxoutType | Pattern | Notes |
|---|---|---|
PUBKEY (P2PK) | <pubkey> OP_CHECKSIG | Legacy; rarely used |
PUBKEYHASH (P2PKH) | OP_DUP OP_HASH160 <h160> OP_EQUALVERIFY OP_CHECKSIG | Ch. 5 |
SCRIPTHASH (P2SH) | OP_HASH160 <h160> OP_EQUAL | Ch. 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_CHECKMULTISIG | Only 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.
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.
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 type | Dust threshold |
|---|---|
| P2PKH, P2SH (legacy) | 546 sats |
| P2WPKH (SegWit v0) | 294 sats |
| P2WSH (SegWit v0) | 330 sats |
| P2TR (SegWit v1) | 330 sats |
| OP_RETURN | 0 (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.
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.
| Version | Year | Default datacarrier limit |
|---|---|---|
| 0.9.0 | 2014 | 40 bytes |
| 0.11.0 | 2015 | 83 bytes (80 data + push header) |
| 30.0 master | current | MAX_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.
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.
Paste a raw transaction (hex):
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.
A non-standard transaction cannot enter the public mempool, but it can still reach a block. Several pathways exist:
-permitbaremultisig=1, -datacarriersize=N, etc.) will accept and mine transactions the default-policy majority rejects. Consensus is not touched; only the miner's own policy is.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.
Relay policy is always in motion. Selected milestones:
| Year | Change | Effect |
|---|---|---|
| 2014 | OP_RETURN made standard (Core 0.9.0) | Prunable data channel (40 B) |
| 2015 | OP_RETURN limit raised to 83 B | More room for anchor-style protocols |
| 2016 | SegWit v0 standardness (deployed with BIP 141) | Pre-activation relay for P2WPKH/P2WSH |
| 2022–2024 | mempoolfullrbf option (Core 24.0), default from 28.0 | Fee-bumping clarity |
| 2021 | Taproot v1 standardness (with BIP 341/342) | Pre-activation relay for P2TR |
| 2024 | TRUC (v3) transactions added | LN fee-bumping safety |
| 2024–2026 | Package relay + ephemeral dust | Coordinated multi-tx submission |
| 2025 | OP_RETURN datacarrier default relaxed to MAX_STANDARD_TX_WEIGHT / 4 | Policy-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.
Three consequences follow from the consensus-vs-policy split:
src/consensus/ and src/policy/ respectively.IsStandardTx runs a tight sequence of checks — version, weight, scriptSig constraints, scriptPubKey classification, datacarrier size, bare-multisig limits, and dust.TxoutTypes are limited to P2PK, P2PKH, P2SH, P2WPKH, P2WSH, P2TR, NULL_DATA, MULTISIG with n ≤ 3, and WITNESS_UNKNOWN (future witness versions v1+, 2–40-byte programs — how pre-activation Taproot sends relayed).dustRelayFee: an output worth less than it costs to spend is rejected by default (546 sats for legacy, 294 sats for P2WPKH, 330 sats for P2WSH and Taproot at 3,000 sat/kvB).