Skip to content

Commit c26ad54

Browse files
authored
Merge pull request #56 from lambdaclass/improve_ffi_arg_types
Improve Mina verification FFI
2 parents 220546a + c7eb450 commit c26ad54

File tree

11 files changed

+255
-349
lines changed

11 files changed

+255
-349
lines changed

batcher/aligned-batcher/src/zk_utils/mod.rs

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use crate::sp1::verify_sp1_proof;
44
use aligned_sdk::core::types::{ProvingSystemId, VerificationData};
55
use ethers::types::U256;
66
use log::{debug, warn};
7-
use mina_account_verifier_ffi::verify_account_inclusion_ffi;
8-
use mina_state_verifier_ffi::verify_mina_state_ffi;
7+
use mina_account_verifier_ffi::verify_account_inclusion;
8+
use mina_state_verifier_ffi::verify_mina_state;
99

1010
pub(crate) async fn verify(verification_data: &VerificationData) -> bool {
1111
let verification_data = verification_data.clone();
@@ -67,45 +67,15 @@ fn verify_internal(verification_data: &VerificationData) -> bool {
6767
return false;
6868
};
6969

70-
const MAX_PROOF_SIZE: usize = 48 * 1024;
71-
const MAX_PUB_INPUT_SIZE: usize = 6 * 1024;
72-
73-
let mut proof_buffer = [0; MAX_PROOF_SIZE];
74-
for (buffer_item, proof_item) in proof_buffer.iter_mut().zip(&verification_data.proof) {
75-
*buffer_item = *proof_item;
76-
}
77-
let proof_len = verification_data.proof.len();
78-
79-
let mut pub_input_buffer = [0; MAX_PUB_INPUT_SIZE];
80-
for (buffer_item, pub_input_item) in pub_input_buffer.iter_mut().zip(pub_input) {
81-
*buffer_item = *pub_input_item;
82-
}
83-
let pub_input_len = pub_input.len();
84-
85-
verify_mina_state_ffi(&proof_buffer, proof_len, &pub_input_buffer, pub_input_len)
70+
verify_mina_state(&verification_data.proof, &pub_input)
8671
}
8772
ProvingSystemId::MinaAccount => {
8873
let Some(pub_input) = verification_data.pub_input.as_ref() else {
8974
warn!("Mina Account public input is missing");
9075
return false;
9176
};
9277

93-
const MAX_PROOF_SIZE: usize = 16 * 1024;
94-
const MAX_PUB_INPUT_SIZE: usize = 6 * 1024;
95-
96-
let mut proof_buffer = [0; MAX_PROOF_SIZE];
97-
for (buffer_item, proof_item) in proof_buffer.iter_mut().zip(&verification_data.proof) {
98-
*buffer_item = *proof_item;
99-
}
100-
let proof_len = verification_data.proof.len();
101-
102-
let mut pub_input_buffer = [0; MAX_PUB_INPUT_SIZE];
103-
for (buffer_item, pub_input_item) in pub_input_buffer.iter_mut().zip(pub_input) {
104-
*buffer_item = *pub_input_item;
105-
}
106-
let pub_input_len = pub_input.len();
107-
108-
verify_account_inclusion_ffi(&proof_buffer, proof_len, &pub_input_buffer, pub_input_len)
78+
verify_account_inclusion(&verification_data.proof, &pub_input)
10979
}
11080
}
11181
}

operator/mina/lib/mina_verifier.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <stdbool.h>
2+
#include <stdint.h>
23

3-
bool verify_mina_state_ffi(unsigned char *proof_buffer,
4-
unsigned int proof_len,
5-
unsigned char *pub_input_buffer,
6-
unsigned int pub_input_len);
4+
int32_t verify_mina_state_ffi(unsigned char *proof_buffer, uint32_t proof_len,
5+
unsigned char *pub_input_buffer,
6+
uint32_t pub_input_len);

operator/mina/lib/src/lib.rs

Lines changed: 66 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -34,35 +34,56 @@ lazy_static! {
3434
static ref MINA_SRS: SRS<Vesta> = SRS::<Vesta>::create(Fq::SRS_DEPTH);
3535
}
3636

