Skip to content

policy: P2MR stack-byte limit error code, spec, and oracle cases - #271

Merged
kiwidream merged 3 commits into
djh58/p2mr-stack-bytes-policyfrom
kiwidream/rg-257-stack-bytes-error
Oct 30, 2026
Merged

kiwidream merged 3 commits into
djh58/p2mr-stack-bytes-policyfrom
kiwidream/rg-257-stack-bytes-error

Conversation

@kiwidream

@kiwidream kiwidream commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Summary

Stacked on #263 (base djh58/p2mr-stack-bytes-policy). It closes three policy gaps in that PR. Refs #257.

1. Its own error code. SCRIPT_VERIFY_P2MR_STACK_BYTES failed with SCRIPT_ERR_STACK_SIZE, the error of the consensus 1,000-item limit, so a mempool rejection read Stack size limit exceeded for either limit. It now fails with SCRIPT_ERR_P2MR_STACK_BYTES:

mempool-script-verify-flag-failed (Standard P2MR stack byte limit exceeded)
  • The item limit is still checked first after each opcode, so a spend that breaks both limits on the same opcode reports SCRIPT_ERR_STACK_SIZE.
  • Limitation: under standard flags the mempool reports the first failure and does not re-run with consensus-only flags. That is existing behavior for every policy flag. So the new reason means "hit the byte limit", not "otherwise consensus-valid".

2. Spec (doc/consensus/p2mr-v1.md).

  • Section 10 now states that the 1 MiB limit is policy only, names the flag and the error, and explains why only scripts that copy stack elements can reach it.
  • Section 11: the row "over an initial-stack or runtime resource limit → Invalid" now says consensus runtime resource limit.
  • Section 11 gains a row for otherwise valid spends over the byte limit: consensus-valid, nonstandard, and signing/finalization reports them incomplete.

3. Conformance oracle and corpus.

  • The oracle's evaluator learns OP_DUP, OP_DROP, and an optional stack-byte limit after each opcode (evaluate_policy). It recomputes the full total each time, independently of the C++ incremental window accounting.
  • New runtime-stack-bytes resource kind. The oracle evaluates it under consensus and policy separately, instead of copying the consensus result into policy as it does for the other resource kinds.
  • Two boundary cases:
    • 1048576: standard.
    • 1048577: consensus-valid, policy SCRIPT_ERR_P2MR_STACK_BYTES.
  • Corpus regenerated; the manifest goes from 78 to 80 cases and the boundary file's digest changes.
  • The C++ consumer builds the same spend and checks both cases under consensus and standard flags.

Testing

  • Built locally.
  • Ran focused unit or functional tests for the changed area.
  • Ran lint or formatting checks relevant to this change.
  • Not run. Reason:

Built with cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_GUI=OFF (targets test_qbit qbitd qbit-cli). Results are at the PR head.

  • Unit: build/bin/test_qbit --run_test='script_p2mr_tests:script_tests:transaction_tests:txvalidationcache_tests:pqc_sigcache_tests:p2mr_datapqchash_tests:descriptor_p2mr_tests:psbt_p2mr_tests:script_standard_tests:sigopcount_tests:miniscript_tests:script_p2sh_tests:script_segwit_tests:txpackage_tests:mempool_tests:feebumper_tests:pqc_tests': no errors. This runs all 53 boundary cases under both consensus and standard flags.
  • Functional: test/functional/test_runner.py feature_p2mr.py passed, with the new reject reason.
  • Oracle:
    • cargo fmt -- --check and cargo test --locked --offline: 38 tests passed.
    • check-manifest and verify against src/test/data/p2mr_v1_manifest.json: 80 cases passed.
  • Mutation check: I flipped the 1048577 case's policy expectation to accepted in a scratch copy and re-digested the manifest. The oracle then failed with resource-runtime-stack-bytes-1048577: independently observed policy result mismatch.
  • Reproducibility: contrib/devtools/check-p2mr-v1-corpus-reproducible.sh passes.
  • Lint:
    • lint-qbit-public-docs, lint-files, lint-tests, lint-locale-dependence and lint-python-utf8-encoding pass.
    • lint-spelling and lint-python were skipped locally because codespell and lief are not installed.
  • Per commit: the first commit was built on its own, and script_p2mr_tests and feature_p2mr.py pass at it. The last commit only changes docs.
  • Not run: the fuzz binary, and Windows and macOS.

