#29843 policy: Allow non-standard scripts with -acceptnonstdtxn=1 (test nets only)
https://github.com/bitcoin/bitcoin/pull/29843 · · +149/-55 in 6 files, 5 commits · labels: TX fees and policy
Goal
- Allow transactions with non-standard scripts into the mempool on test networks using -acceptnonstdtxn=1
- Let developers test proposed soft forks on testnets without having to maintain custom node forks
This pull request modifies the `-acceptnonstdtxn=1` option on test networks so that it skips non-mandatory script checks, allowing transactions that use opcodes such as OP_SUCCESS or OP_NOPx into the mempool. It distinguishes between block and mempool script checks in `CheckInputScripts` via an explicit enum and introduces compile-time and runtime checks ensuring consensus block script flags remain a subset of policy flags.
Problem: On test networks, developers and testers experimenting with future soft-fork features (such as OP_CAT or SIGHASH_APO) cannot get transactions into a standard Bitcoin Core mempool without maintaining custom forks like bitcoin-inquisition, because the node rejects non-mandatory script verify flags even when -acceptnonstdtxn=1 is specified.
Category: Mempool and policy (#5 of 10)
P3 · new feature
- P3 because it adds a useful developer feature to test non-standard scripts without off-tree patches
- Confined to test networks and does not fix a bug or affect mainnet behavior
P3 because it adds a useful developer-facing feature for testing non-standard and proposed soft-fork scripts in the mempool without maintaining off-tree patches. It is restricted to test networks and does not fix an active bug or consensus vulnerability on mainnet.
Membership: Changes mempool acceptance policy under -acceptnonstdtxn to skip non-mandatory script verification flags.
Factors: security/stability 0, bug 0, performance 0, user value 2, leverage 1
Category: Validation (#42 of 48)
P3 · cleanup
- P3 because it hardens the distinction between consensus and mempool policy script checks
- Enforces that consensus block script flags remain a strict subset of standard policy flags
P3 because it clarifies and hardens the distinction between block consensus script errors and mempool policy script errors in CheckInputScripts, while asserting that consensus flags remain a strict subset of standard script verify flags.
Membership: Refactors CheckInputScripts in src/validation.cpp to take an explicit CheckInputScriptsFor enum and adds GetAllConsensusScriptFlags to ChainstateManager.
Factors: security/stability 1, bug 0, performance 0, user value 0, leverage 1
Reviewability: Ready
- Reviewable now; CI is passing and open review feedback is a minor design question rather than a rework
The PR has passing CI, clean mergeability, and the open feedback from sedited is a minor design question rather than a blocking rework.
Author status: Active; last pushed updates in July 2026 addressing review comments, with one recent suggestion from sedited in September 2026 pending response.
Open concerns:
- sedited questioned whether the StandardScriptVerifyFlags consteval wrapper in GetBlockScriptFlags adds unnecessary complexity and could be replaced with a unit test.
Resolved concerns:
- luke-jr argued that altering -acceptnonstdtxn beyond its historical Knots behavior should require a new option value, but reviewers agreed existing testnet-only behavior does not require Knots compatibility.
- ismaelsadeeq proposed refactoring CheckInputScripts to return raw errors rather than passing caller context; ajtowns and sedited preferred an explicit enum parameter, which was implemented.
- instagibbs explored reporting block-level errors without caller enum differentiation, but agreed with ajtowns that tip-dependent differences justify explicit context.
Agreement: Mild
- Broad concept and approach support for enabling soft-fork testing on test networks
- Helpful for experimenting with future soft-fork features on test networks (benthecarman)
- Concept approval without stated reasons (1440000bytes, glozow, fjahr)
- Nonblocking objection: goes beyond historical Knots behavior and should use another value (luke-jr)
- Questioned whether a compile-time wrapper could be replaced with a unit test (sedited)
Strong concept and approach support; minor open question from sedited regarding compile-time check placement.
Multiple maintainers and contributors support enabling non-standard script acceptance for test networks, and earlier design disagreements over CheckInputScripts refactoring have converged.
- benthecarman: 'Concept ACK this would be nice for testing soft forks on test networks'
- sedited: 'Approach ACK. Read through the discussion again, and think this is the pragmatic solution.'
Objections:
| Reviewer | Kind | Harm | Status | Blocking | Author replied | Quote |
|---|---|---|---|---|---|---|
| luke-jr | interface | Deviates from the semantics of -acceptnonstdtxn established in Knots | open | no | no | 2024-04-21: 'Seems like this goes beyond the expected behaviour. Maybe make it =2 at least?' Settled: 2024-04-22: instagibbs noted 'Since these are test-network-only changes, are we required to preserve current behavior?' and discussion moved on. |
| ismaelsadeeq | approach | CheckInputScripts becomes brittle by knowing caller context rather than just returning verification errors | resolved | no | yes | 2026-03-29: 'I think the second commit adds some brittleness to the CheckInputScripts function; it now needs to know whether we are in block validation or individual transaction validation.' Settled: 2026-04-04: ismaelsadeeq noted 'I’m curious to hear other reviewers\' thoughts, though, not rigid on this at all' and sedited proposed the enum solution adopted in July 2026. |
| sedited | approach | Adds an intrusive compile-time type wrapper StandardScriptVerifyFlags inside GetBlockScriptFlags instead of testing in unit tests | open | no | no | 2026-09-17: 'It still seems confusing to me to introduce this type change here in a function that has nothing to do with standardness. Is this check really required in the first place? Maybe the invariant "GetBlockScriptFlags returns a subset of STANDARD_SCRIPT_VERIFY_FLAGS" can just be checked in a unit test instead?' |
Support:
- benthecarman: Helpful for testing soft forks on test networks
- sedited: Pragmatic solution for caller differentiation and script check verification
- ismaelsadeeq: Clarifies consensus vs standardness script verification distinctions
- glozow: Concept ACK for test network soft-fork testing enablement [not substantive]
- fjahr: Concept ACK [not substantive]
- 1440000bytes: Concept ACK [not substantive]
- instagibbs: logic looks correct
Participants: 1440000bytes (support), benthecarman (support), luke-jr (objection), glozow (support), instagibbs (support), twosatsmaxi (neutral), fjahr (support), sedited (support), ismaelsadeeq (support)
State derived from the lists: nonblocking objection open (luke-jr, sedited) (model's own read: Strong)
Review verdicts (DrahtBot): 0
- Approach ACK: sedited
- Concept ACK: benthecarman, glozow, fjahr, 1440000bytes, ismaelsadeeq
Files
77 lines under test/bench/ci.
- src/validation.cpp +83/-23
- src/test/txvalidationcache_tests.cpp +9/-15
- src/validation.h +21/-0
- test/functional/p2p_segwit.py +10/-11
- test/functional/p2p_invalid_tx.py +15/-5
- test/functional/data/invalid_txs.py +11/-1
Card
PR #29843 updates -acceptnonstdtxn=1 so that it permits non-mandatory script verify flag failures (such as OP_SUCCESS or OP_NOPx) into the mempool on test networks. This facilitates testing upcoming soft-fork proposals like OP_CAT without requiring custom client builds like inquisition. It also clarifies error categorization in CheckInputScripts by explicitly passing whether validation is for a block or mempool entry. Reviewers broadly support the concept, and the PR is ready for review with only a minor open question from sedited regarding a compile-time flag wrapper.