- The production default is
native(validation.engine = "native"). - Getting started owns the option spelling and resolution order.
- A different production default requires measured product-cell promotion evidence (
docs/contracts/test-evidence.mdowns the evidence rules). - A compiled
kernelcapability, a microbenchmark, or a historical verdict does not change the default.
Interpreter::execute_with_prevoutsandPreparedTransaction::verify_inputincrates/script/src/interpreter.rsverify every consensus spend class.- The functions verify legacy and P2SH through
eval::eval_script. - The functions verify SegWit v0 through BIP143.
- The functions verify Taproot key-path and script-path through local BIP341/BIP342.
crates/consensus/src/verify_tx.rsroutes verification throughverify_input_script_native(prepared, input_index, flags, signature_cache).- Every build compiles this function, including
kernelbuilds wherevalidation.engine = "native"still reaches it. - Block and transaction verification retain one native sighash cache and ordered prevout set per prepared transaction.
- Transaction aggregates initialize once across parallel input checks.
- Script, input index, hash mode, annex, and code-separator context remain local to each check.
- Preparation validates prevout count and each outpoint against the transaction input before script evaluation.
- An outpoint mismatch is a caller-wiring error, not a script verdict.
- The native owner retains owned outputs against an immutable borrowed transaction after this check.
- Block preparation transfers resolved outputs into that owner.
- Borrowed callers clone their outputs when constructing the owner.
- Core
script_tests.json,tx_valid.json, andtx_invalid.jsonnative columns pin zero mismatches on runnable rows incrates/script/tests/core_vectors.rs. - The columns pin skip counts and skip-reason allow-lists so silent coverage loss cannot remain green.
- The only accepted
script_testsskip is a one-string prose/section header. - The only accepted
tx_invalidskip isBADTX, which failsCheckTransactionbefore script verification. tx_validaccepts no skips.
- Live block rules and context-free revalidation share the consensus-owned transaction structure and aggregate legacy sigop checks in
verify_block.rs. - Every transaction, including coinbase, MUST pass these checks before the PoW-valid announce hook.
- Coinbase-only shortcuts, script caches, window proofs, AssumeValid, and replay provenance do not exempt a block from these checks.
- Proposal and commit both enforce absolute transaction finality using the same height and locktime cutoff, including coinbase.
- Proposals retain their lack of commit and publication effects and their PoW and signet exceptions.
- Early announcement is not a commit receipt.
- Contextual P2SH and witness sigop checks, input-script checks, and coinbase reward checks can still reject a block after the hook.
- A later connect failure does not retract that announcement.
- Tapscript signature messages commit to the zero-based decoded opcode index of the last executed
OP_CODESEPARATOR, or0xffffffffif none executed (BIP342). - Each push counts once regardless of payload length.
- Parsed instructions in skipped branches also count, but their separators do not replace the last executed separator.
- Legacy and SegWit v0 byte-based
scriptCodeslicing and legacy-only FindAndDelete remain unchanged. - Bare P2TR is recognized in the existing witness-program path when witness verification is active.
- Taproot verification runs only with its activation flag.
- A recognized v1/32-byte program before activation succeeds even with
DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM. - Wrapped v1 and other program sizes retain their upgradeable-program policy.
- The former generic-version path incorrectly applied that policy to inactive native P2TR.
- ScriptSig push-only checks and script evaluation errors precede the native-witness empty-scriptSig check.
- A push-only nonempty scriptSig fails
WITNESS_MALLEATEDfor both key-path and script-path spends. - Key-path and tapscript signatures use the same native Schnorr checker.
- A 64-byte key-path signature selects
SIGHASH_DEFAULT. - A 65-byte signature MUST append one of
01,02,03,81,82, or83. - An appended
00byte is forbidden. - Malformed suffixes and invalid sizes fail before signature verification.
- Annex handling remains per input and enters the existing BIP341 sighash.
- After script-path commitment and leaf-version checks, the opcode parser scans tapscript for
OP_SUCCESS. OP_SUCCESSbypasses initial stack count limits, element limits, evaluation, and final clean-stack checks.- A malformed push before
OP_SUCCESSfails closed. - Bytes inside pushes are data, not opcodes.
- Policy rule
DISCOURAGE_OP_SUCCESSfails before stack limits. - This rule corrects the former placement inside evaluation, which rejected consensus-valid success paths.
- This rule corrects the former native P2TR fast path that bypassed scriptSig validation.
- That former path passed all 65 bytes to a 64-byte Schnorr parser.
- Spends with nonempty scriptSig are rejected.
- Correctly signed nondefault hash modes are accepted.
- Network activation heights, flag definitions, and the default validation engine are unchanged.
crates/script/tests/taproot_spend_rules.rstests rust-bitcoin signatures and control blocks against both complete-prevout entry points.- The tests verify flag activation, wrapped-v1 rules, and error-order cases.
overhaul_process_harness::taproot_spend_casescompares 40 transaction signature and scriptSig cases, 28OP_SUCCESScases, and 48 opcode-position signature cases.- The harness runs native and Core 31.1 block validation over identical funded regtest histories.
- Block proposals isolate consensus from annex relay policy.
- Fixture keys exist only in test targets.
- No performance claim or production signing capability follows from these checks.
- The opcode-position fixtures use independent rust-bitcoin signing and cover
CHECKSIG,CHECKSIGVERIFY, andCHECKSIGADD, multi-byte pushes, skipped branches, multiple separators, and wrong-position signatures. - A
kernel-gated test intaproot_spend_rulescompares these same fixtures to the Kernel engine.
PreparedAdmission::verify_scriptsconstructs a localSignatureCache.- Native verification shares this cache across the
STANDARDpass and the next-block script pass. - This cache reuses positive cryptographic signature results for one transaction across both passes.
PreparedTransaction::verify_inputaccepts an optional&SignatureCacheargument.- The prepared transaction does not store the cache reference.
- The prepared transaction remains
Syncand shareable across parallel block input checks. - Block verification and uncached callers pass
None. - The cache MUST enforce a hard capacity limit of 64 entries.
- This limit is an independent resource bound, not a configuration setting or policy rule.
- At capacity, existing entries remain valid and continue to hit.
- The cache refuses new distinct entries at capacity and never evicts entries.
- The trust boundary is strictly positive-only.
- The cache stores only keys for successful signature verifications.
- Verification failures MUST never be stored.
- A cache hit skips only the
secp256k1group operation. - Every check still executes flag-dependent rules, signature and public key encodings, and sighash calculations.
- Every check still executes script evaluation steps and
NULLFAILrequirements. - Keys use unambiguous 32-byte digests with domain tags, algorithm prefixes, length-prefixed bytes, and sighash messages.
ValidationEngine::Kernelignores the signature cache and verifies scripts independently.- The cache is serial admission-local state wrapped in a
RefCell. - The cache exists only for the duration of
PreparedAdmission::verify_scripts. - The runtime drops the cache immediately when admission verification completes.
- Entries MUST never persist into mempool storage, blocks, or chain state.
ScriptExecutionCacheremains the sole owner of admission-to-block reuse.ScriptExecutionCacheis a long-lived, thread-safe cache shared between the mempool gateway and block connect.- It stores whole transaction execution outcomes keyed by witness transaction id and verify flags.
- In contrast,
SignatureCacheis temporary and single-threaded. - It reuses individual signature operations only between the two admission passes of a single transaction.
bin/bitcoin-rsdefault features MUST befjall,redb, andzmq.- Default features MUST never include
kernel. --features kernelmeans bitcoinkernel support is compiled in on the binary.- The Compose image
Dockerfilebuildsfjall,kernel. - Compiling
kerneldoes not select the engine. - Selection is
validation.engine = "kernel"(--validation-engine kernel,BITCOIN_RS_VALIDATION_ENGINE=kernel, or TOMLvalidation_engine = "kernel"). - The shipped image selects
kernelat the config-file layer (/etc/bitcoin-rs/default.toml, handed to the node with--config). - Bare
docker runkeeps historical kernel behavior. - An environment override or mounted config file overrides defaults under precedence (defaults -> file -> environment -> CLI).
- A CLI override replaces
CMDwholesale under docker semantics (runningbitcoin-rs <args>instead of the shipped argument list). - The CLI override MUST repeat the full
--config --data-dir --p2p-listenset. - The kernel-free default keeps
kernelout of every manifest default. - This rule is not a C++-free claim.
- The default build compiles bundled ZeroMQ C++ from source.
- The build needs C/C++ compilers plus
ar(see getting-started prerequisites). - Changing the production default engine under
VAL-01does not addkernelto any manifest default.
- Configuration, backend metadata, native/kernel capability, and startup failure tests own selection and refusal behavior.
- CI and provisioned reference campaigns own execution evidence.
- Compiling a capability does not select it at runtime.
- Compiling a capability does not establish consensus parity.
- Permanent tests MUST follow the Core 31.1 product reference (
REF-02in reference-set.md). - The retarget timespan MUST clamp to between 1/4 and 4x the target.
- Testnet allows a minimum-difficulty exception after a gap over 20 minutes (1,800 s).
- Timely blocks MUST inherit the last non-minimum target.
- Retarget boundaries MUST take precedence over that exception.
- Rules map to Core
GetNextWorkRequiredandCalculateNextWorkRequired. - Update contract and reference identity together on consensus review.