37-
// TODO(xqft): check proof size
38-
const MAX_PROOF_SIZE: usize = 48 * 1024;
39-
const MAX_PUB_INPUT_SIZE: usize = 6 * 1024;
40-
4137
#[no_mangle]
4238
pub extern "C" fn verify_mina_state_ffi(
43-
proof_buffer: &[u8; MAX_PROOF_SIZE],
44-
proof_len: usize,
45-
pub_input_buffer: &[u8; MAX_PUB_INPUT_SIZE],
46-
pub_input_len: usize,
39+
proof_bytes: *const u8,
40+
proof_len: u32,
41+
pub_input_bytes: *const u8,
42+
pub_input_len: u32,
43+
) -> i32 {
44+
let result = std::panic::catch_unwind(|| {
45+
inner_verify_mina_state_ffi(proof_bytes, proof_len, pub_input_bytes, pub_input_len)
46+
});
47+
48+
match result {
49+
Ok(v) => v as i32,
50+
Err(_) => -1,
51+
}
52+
}
53+
54+
fn inner_verify_mina_state_ffi(
55+
proof_bytes: *const u8,
56+
proof_len: u32,
57+
pub_input_bytes: *const u8,
58+
pub_input_len: u32,
4759
) -> bool {
48-
let Some(proof_buffer_slice) = proof_buffer.get(..proof_len) else {
49-
error!("Proof length argument is greater than max proof size");
60+
if proof_bytes.is_null() || pub_input_bytes.is_null() {
61+
error!("Input buffer null");
5062
return false;
51-
};
63+
}
5264

53-
let Some(pub_input_buffer_slice) = pub_input_buffer.get(..pub_input_len) else {
54-
error!("Public input length argument is greater than max public input size");
65+
if proof_len == 0 || pub_input_len == 0 {
66+
error!("Input buffer length zero size");
5567
return false;
56-
};
68+
}
69+
70+
let proof_bytes = unsafe { std::slice::from_raw_parts(proof_bytes, proof_len as usize) };
71+
72+
let pub_input_bytes =
73+
unsafe { std::slice::from_raw_parts(pub_input_bytes, pub_input_len as usize) };
74+
75+
verify_mina_state(proof_bytes, pub_input_bytes)
76+
}
5777

58-
let proof: MinaStateProof = match bincode::deserialize(proof_buffer_slice) {
78+
pub fn verify_mina_state(proof_bytes: &[u8], pub_input_bytes: &[u8]) -> bool {
79+
let proof: MinaStateProof = match bincode::deserialize(proof_bytes) {
5980
Ok(proof) => proof,
6081
Err(err) => {
6182
error!("Failed to deserialize state proof: {}", err);
6283
return false;
6384
}
6485
};
65-
let pub_inputs: MinaStatePubInputs = match bincode::deserialize(pub_input_buffer_slice) {
86+
let pub_inputs: MinaStatePubInputs = match bincode::deserialize(pub_input_bytes) {
6687
Ok(pub_inputs) => pub_inputs,
6788
Err(err) => {
6889
error!("Failed to deserialize state pub inputs: {}", err);
@@ -228,105 +249,51 @@ mod test {
228249

229250
#[test]
230251
fn valid_mina_state_proof_verifies() {
231-
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
232-
let proof_size = PROOF_BYTES.len();
233-
assert!(proof_size <= proof_buffer.len());
234-
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);
235-
236-
let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
237-
let pub_input_size = PUB_INPUT_BYTES.len();
238-
assert!(pub_input_size <= pub_input_buffer.len());
239-
pub_input_buffer[..pub_input_size].clone_from_slice(PUB_INPUT_BYTES);
240-
241-
let result =
242-
verify_mina_state_ffi(&proof_buffer, proof_size, &pub_input_buffer, pub_input_size);
243-
assert!(result);
252+
let result = verify_mina_state_ffi(
253+
PROOF_BYTES.as_ptr(),
254+
PROOF_BYTES.len() as u32,
255+
PUB_INPUT_BYTES.as_ptr(),
256+
PUB_INPUT_BYTES.len() as u32,
257+
);
258+
assert_eq!(result, 1);
244259
}
245260

246261
#[test]
247262
fn mina_state_proof_with_bad_bridge_tip_hash_does_not_verify() {
248-
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
249-
let proof_size = PROOF_BYTES.len();
250-
assert!(proof_size <= proof_buffer.len());
251-
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);
252-
253-
let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
254-
let pub_input_size = BAD_HASH_PUB_INPUT_BYTES.len();
255-
assert!(pub_input_size <= pub_input_buffer.len());
256-
pub_input_buffer[..pub_input_size].clone_from_slice(BAD_HASH_PUB_INPUT_BYTES);
257-
258-
let result =
259-
verify_mina_state_ffi(&proof_buffer, proof_size, &pub_input_buffer, pub_input_size);
260-
assert!(!result);
263+
let result = verify_mina_state_ffi(
264+
PROOF_BYTES.as_ptr(),
265+
PROOF_BYTES.len() as u32,
266+
BAD_HASH_PUB_INPUT_BYTES.as_ptr(),
267+
BAD_HASH_PUB_INPUT_BYTES.len() as u32,
268+
);
269+
assert_eq!(result, 0);
261270
}
262271

263272
#[test]
264273
fn empty_mina_state_proof_does_not_verify() {
265-
let proof_buffer = [0u8; super::MAX_PROOF_SIZE];
266-
let proof_size = PROOF_BYTES.len();
267-
268-
let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
269-
let pub_input_size = PUB_INPUT_BYTES.len();
270-
assert!(pub_input_size <= pub_input_buffer.len());
271-
pub_input_buffer[..pub_input_size].clone_from_slice(PUB_INPUT_BYTES);
272-
273-
let result =
274-
verify_mina_state_ffi(&proof_buffer, proof_size, &pub_input_buffer, pub_input_size);
275-
assert!(!result);
276-
}
277-
278-
#[test]
279-
fn valid_mina_state_proof_with_empty_pub_input_does_not_verify() {
280-
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
281-
let proof_size = PROOF_BYTES.len();
282-
assert!(proof_size <= proof_buffer.len());
283-
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);
284-
285-
let pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
286-
let pub_input_size = PUB_INPUT_BYTES.len();
287-
288-
let result =
289-
verify_mina_state_ffi(&proof_buffer, proof_size, &pub_input_buffer, pub_input_size);
290-
assert!(!result);
291-
}
292-
293-
#[test]
294-
fn valid_mina_state_proof_with_greater_proof_size_does_not_verify() {
295-
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
296-
let wrong_proof_size = super::MAX_PROOF_SIZE + 1;
297-
proof_buffer[..PROOF_BYTES.len()].clone_from_slice(PROOF_BYTES);
298-
299-
let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
300-
let pub_input_size = PUB_INPUT_BYTES.len();
301-
assert!(pub_input_size <= pub_input_buffer.len());
302-
pub_input_buffer[..pub_input_size].clone_from_slice(PUB_INPUT_BYTES);
274+
const PROOF_SIZE: usize = PROOF_BYTES.len();
275+
let empty_proof_buffer = [0u8; PROOF_SIZE];
303276

304277
let result = verify_mina_state_ffi(
305-
&proof_buffer,
306-
wrong_proof_size,
307-
&pub_input_buffer,
308-
pub_input_size,
278+
empty_proof_buffer.as_ptr(),
279+
PROOF_SIZE as u32,
280+
PUB_INPUT_BYTES.as_ptr(),
281+
PUB_INPUT_BYTES.len() as u32,
309282
);
310-
assert!(!result);
283+
assert_eq!(result, 0);
311284
}
312285

313286
#[test]
314-
fn valid_mina_state_proof_with_greater_pub_input_size_does_not_verify() {
315-
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
316-
let proof_size = PROOF_BYTES.len();
317-
assert!(proof_size <= proof_buffer.len());
318-
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);
319-
320-
let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
321-
let wrong_pub_input_size = MAX_PUB_INPUT_SIZE + 1;
322-
pub_input_buffer[..PUB_INPUT_BYTES.len()].clone_from_slice(PUB_INPUT_BYTES);
287+
fn valid_mina_state_proof_with_empty_pub_input_does_not_verify() {
288+
const PUB_INPUT_SIZE: usize = PUB_INPUT_BYTES.len();
289+
let empty_pub_input_buffer = [0u8; PUB_INPUT_SIZE];
323290

324291
let result = verify_mina_state_ffi(
325-
&proof_buffer,
326-
proof_size,
327-
&pub_input_buffer,
328-
wrong_pub_input_size,
292+
PROOF_BYTES.as_ptr(),
293+
PROOF_BYTES.len() as u32,
294+
empty_pub_input_buffer.as_ptr(),
295+
PUB_INPUT_SIZE as u32,
329296
);
330-
assert!(!result);
297+
assert_eq!(result, 0);
331298
}
332299
}

operator/mina/mina.go

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,36 @@ package mina
99
import "C"
1010
import (
1111
"fmt"
12-
"time"
1312
"unsafe"
1413
)
1514

16-
// TODO(xqft): check proof size
17-
const MAX_PROOF_SIZE = 48 * 1024
18-
const MAX_PUB_INPUT_SIZE = 6 * 1024
19-
20-
func timer() func() {
21-
start := time.Now()
22-
return func() {
23-
fmt.Printf("Mina block verification took %v\n", time.Since(start))
15+
func VerifyMinaState(proofBuffer []byte, pubInputBuffer []byte) (isVerified bool, err error) {
16+
// Here we define the return value on failure
17+
isVerified = false
18+
err = nil
19+
if len(proofBuffer) == 0 || len(pubInputBuffer) == 0 {
20+
return isVerified, err
2421
}
25-
}
2622

27-
func VerifyMinaState(proofBuffer [MAX_PROOF_SIZE]byte, proofLen uint, pubInputBuffer [MAX_PUB_INPUT_SIZE]byte, pubInputLen uint) bool {
28-
defer timer()()
23+
// This will catch any go panic
24+
defer func() {
25+
rec := recover()
26+
if rec != nil {
27+
err = fmt.Errorf("Panic was caught while verifying sp1 proof: %s", rec)
28+
}
29+
}()
30+
2931
proofPtr := (*C.uchar)(unsafe.Pointer(&proofBuffer[0]))
3032
pubInputPtr := (*C.uchar)(unsafe.Pointer(&pubInputBuffer[0]))
31-
return (bool)(C.verify_mina_state_ffi(proofPtr, (C.uint)(proofLen), pubInputPtr, (C.uint)(pubInputLen)))
33+
34+
r := (C.int32_t)(C.verify_mina_state_ffi(proofPtr, (C.uint32_t)(len(proofBuffer)), pubInputPtr, (C.uint32_t)(len(pubInputBuffer))))
35+
36+
if r == -1 {
37+
err = fmt.Errorf("Panic happened on FFI while verifying Mina proof")
38+
return isVerified, err
39+
}
40+
41+
isVerified = (r == 1)
42+
43+
return isVerified, err
3244
}

0 commit comments

Comments
 (0)