Skip to content

fix: graceful failures in verifier code paths + other fixes#22311

Merged
iakovenkos merged 10 commits intomerge-train/barretenbergfrom
claudebox/6a1ba966035b66be-3
Apr 6, 2026
Merged

fix: graceful failures in verifier code paths + other fixes#22311
iakovenkos merged 10 commits intomerge-train/barretenbergfrom
claudebox/6a1ba966035b66be-3

Conversation

@AztecBot
Copy link
Copy Markdown
Collaborator

@AztecBot AztecBot commented Apr 3, 2026

Summary

Hardens barretenberg verifier code paths and API boundaries based on security review findings.

Verifier robustness

  • Replace BB_ASSERT with context-appropriate failures in verifier code paths — throw_or_abort for parsing/structural invariants, return false for native verification failures, circuit constraints for recursive verifiers
  • Move IPA SRS size check before circuit construction in full_verify_recursive (fail early on misconfiguration)
  • Remove redundant witness-value comparison in recursive IPA verifier (assert_equal is the real enforcement)
  • Guard unsigned underflow in batched translator verifier's num_public_inputs derivation

Input validation

  • 2513: Reject non-canonical field encodings in MsgPack deserialization (value >= modulus now throws instead of silently reducing)
  • 2501: Reject trailing data in ChonkProof MsgPack deserialization (consistent with hardened PrivateExecutionStepRaw loaders)

API state machine fixes

  • 2504: ChonkStart: clear stale loaded_circuit_* state when starting a new session, preventing silent reuse of circuits from a prior session
  • 2509: ChonkAccumulate: clear loaded state immediately after move, preventing use-after-move on retry if a later step throws

Debug

  • 2479: Fix off-by-one in has_last_app_been_accumulated flag (num_circuits - 4num_circuits - 3), debug-only

Tests

  • 2513: Regression test for non-canonical MsgPack field encoding rejection (all 6 field types)
  • 2493: Regression test for translator NonNativeFieldRelation accumulator alias attack

@AztecBot AztecBot added ci-draft Run CI on draft PRs. claudebox Owned by claudebox. it can push to this PR. labels Apr 3, 2026
Convert BB_ASSERT/BB_ASSERT_EQ/BB_ASSERT_LTE calls in verifier code
paths to return false or throw_or_abort instead of panicking. Malformed
proofs should cause verification to fail gracefully, not crash the
process via SIGABRT.

Changes by area:
- IPA (ipa.hpp): 5 assertions in reduce_verify_internal_native,
  batch_reduce_verify, and reduce_verify_internal_recursive now return
  false on invalid input instead of asserting
- Translator verifier: 4 size-check assertions now return
  ReductionResult with reduction_succeeded=false
- KZG: MSM size assertion converted to info() warning
- Shplonk: constructor assertion converted to explicit throw_or_abort
- Shplemini: 2 assertions converted to graceful handling
- Proof compression: 11 assertions in decompress_chonk_proof converted
  to explicit throw_or_abort with descriptive messages
- ChonkProof: from_field_elements assertion converted to throw_or_abort
- Transcript: 2 bounds-check assertions in receive_from_prover and
  deserialize_from_buffer converted to explicit throw_or_abort
@AztecBot AztecBot force-pushed the claudebox/6a1ba966035b66be-3 branch from 816473c to d026957 Compare April 4, 2026 17:37
@iakovenkos iakovenkos marked this pull request as ready for review April 6, 2026 11:40
- IPA recursive: move SRS check before circuit construction, remove
  redundant witness-value G_zero comparison (assert_equal suffices)
- KZG: throw_or_abort for MSM size mismatch (structural invariant)
- Shplemini: throw_or_abort for commitment mismatch and ZK requirement
- Translator: throw_or_abort for PCS size mismatch (compile-time invariant)
msgpack_unpack now checks that the raw value is < modulus before
converting to Montgomery form, closing a proof-boundary inconsistency
where MsgPack paths accepted non-canonical encodings that stricter
paths (concatenate_proof, proof compression) would reject.
Move cleanup of loaded_circuit_constraints, loaded_circuit_vk, and
loaded_circuit_name to immediately after extracting their values,
before any step that can throw. Previously, a failure in VK validation,
circuit creation, or accumulation would leave the request with a
moved-from optional that still reports has_value()==true, allowing a
subsequent ChonkAccumulate to bypass the ChonkLoad guard and operate
on poisoned state.
ChonkStart now resets loaded_circuit_name, loaded_circuit_constraints,
and loaded_circuit_vk when beginning a new session. Previously, a
circuit loaded in a prior session would survive across ChonkStart
calls, allowing ChonkAccumulate to silently reuse stale state without
requiring a fresh ChonkLoad.
Use the offset-tracking msgpack::unpack overload and verify that the
entire buffer was consumed, consistent with the hardened pattern
already used in PrivateExecutionStepRaw loaders.
Add a size check before subtracting LENGTH_WITHOUT_PUB_INPUTS from
the MegaZK proof size, matching the existing guard in UltraVerifier.
Without this, a truncated proof would cause size_t underflow and an
obscure crash deep in OinkVerifier rather than a clean early error.
The has_last_app_been_accumulated flag used num_circuits - 4 but
the last app is at position num_circuits - 3 (pre-increment). This
caused the native verifier accumulator hash to never be updated for
the last app, producing misleading debug output. Debug-only code,
no production impact.
…NativeFieldRelation

Add negative test that applies the (acc += q, quotient -= 1) mutation at
RESULT_ROW and verifies the higher carry check (subrelation 1) catches it.
Also populate evaluation_input_x and batching_challenge_v in the existing
accumulator transfer test helper so it supports NonNativeField checks.
Random bytes can now trigger multiple exception types: msgpack
type_error, runtime_error from trailing data check, or runtime_error
from non-canonical field encoding. Use EXPECT_ANY_THROW instead of
checking for a specific exception type.
@iakovenkos iakovenkos self-assigned this Apr 6, 2026
@iakovenkos iakovenkos changed the title fix: replace BB_ASSERT with graceful failures in verifier code paths fix: graceful failures in verifier code paths + other fixes Apr 6, 2026
@iakovenkos iakovenkos requested a review from suyash67 April 6, 2026 13:13
static bool full_verify_recursive(const VK& vk, const OpeningClaim<Curve>& opening_claim, auto& transcript)
requires Curve::is_stdlib_type
{
// Check SRS size up front before any circuit construction
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

* Replacing current_acc with current_acc + p and quotient with quotient - 1 preserves this
* equation, plus its mod-2^272 and mod-r projections. However, the limb-level carry witnesses
* (relation_wide_limbs) become stale: the new intermediate sums at limbs 2-3 no longer match
* the old high carry value, and subrelation 1 (higher mod 2^136 check) detects the mismatch.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good test

Copy link
Copy Markdown
Contributor

@suyash67 suyash67 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, thanks for adding the failure test case in translator!

@iakovenkos iakovenkos merged commit 5f09c55 into merge-train/barretenberg Apr 6, 2026
16 checks passed
@iakovenkos iakovenkos deleted the claudebox/6a1ba966035b66be-3 branch April 6, 2026 14:30
AztecBot added a commit that referenced this pull request Apr 6, 2026
…ormat

Fr::from_u64 was storing values in little-endian, but the C++ field::msgpack_unpack
expects big-endian (network byte order). This was masked before because the C++ side
silently reduced non-canonical values via to_montgomery_form_reduced(). After #22311
added strict non-canonical field validation (throwing for values >= modulus), values
like Fr::from_u64(123) produce 0x7B<<248 which exceeds the BN254 Fr modulus (0x30...)
and cause a C++ exception that propagates through the FFI boundary, aborting the Rust
test process.
ludamad pushed a commit that referenced this pull request Apr 6, 2026
…2233)

## Summary

Fixes bb-rs test failure introduced by #22311 (graceful failures in
verifier code paths).

`Fr::from_u64` was storing values in **little-endian**, but the C++
`field::msgpack_unpack` expects **big-endian** (network byte order).
This was masked before because the C++ side silently reduced
non-canonical values via `to_montgomery_form_reduced()`. After #22311
added strict non-canonical field validation (throwing for values >=
modulus), values like `Fr::from_u64(123)` produce `0x7B<<248` which
exceeds the BN254 Fr modulus (`0x30644e72...`) and cause a C++ exception
that propagates through the FFI boundary, aborting the Rust test process
with "Rust cannot catch foreign exceptions".

## Fix

One-line change: store the u64 value in bytes 24..32 as big-endian
instead of bytes 0..8 as little-endian.

## Test plan

- [x] Reproduced failure locally — `test_pedersen_commit_deterministic`
crashes with SIGABRT
- [x] Applied fix — all 70 bb-rs tests pass (3 perf tests ignored)
- [ ] `./bootstrap.sh ci` running
ludamad pushed a commit that referenced this pull request Apr 6, 2026
…nical field encoding (#22333)

## Summary

Fixes CI failure in `merge-train/barretenberg` caused by the interaction
of #22233 (Fr::from_u64 big-endian encoding) and #22311 (strict
non-canonical field validation).

The `corruptProofFields()` test helper was flipping high-order bytes
(indices 0,1) of field elements, creating values exceeding the BN254 Fr
modulus. The strict validation now rejects these at deserialization time
with `non-canonical encoding (value >= modulus)` before they reach the
verifier.

**Fix**: Flip low-order bytes (indices 30,31) instead — still corrupts
the proof but keeps field values canonical.

## Test plan
- [x] `batch_verifier.test.ts` — all 4 tests pass locally (previously 1
failing)

ClaudeBox log: https://claudebox.work/s/e5146dc92fea29dd?run=1
github-merge-queue bot pushed a commit that referenced this pull request Apr 6, 2026
BEGIN_COMMIT_OVERRIDE
fix: reject VK with log_circuit_size=0 in UltraKeccak verifier (#22319)
chore: merkle tree audit 2 (#21475)
fix: graceful failures in verifier code paths + other fixes (#22311)
fix: Fr::from_u64 big-endian encoding to match C++ msgpack format
(#22233)
fix: corrupt low-order bytes in batch verifier test to avoid
non-canonical field encoding (#22333)
fix: skip MsgpackRejectsNonCanonical test in WASM builds (#22335)
END_COMMIT_OVERRIDE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-draft Run CI on draft PRs. claudebox Owned by claudebox. it can push to this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants