Skip to content

Commit f188dfc

Browse files
committed
refactor(inlines): InlineSpec requires InlineOp, implement on same struct
- InlineSpec: InlineOp supertrait — no separate spec structs - Implement InlineSpec directly on InlineOp structs (Sha256Compression, etc.) - Remove free functions from spec modules; callers use Struct::reference() - Keep internal helpers (execute_keccak_f, g, round, etc.) as pub(crate)
1 parent 9543720 commit f188dfc

File tree

26 files changed

+333
-578
lines changed

26 files changed

+333
-578
lines changed

jolt-inlines/bigint/src/multiplication/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,5 @@ pub mod sequence_builder;
1515
#[cfg(feature = "host")]
1616
pub mod spec;
1717

18-
#[cfg(all(test, feature = "host"))]
19-
pub mod test_utils;
2018
#[cfg(all(test, feature = "host"))]
2119
pub mod tests;

jolt-inlines/bigint/src/multiplication/sdk.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,11 @@ pub unsafe fn bigint256_mul_inline(_a: *const u64, _b: *const u64, _result: *mut
6969
/// - `result` must point to at least 64 bytes of writable memory
7070
#[cfg(feature = "host")]
7171
pub unsafe fn bigint256_mul_inline(a: *const u64, b: *const u64, result: *mut u64) {
72+
use crate::multiplication::sequence_builder::BigintMul256;
73+
use jolt_inlines_sdk::spec::InlineSpec;
74+
7275
let a_array = *(a as *const [u64; INPUT_LIMBS]);
7376
let b_array = *(b as *const [u64; INPUT_LIMBS]);
74-
let result_array = crate::multiplication::spec::bigint_mul(a_array, b_array);
77+
let result_array = BigintMul256::reference(&(a_array, b_array));
7578
core::ptr::copy_nonoverlapping(result_array.as_ptr(), result, OUTPUT_LIMBS);
7679
}

jolt-inlines/bigint/src/multiplication/sequence_builder.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use core::array;
22

33
use jolt_inlines_sdk::host::{
44
instruction::{add::ADD, ld::LD, mul::MUL, mulhu::MULHU, sd::SD, sltu::SLTU},
5-
Cpu, FormatInline, InlineOp, InstrAssembler, Instruction, VirtualRegisterGuard,
5+
FormatInline, InlineOp, InstrAssembler, Instruction, VirtualRegisterGuard,
66
};
77

88
use super::{INPUT_LIMBS, OUTPUT_LIMBS};
@@ -155,6 +155,4 @@ impl InlineOp for BigintMul256 {
155155
fn build_sequence(asm: InstrAssembler, operands: FormatInline) -> Vec<Instruction> {
156156
BigIntMulSequenceBuilder::new(asm, operands).build()
157157
}
158-
159-
fn build_advice(_asm: InstrAssembler, _operands: FormatInline, _cpu: &mut Cpu) {}
160158
}

jolt-inlines/bigint/src/multiplication/spec.rs

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,45 @@
1+
use super::sequence_builder::BigintMul256;
12
use super::{INPUT_LIMBS, OUTPUT_LIMBS};
23
use jolt_inlines_sdk::host::Xlen;
34
use jolt_inlines_sdk::spec::{InlineMemoryLayout, InlineSpec, InlineTestHarness, INLINE};
45

5-
pub fn bigint_mul(lhs: [u64; INPUT_LIMBS], rhs: [u64; INPUT_LIMBS]) -> [u64; OUTPUT_LIMBS] {
6-
let mut result = [0u64; OUTPUT_LIMBS];
6+
impl InlineSpec for BigintMul256 {
7+
type Input = ([u64; INPUT_LIMBS], [u64; INPUT_LIMBS]);
8+
type Output = [u64; OUTPUT_LIMBS];
9+
10+
fn reference(input: &Self::Input) -> Self::Output {
11+
let (lhs, rhs) = input;
12+
let mut result = [0u64; OUTPUT_LIMBS];
713

8-
for (i, &lhs_limb) in lhs.iter().enumerate() {
9-
for (j, &rhs_limb) in rhs.iter().enumerate() {
10-
let product = (lhs_limb as u128) * (rhs_limb as u128);
11-
let low = product as u64;
12-
let high = (product >> 64) as u64;
14+
for (i, &lhs_limb) in lhs.iter().enumerate() {
15+
for (j, &rhs_limb) in rhs.iter().enumerate() {
16+
let product = (lhs_limb as u128) * (rhs_limb as u128);
17+
let low = product as u64;
18+
let high = (product >> 64) as u64;
1319

14-
let result_position = i + j;
20+
let result_position = i + j;
1521

16-
let (sum, carry1) = result[result_position].overflowing_add(low);
17-
result[result_position] = sum;
22+
let (sum, carry1) = result[result_position].overflowing_add(low);
23+
result[result_position] = sum;
1824

19-
let mut carry = carry1 as u64;
20-
if high != 0 || carry != 0 {
21-
let (sum_with_hi, carry_hi) = result[result_position + 1].overflowing_add(high);
22-
let (sum_with_carry, carry_carry) = sum_with_hi.overflowing_add(carry);
23-
result[result_position + 1] = sum_with_carry;
24-
carry = (carry_hi as u64) + (carry_carry as u64);
25+
let mut carry = carry1 as u64;
26+
if high != 0 || carry != 0 {
27+
let (sum_with_hi, carry_hi) = result[result_position + 1].overflowing_add(high);
28+
let (sum_with_carry, carry_carry) = sum_with_hi.overflowing_add(carry);
29+
result[result_position + 1] = sum_with_carry;
30+
carry = (carry_hi as u64) + (carry_carry as u64);
2531

26-
let mut carry_position = result_position + 2;
27-
while carry != 0 && carry_position < OUTPUT_LIMBS {
28-
let (sum, c) = result[carry_position].overflowing_add(carry);
29-
result[carry_position] = sum;
30-
carry = c as u64;
31-
carry_position += 1;
32+
let mut carry_position = result_position + 2;
33+
while carry != 0 && carry_position < OUTPUT_LIMBS {
34+
let (sum, c) = result[carry_position].overflowing_add(carry);
35+
result[carry_position] = sum;
36+
carry = c as u64;
37+
carry_position += 1;
38+
}
3239
}
3340
}
3441
}
35-
}
36-
result
37-
}
38-
39-
pub struct BigintMul256Spec;
40-
41-
impl InlineSpec for BigintMul256Spec {
42-
type Input = ([u64; INPUT_LIMBS], [u64; INPUT_LIMBS]);
43-
type Output = [u64; OUTPUT_LIMBS];
44-
45-
fn reference(input: &Self::Input) -> Self::Output {
46-
bigint_mul(input.0, input.1)
42+
result
4743
}
4844

4945
fn create_harness() -> InlineTestHarness {

jolt-inlines/bigint/src/multiplication/test_utils.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

jolt-inlines/bigint/src/multiplication/tests.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,29 @@ use super::{INPUT_LIMBS, OUTPUT_LIMBS};
44

55
mod bigint256_multiplication {
66
use super::TestVectors;
7-
use crate::test_utils::bigint_verify;
7+
use crate::multiplication::sequence_builder::BigintMul256;
8+
use jolt_inlines_sdk::spec;
89

910
#[test]
1011
fn test_bigint256_mul_default() {
11-
// Test with the default test vector
12-
let (lhs, rhs, expected) = TestVectors::get_default_test();
13-
bigint_verify::assert_exec_trace_equiv(&lhs, &rhs, &expected);
12+
let (lhs, rhs, _expected) = TestVectors::get_default_test();
13+
spec::verify::<BigintMul256>(&(lhs, rhs));
1414
}
1515

1616
#[test]
1717
fn test_bigint256_mul_random() {
18-
// Test with 100 random inputs
1918
for _ in 0..100 {
20-
let (lhs, rhs, expected) = TestVectors::generate_random_test();
21-
bigint_verify::assert_exec_trace_equiv(&lhs, &rhs, &expected);
19+
let (lhs, rhs, _expected) = TestVectors::generate_random_test();
20+
spec::verify::<BigintMul256>(&(lhs, rhs));
2221
}
2322
}
2423

2524
#[test]
2625
fn test_bigint256_mul_edge_cases() {
27-
println!("\n=== Testing BigInt256 multiplication edge cases ===");
28-
2926
let edge_cases = TestVectors::get_edge_cases();
30-
31-
for (i, (lhs, rhs, expected, description)) in edge_cases.iter().enumerate() {
32-
println!("\nEdge case #{}: {}", i + 1, description);
33-
bigint_verify::assert_exec_trace_equiv(lhs, rhs, expected);
27+
for (lhs, rhs, _expected, _description) in &edge_cases {
28+
spec::verify::<BigintMul256>(&(*lhs, *rhs));
3429
}
35-
36-
println!("\n✅ All {} edge cases passed!\n", edge_cases.len());
3730
}
3831
}
3932

jolt-inlines/blake2/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ mod host;
2020
#[cfg(feature = "host")]
2121
pub use host::*;
2222

23-
#[cfg(all(test, feature = "host"))]
24-
pub mod test_utils;
25-
2623
/// Blake2b initialization vector (IV).
2724
pub const IV: [u64; 8] = [
2825
0x6a09e667f3bcc908,

jolt-inlines/blake2/src/sdk.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -401,18 +401,13 @@ pub(crate) unsafe fn blake2b_compress(state: *mut u64, message: *const u64) {
401401
/// - `message` must point to a valid array of 18 u64 values
402402
#[cfg(feature = "host")]
403403
pub(crate) unsafe fn blake2b_compress(state: *mut u64, message: *const u64) {
404-
let state_slice = core::slice::from_raw_parts_mut(state, 8);
405-
let message_slice = core::slice::from_raw_parts(message, 18);
406-
407-
// Convert to arrays for type safety
408-
let state_array: &mut [u64; 8] = state_slice
409-
.try_into()
410-
.expect("State pointer must reference exactly 8 u64 values");
411-
let message_array: [u64; 18] = message_slice
412-
.try_into()
413-
.expect("Message pointer must reference exactly 18 u64 values");
414-
415-
crate::spec::execute_blake2b_compression(state_array, &message_array);
404+
use crate::sequence_builder::Blake2bCompression;
405+
use jolt_inlines_sdk::spec::InlineSpec;
406+
407+
let state_array = *(state as *const [u64; 8]);
408+
let message_array = *(message as *const [u64; 18]);
409+
let result = Blake2bCompression::reference(&(state_array, message_array));
410+
core::ptr::copy_nonoverlapping(result.as_ptr(), state, 8);
416411
}
417412

418413
#[cfg(all(

jolt-inlines/blake2/src/sequence_builder.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use jolt_inlines_sdk::host::{
1717
sub::SUB,
1818
virtual_xor_rot::{VirtualXORROT16, VirtualXORROT24, VirtualXORROT32, VirtualXORROT63},
1919
},
20-
Cpu, FormatInline, InlineOp, InstrAssembler, InstrAssemblerExt, Instruction,
20+
FormatInline, InlineOp, InstrAssembler, InstrAssemblerExt, Instruction,
2121
Value::{Imm, Reg},
2222
VirtualRegisterGuard,
2323
};
@@ -239,19 +239,14 @@ impl InlineOp for Blake2bCompression {
239239
fn build_sequence(asm: InstrAssembler, operands: FormatInline) -> Vec<Instruction> {
240240
Blake2SequenceBuilder::new(asm, operands).build()
241241
}
242-
243-
fn build_advice(_asm: InstrAssembler, _operands: FormatInline, _cpu: &mut Cpu) {}
244242
}
245243

246244
#[cfg(test)]
247245
mod tests {
248-
use crate::{
249-
test_utils::{create_blake2_harness, instruction, load_blake2_data, read_state},
250-
IV,
251-
};
246+
use crate::IV;
247+
use jolt_inlines_sdk::spec::InlineSpec;
252248

253249
fn generate_default_input() -> ([u64; crate::MSG_BLOCK_LEN], u64) {
254-
// Message block with "abc" in little-endian
255250
let mut message = [0u64; crate::MSG_BLOCK_LEN];
256251
message[0] = 0x0000000000636261u64;
257252
(message, 3)
@@ -294,13 +289,18 @@ mod tests {
294289
counter: u64,
295290
is_final: bool,
296291
) -> [u64; crate::STATE_VECTOR_LEN] {
297-
let mut harness = create_blake2_harness();
298-
load_blake2_data(&mut harness, state, message, counter, is_final);
299-
harness.execute_inline(instruction());
300-
read_state(&mut harness)
292+
let mut combined = [0u64; 18];
293+
combined[..16].copy_from_slice(message);
294+
combined[16] = counter;
295+
combined[17] = is_final as u64;
296+
297+
let input = (*state, combined);
298+
let mut harness = super::Blake2bCompression::create_harness();
299+
super::Blake2bCompression::load(&mut harness, &input);
300+
harness.execute_inline(super::Blake2bCompression::instruction());
301+
super::Blake2bCompression::read(&mut harness)
301302
}
302303

303-
/// Helper function to test blake2b compression with given input
304304
fn verify_blake2b_compression(message_words: [u64; crate::MSG_BLOCK_LEN], message_len: u64) {
305305
let mut initial_state = IV;
306306
initial_state[0] ^= 0x01010000 ^ 64u64;
@@ -310,7 +310,7 @@ mod tests {
310310

311311
assert_eq!(
312312
&expected_state, &trace_result,
313-
"\n❌ BLAKE2b Trace Verification Failed!\n\
313+
"\nBLAKE2b Trace Verification Failed!\n\
314314
Message: {message_words:016x?}"
315315
);
316316
}
@@ -323,7 +323,6 @@ mod tests {
323323

324324
#[test]
325325
fn test_trace_result_with_random_inputs() {
326-
// Test with multiple random inputs
327326
for _ in 0..10 {
328327
let input = generate_random_input();
329328
verify_blake2b_compression(input.0, input.1);

0 commit comments

Comments
 (0)