Target Branch

  • This PR targets main or a maintainer-requested release branch such as 0.1.x.

This PR is stacked on #263 and targets its branch, djh58/p2mr-stack-bytes-policy. Retarget it to 1.x.x once #263 merges.

Risk / Review Notes

  • Consensus, script, crypto, wallet, P2P, release, CI, or security-sensitive behavior changed.
  • No consensus, script, crypto, wallet, P2P, release, CI, or security-sensitive behavior changed.

Notes:

  • No consensus change. Only the error returned by the policy flag changes. MANDATORY_SCRIPT_VERIFY_FLAGS, GetBlockScriptFlags and every consensus expectation in the corpus are unchanged.
  • ScriptError numbering. The new value sits after SCRIPT_ERR_P2MR_CHECKSIG, which shifts the values after it. Nothing persists or exposes them numerically.
  • Corpus compatibility. schema_version stays 1 because the case shape is unchanged. Strict consumers fail closed on the new kind by design, and both in-repo consumers are updated here.
  • Release evidence. The manifest digest changes, so the v1.0.1 release evidence must use the new manifest. The v1.0.0 trust record is unaffected.
  • Reject text. policy: bound P2MR runtime stack bytes #263's Stack size limit exceeded text was never released, so no released behavior changes.

Docs / Process Impact

Choose exactly one:

  • I updated public docs because this PR changes user-visible behavior, integration guidance, release/process guidance, or expected validation.
  • No public docs update needed. Reason:

Updated sections 10 and 11 of doc/consensus/p2mr-v1.md and the oracle README. The v1.0.1 release notes (#181) should quote the new reject reason together with the standardness rule from #263.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

kiwidream and others added 3 commits October 30, 2026 11:24
SCRIPT_VERIFY_P2MR_STACK_BYTES failed with SCRIPT_ERR_STACK_SIZE, the
error of the consensus 1,000-item stack limit. A mempool rejection then
read "Stack size limit exceeded" whether the spend broke the policy byte
limit or the consensus item limit.

Add SCRIPT_ERR_P2MR_STACK_BYTES, "Standard P2MR stack byte limit
exceeded", and return it when the byte limit is exceeded. The consensus
item limit is checked first after each opcode, so a spend that breaks
both on the same opcode still reports SCRIPT_ERR_STACK_SIZE.

Refs #257

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The conformance oracle derived each resource case's policy result from
its consensus result, so it could not express a policy-only limit, and
the corpus had no case for the 1 MiB runtime stack-byte limit.

Teach the oracle's evaluator OP_DUP, OP_DROP and an optional limit on
stack bytes after each opcode. Add a runtime-stack-bytes resource kind
that the oracle evaluates under consensus and policy separately, with
boundary cases at exactly 1 MiB (standard) and 1 MiB plus one byte
(consensus-valid, nonstandard with SCRIPT_ERR_P2MR_STACK_BYTES).
Regenerate the boundary corpus and the manifest.

The C++ consumer builds the same spend and checks both cases under
consensus and standard flags.

Refs #257

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Section 11 said a known leaf over any runtime resource limit is
consensus-invalid, which does not hold for the policy-only 1 MiB
stack-byte limit. Narrow that row to consensus limits, add a row for
otherwise valid spends over the byte limit, and describe the policy
check and its error in section 10.

Refs #257

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-30T15:33:05.822921Z ba62cfc Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kiwidream

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: ba62cfcd71

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@kiwidream
kiwidream added this pull request to stack #273 October 30, 2026 15:48
@djh58
djh58 self-requested a review October 30, 2026 16:16
@kiwidream
kiwidream merged commit ba62cfc into 1.x.x Oct 30, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants