Skip to content

Conversation

@hero78119
Copy link
Collaborator

@hero78119 hero78119 commented Jan 12, 2026

To address #1212 (Follow up on #1084)

change highlights

  • hint/heap circuit check num_instances == mem_length via adding zero constraint assert_eq(pi[num_instances], pi[mem_length]). Also make num_instance could be query from public_values.
  • verifier agnostic: support mem continuation check, but encaptulate heap, hint within RV32imMemStateConfig, for those terms are tightly couple with riv32im. This design keep the door open to support other ISA.
  • (recursion) introduce field range, less-than, larger-or-equal when build recursion circuit
  • (recursion soundness) derive sum_num_instances, log_num_instance from num_instances, avoid hint mismatched for malicious manipulation
  • added missing check in (recursion) verifier
    • shard id == 0 && init_mem_table => assert_eq!(chip_proofs.len(), 1)
    • shard id > 0 && init_mem_table => assert_eq!(chip_proofs.len(), 0)
    • dynamic_mem_table => assert_eq!(chip_proofs.len(), 0 or 1)
  • move heap to lower address space to assure "2 * heap.end < Babybear Prime"

benchmark

it shows a negligible overhead in 23817600 e2e

Stage Before After Δ Change
reth-block (total) 195 s · 100.00% 196 s · 100.00% +1 s
recursion.compress_to_root_proof 56.6 s · 9.04% / 28.99% 57.3 s · 9.26% / 29.29% +0.7 s

"HeapTable"
}

fn max_len(params: &ProgramParams) -> usize {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

no logic change, just make function impl order follow trait

"HintsTable"
}

fn max_len(params: &ProgramParams) -> usize {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

no logic change, just make function impl order follow trait

name_fn: N,
assert_zero_expr: Expression<E>,
) -> Result<(), CircuitBuilderError> {
assert!(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

To check assert_eq(public_value[i], public_value[j]) within constrain, both are scalar thus degree is 0

@hero78119 hero78119 requested a review from kunxian-xia January 13, 2026 08:21
let chip_proofs =
builder.get(&zkvm_proof_input.chip_proofs, num_chips_verified.get_var());

let chip_proofs_len = chip_proofs.len();
Copy link
Collaborator Author

@hero78119 hero78119 Jan 13, 2026

Choose a reason for hiding this comment

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

Soundness fix: this logic present in rust verifier but not in recursion verifier

.then(|builder| {
builder.assert_usize_eq(chip_proofs_len.clone(), Usize::from(1));
});
} else if circuit_vk.get_cs().with_omc_init_dyn() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

dynamic init table only allow 1 chip proof per shard

@hero78119 hero78119 force-pushed the feat/dynamic_heap_hint_check branch from 97f5680 to d87ea19 Compare January 13, 2026 14:24
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.

3 participants