Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
84c52d7
inline ec_scalar chip into ecsm
jotabulacios Jun 30, 2026
0547f08
Add xG range check in the ECSM AIR
jotabulacios Jun 30, 2026
39046cc
Make ECSM memory interaction timestamps disjoint
jotabulacios Jun 30, 2026
8eca0e7
Extend q1 range check to all 33 bytes
jotabulacios Jun 30, 2026
f56b29e
Fix ECDAS padding and gate R·P term with μ
jotabulacios Jun 30, 2026
270356a
Add curve identifier to ECDAS bus
jotabulacios Jun 30, 2026
1cb8988
Merge branch 'main' into feat/ecsm-spec-update
jotabulacios Jun 30, 2026
2b843fa
Merge branch 'main' into feat/ecsm-spec-update
jotabulacios Jun 30, 2026
53e31bd
Restore IS_BIT on q1[32] and fix stale executor comment
jotabulacios Jul 1, 2026
cd41217
Include XgLtP in the overflow carry constraint test loop
jotabulacios Jul 1, 2026
932ed3b
Fix stale docs, q1 loop trap comment, k_bit IS_BIT test gap
jotabulacios Jul 2, 2026
527b684
Add KBitsZeroOnPadding and extend ECSM tests
jotabulacios Jul 3, 2026
0c8dd0b
fix lint
jotabulacios Jul 3, 2026
9a5619f
ECSM: add KBitsZeroOnPadding, µP² gate, x10 T+2
jotabulacios Jul 3, 2026
9e6ba1c
Merge main; reimplement ECSM/ECDAS on new IR
jotabulacios Jul 6, 2026
f7bc5dc
Explain ECSM operand-overlap guard rationale
jotabulacios Jul 6, 2026
1f0ce43
docs(ecsm): correct stale column-count comment (~427 -> 667)
diegokingston Jul 8, 2026
f516c20
docs(ecdas): note yR relation is also mu-gated
diegokingston Jul 8, 2026
5144dde
perf(ecsm): factor mu out of the Yg p^2 convolution sum
diegokingston Jul 8, 2026
860e323
Merge pull request #796 from yetanotherco/review/ecsm-ecdas-corrections
jotabulacios Jul 8, 2026
df234a6
solve conlficts
jotabulacios Jul 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crypto/ecsm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! This crate is shared by the executor (which needs `k·G`'s x-coordinate to write back
//! to guest memory) and the prover (which replays the full double-and-add sequence to
//! fill the ECSM / ECDAS / EC_SCALAR trace witnesses). Both entry points compute the same
//! fill the ECSM / ECDAS trace witnesses). Both entry points compute the same
//! `k·G` over the audited `k256` curve arithmetic — the executor via `k256`'s scalar
//! multiplication, the prover via a projective double-and-add replay — so the x-coordinate
//! they write/prove agrees. It is also independent of the `yG` root: both recover the same
Expand Down
4 changes: 4 additions & 0 deletions crypto/ecsm/src/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub struct EcsmWitness {
pub q1: [u8; 33],
/// carries for the `yG` relation
pub c1: [i64; 64],
/// `(xG - p) mod 2^256`
pub x_g_sub_p: [u8; 32],
/// `(k - N) mod 2^256`
pub k_sub_n: [u8; 32],
/// `(xR - p) mod 2^256`
Expand Down Expand Up @@ -314,6 +316,7 @@ pub fn compute_witness(k_le: &[u8; 32], xg_le: &[u8; 32]) -> Result<EcsmWitness,
// --- scalar range data ---
let len_k = crate::curve::msb_position(&k) as u8;
let two_256 = BigUint::from(1u8) << 256u32;
let x_g_sub_p = to_le_32(&((&two_256 + &g.x) - p())); // xG < p
let k_sub_n = to_le_32(&((&two_256 + &k) - n())); // k < N

// --- double/add replay ---
Expand All @@ -336,6 +339,7 @@ pub fn compute_witness(k_le: &[u8; 32], xg_le: &[u8; 32]) -> Result<EcsmWitness,
c0,
q1: q1_b,
c1,
x_g_sub_p,
k_sub_n,
x_r_sub_p,
len_k,
Expand Down
12 changes: 7 additions & 5 deletions executor/src/vm/instruction/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,13 @@ impl Instruction {
{
return Err(ExecutionError::EcsmAddressOverflow);
}
// xG and k are both read at the same proof timestamp, so their
// 32-byte ranges must be disjoint or the trace is unprovable
// (MEMW orders accesses per address by strictly increasing
// timestamp). xR may alias either: its accesses are offset to
// later timestamps.
// xG and k must occupy disjoint 32-byte regions. The trace builder
// reads each operand as unaligned doubleword MEMW accesses (xG at T,
// k at T+1); if the regions overlap, the same address is touched at
// both timestamps and the MEMW consistency argument can't prove the
// access chain. The loaded values would still be well-defined — this
// guard is about trace provability, not correctness of the multiply.
// xR may alias either: its accesses are at a later timestamp.
if addr_xg.abs_diff(addr_k) < 32 {
return Err(ExecutionError::EcsmOperandOverlap);
}
Expand Down
15 changes: 5 additions & 10 deletions prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ use crate::tables::trace_builder::count_table_lengths;
use crate::tables::types::BusId;
use crate::test_utils::{
E, F, VmAir, create_bitwise_air, create_branch_air, create_bytewise_air, create_commit_air,
create_cpu_air, create_cpu32_air, create_decode_air, create_dvrm_air, create_ec_scalar_air,
create_ecdas_air, create_ecsm_air, create_eq_air, create_halt_air, create_keccak_air,
create_keccak_rc_air, create_keccak_rnd_air, create_load_air, create_lt_air, create_memw_air,
create_cpu_air, create_cpu32_air, create_decode_air, create_dvrm_air, create_ecdas_air,
create_ecsm_air, create_eq_air, create_halt_air, create_keccak_air, create_keccak_rc_air,
create_keccak_rnd_air, create_load_air, create_lt_air, create_memw_air,
create_memw_aligned_air, create_memw_register_air, create_mul_air, create_page_air,
create_register_air, create_shift_air, create_store_air,
};
Expand All @@ -78,8 +78,8 @@ pub struct RuntimePageRange {

/// Number of tables that always contribute exactly one sub-proof, regardless
/// of `TableCounts`: bitwise, decode, halt, commit, keccak, keccak_rnd,
/// keccak_rc, register, ecsm, ec_scalar, ecdas.
pub const FIXED_TABLE_COUNT: usize = 11;
/// keccak_rc, register, ecsm, ecdas.
pub const FIXED_TABLE_COUNT: usize = 10;

/// Number of chunks for each split table.
/// The verifier needs this to reconstruct matching AIRs.
Expand Down Expand Up @@ -259,7 +259,6 @@ pub(crate) struct VmAirs {
pub keccak_rnd: VmAir,
pub keccak_rc: VmAir,
pub ecsm: VmAir,
pub ec_scalar: VmAir,
pub ecdas: VmAir,
pub register: VmAir,
pub pages: Vec<VmAir>,
Expand All @@ -285,7 +284,6 @@ impl VmAirs {
(self.keccak_rnd.as_ref(), &mut traces.keccak_rnd, &()),
(self.keccak_rc.as_ref(), &mut traces.keccak_rc, &()),
(self.ecsm.as_ref(), &mut traces.ecsm, &()),
(self.ec_scalar.as_ref(), &mut traces.ec_scalar, &()),
(self.ecdas.as_ref(), &mut traces.ecdas, &()),
(self.register.as_ref(), &mut traces.register, &()),
];
Expand Down Expand Up @@ -360,7 +358,6 @@ impl VmAirs {
self.keccak_rnd.as_ref(),
self.keccak_rc.as_ref(),
self.ecsm.as_ref(),
self.ec_scalar.as_ref(),
self.ecdas.as_ref(),
self.register.as_ref(),
];
Expand Down Expand Up @@ -534,7 +531,6 @@ impl VmAirs {
tables::keccak_rc::NUM_PRECOMPUTED_COLS,
));
let ecsm: VmAir = Box::new(create_ecsm_air(proof_options));
let ec_scalar: VmAir = Box::new(create_ec_scalar_air(proof_options));
let ecdas: VmAir = Box::new(create_ecdas_air(proof_options));
let register: VmAir =
if let Some((commitment, num_preprocessed_cols)) = register_preprocessed {
Expand Down Expand Up @@ -641,7 +637,6 @@ impl VmAirs {
keccak_rnd,
keccak_rc,
ecsm,
ec_scalar,
ecdas,
register,
pages,
Expand Down
Loading
Loading