Skip to content

Commit

Permalink
Merge pull request #35 from lambdaclass/input_checks
Browse files Browse the repository at this point in the history
Add tests for input sizes
  • Loading branch information
gabrielbosio authored Sep 19, 2024
2 parents 7a2b555 + e46b6f5 commit 05eccaf
Show file tree
Hide file tree
Showing 9 changed files with 301 additions and 13 deletions.
14 changes: 12 additions & 2 deletions batcher/aligned-batcher/src/mina/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ mod test {
use super::verify_proof_integrity;

const PROTOCOL_STATE_PROOF_BYTES: &[u8] =
include_bytes!("../../../../batcher/aligned/test_files/mina/protocol_state.proof");
include_bytes!("../../../../scripts/test_files/mina/mina_state.proof");
const PROTOCOL_STATE_PUB_BYTES: &[u8] =
include_bytes!("../../../../batcher/aligned/test_files/mina/protocol_state.pub");
include_bytes!("../../../../scripts/test_files/mina/mina_state.pub");

#[test]
fn verify_proof_integrity_does_not_fail() {
Expand All @@ -33,4 +33,14 @@ mod test {
PROTOCOL_STATE_PUB_BYTES,
));
}

#[test]
fn verify_empty_proof() {
assert!(!verify_proof_integrity(&[], PROTOCOL_STATE_PUB_BYTES));
}

#[test]
fn verify_empty_pub_inputs() {
assert!(!verify_proof_integrity(PROTOCOL_STATE_PROOF_BYTES, &[]));
}
}
97 changes: 88 additions & 9 deletions operator/mina/lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,30 @@ pub extern "C" fn verify_mina_state_ffi(
pub_input_buffer: &[u8; MAX_PUB_INPUT_SIZE],
pub_input_len: usize,
) -> bool {
let proof: MinaStateProof = match bincode::deserialize(&proof_buffer[..proof_len]) {
let Some(proof_buffer_slice) = proof_buffer.get(..proof_len) else {
eprintln!("Proof length argument is greater than max proof size");
return false;
};

let Some(pub_input_buffer_slice) = pub_input_buffer.get(..pub_input_len) else {
eprintln!("Public input length argument is greater than max public input size");
return false;
};

let proof: MinaStateProof = match bincode::deserialize(proof_buffer_slice) {
Ok(proof) => proof,
Err(err) => {
eprintln!("Failed to deserialize state proof: {}", err);
return false;
}
};
let pub_inputs: MinaStatePubInputs =
match bincode::deserialize(&pub_input_buffer[..pub_input_len]) {
Ok(pub_inputs) => pub_inputs,
Err(err) => {
eprintln!("Failed to deserialize state pub inputs: {}", err);
return false;
}
};
let pub_inputs: MinaStatePubInputs = match bincode::deserialize(pub_input_buffer_slice) {
Ok(pub_inputs) => pub_inputs,
Err(err) => {
eprintln!("Failed to deserialize state pub inputs: {}", err);
return false;
}
};

// Checks the integrity of the public inputs, also checks if the states form a chain.
let (candidate_tip_state, bridge_tip_state, candidate_tip_state_hash) =
Expand Down Expand Up @@ -234,4 +243,74 @@ mod test {
verify_mina_state_ffi(&proof_buffer, proof_size, &pub_input_buffer, pub_input_size);
assert!(!result);
}

#[test]
fn empty_mina_state_proof_does_not_verify() {
let proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let proof_size = PROOF_BYTES.len();

let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let pub_input_size = PUB_INPUT_BYTES.len();
assert!(pub_input_size <= pub_input_buffer.len());
pub_input_buffer[..pub_input_size].clone_from_slice(PUB_INPUT_BYTES);

let result =
verify_mina_state_ffi(&proof_buffer, proof_size, &pub_input_buffer, pub_input_size);
assert!(!result);
}

#[test]
fn valid_mina_state_proof_with_empty_pub_input_does_not_verify() {
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let proof_size = PROOF_BYTES.len();
assert!(proof_size <= proof_buffer.len());
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);

let pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let pub_input_size = PUB_INPUT_BYTES.len();

let result =
verify_mina_state_ffi(&proof_buffer, proof_size, &pub_input_buffer, pub_input_size);
assert!(!result);
}

#[test]
fn valid_mina_state_proof_with_greater_proof_size_does_not_verify() {
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let wrong_proof_size = super::MAX_PROOF_SIZE + 1;
proof_buffer[..PROOF_BYTES.len()].clone_from_slice(PROOF_BYTES);

let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let pub_input_size = PUB_INPUT_BYTES.len();
assert!(pub_input_size <= pub_input_buffer.len());
pub_input_buffer[..pub_input_size].clone_from_slice(PUB_INPUT_BYTES);

let result = verify_mina_state_ffi(
&proof_buffer,
wrong_proof_size,
&pub_input_buffer,
pub_input_size,
);
assert!(!result);
}

#[test]
fn valid_mina_state_proof_with_greater_pub_input_size_does_not_verify() {
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let proof_size = PROOF_BYTES.len();
assert!(proof_size <= proof_buffer.len());
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);

let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let wrong_pub_input_size = MAX_PUB_INPUT_SIZE + 1;
pub_input_buffer[..PUB_INPUT_BYTES.len()].clone_from_slice(PUB_INPUT_BYTES);

let result = verify_mina_state_ffi(
&proof_buffer,
proof_size,
&pub_input_buffer,
wrong_pub_input_size,
);
assert!(!result);
}
}
40 changes: 40 additions & 0 deletions operator/mina/mina_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,43 @@ func TestMinaStateProofVerifies(t *testing.T) {
t.Errorf("proof did not verify")
}
}

func TestEmptyMinaStateProofDoesNotVerify(t *testing.T) {
fmt.Println(os.Getwd())

proofBuffer := make([]byte, mina.MAX_PROOF_SIZE)

pubInputFile, err := os.Open("../../scripts/test_files/mina/mina_state.pub")
if err != nil {
t.Errorf("could not open mina state hash file")
}
pubInputBuffer := make([]byte, mina.MAX_PUB_INPUT_SIZE)
pubInputLen, err := pubInputFile.Read(pubInputBuffer)
if err != nil {
t.Errorf("could not read bytes from mina state hash")
}

if mina.VerifyMinaState(([mina.MAX_PROOF_SIZE]byte)(proofBuffer), mina.MAX_PROOF_SIZE, ([mina.MAX_PUB_INPUT_SIZE]byte)(pubInputBuffer), uint(pubInputLen)) {
t.Errorf("empty proof should not verify but it did")
}
}

func TestMinaStateProofWithEmptyPubInputDoesNotVerify(t *testing.T) {
fmt.Println(os.Getwd())
proofFile, err := os.Open("../../scripts/test_files/mina/mina_state.proof")
if err != nil {
t.Errorf("could not open mina state proof file")
}

proofBuffer := make([]byte, mina.MAX_PROOF_SIZE)
proofLen, err := proofFile.Read(proofBuffer)
if err != nil {
t.Errorf("could not read bytes from mina state proof file")
}

pubInputBuffer := make([]byte, mina.MAX_PUB_INPUT_SIZE)

if mina.VerifyMinaState(([mina.MAX_PROOF_SIZE]byte)(proofBuffer), uint(proofLen), ([mina.MAX_PUB_INPUT_SIZE]byte)(pubInputBuffer), mina.MAX_PUB_INPUT_SIZE) {
t.Errorf("proof with no public inputs should not verify but it did")
}
}
124 changes: 122 additions & 2 deletions operator/mina_account/lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,20 @@ pub extern "C" fn verify_account_inclusion_ffi(
pub_input_buffer: &[u8; MAX_PUB_INPUT_SIZE],
pub_input_len: usize,
) -> bool {
let Some(proof_buffer_slice) = proof_buffer.get(..proof_len) else {
eprintln!("Proof length argument is greater than max proof size");
return false;
};

let Some(pub_input_buffer_slice) = pub_input_buffer.get(..pub_input_len) else {
eprintln!("Public input length argument is greater than max public input size");
return false;
};

let MinaAccountProof {
merkle_path,
account,
} = match bincode::deserialize(&proof_buffer[..proof_len]) {
} = match bincode::deserialize(proof_buffer_slice) {
Ok(proof) => proof,
Err(err) => {
eprintln!("Failed to deserialize account proof: {}", err);
Expand All @@ -32,7 +42,7 @@ pub extern "C" fn verify_account_inclusion_ffi(
let MinaAccountPubInputs {
ledger_hash,
encoded_account,
} = match bincode::deserialize(&pub_input_buffer[..pub_input_len]) {
} = match bincode::deserialize(pub_input_buffer_slice) {
Ok(pub_inputs) => pub_inputs,
Err(err) => {
eprintln!("Failed to deserialize account pub inputs: {}", err);
Expand Down Expand Up @@ -64,3 +74,113 @@ pub extern "C" fn verify_account_inclusion_ffi(

verify_merkle_proof(leaf_hash, merkle_path, ledger_hash)
}

#[cfg(test)]
mod test {

use super::*;

const PROOF_BYTES: &[u8] =
include_bytes!("../../../../scripts/test_files/mina_account/mina_account.proof");
const PUB_INPUT_BYTES: &[u8] =
include_bytes!("../../../../scripts/test_files/mina_account/mina_account.pub");

#[test]
fn valid_account_state_proof_verifies() {
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let proof_size = PROOF_BYTES.len();
assert!(proof_size <= proof_buffer.len());
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);

let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let pub_input_size = PUB_INPUT_BYTES.len();
assert!(pub_input_size <= pub_input_buffer.len());
pub_input_buffer[..pub_input_size].clone_from_slice(PUB_INPUT_BYTES);

let result = verify_account_inclusion_ffi(
&proof_buffer,
proof_size,
&pub_input_buffer,
pub_input_size,
);
assert!(result);
}

#[test]
fn empty_account_state_proof_does_not_verify() {
let proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let proof_size = PROOF_BYTES.len();

let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let pub_input_size = PUB_INPUT_BYTES.len();
assert!(pub_input_size <= pub_input_buffer.len());
pub_input_buffer[..pub_input_size].clone_from_slice(PUB_INPUT_BYTES);

let result = verify_account_inclusion_ffi(
&proof_buffer,
proof_size,
&pub_input_buffer,
pub_input_size,
);
assert!(!result);
}

#[test]
fn valid_account_state_proof_with_empty_pub_input_does_not_verify() {
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let proof_size = PROOF_BYTES.len();
assert!(proof_size <= proof_buffer.len());
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);

let pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let pub_input_size = PUB_INPUT_BYTES.len();

let result = verify_account_inclusion_ffi(
&proof_buffer,
proof_size,
&pub_input_buffer,
pub_input_size,
);
assert!(!result);
}

#[test]
fn valid_account_state_proof_with_greater_proof_size_does_not_verify() {
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let wrong_proof_size = MAX_PROOF_SIZE + 1;
proof_buffer[..PROOF_BYTES.len()].clone_from_slice(PROOF_BYTES);

let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let pub_input_size = PUB_INPUT_BYTES.len();
assert!(pub_input_size <= pub_input_buffer.len());
pub_input_buffer[..pub_input_size].clone_from_slice(PUB_INPUT_BYTES);

let result = verify_account_inclusion_ffi(
&proof_buffer,
wrong_proof_size,
&pub_input_buffer,
pub_input_size,
);
assert!(!result);
}

#[test]
fn valid_account_state_proof_with_greater_pub_input_size_does_not_verify() {
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
let proof_size = PROOF_BYTES.len();
assert!(proof_size <= proof_buffer.len());
proof_buffer[..proof_size].clone_from_slice(PROOF_BYTES);

let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
let wrong_pub_input_size = MAX_PUB_INPUT_SIZE + 1;
pub_input_buffer[..PUB_INPUT_BYTES.len()].clone_from_slice(PUB_INPUT_BYTES);

let result = verify_account_inclusion_ffi(
&proof_buffer,
proof_size,
&pub_input_buffer,
wrong_pub_input_size,
);
assert!(!result);
}
}
39 changes: 39 additions & 0 deletions operator/mina_account/mina_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,42 @@ func TestMinaStateProofVerifies(t *testing.T) {
t.Errorf("proof did not verify")
}
}

func TestEmptyMinaStateProofDoesNotVerify(t *testing.T) {
fmt.Println(os.Getwd())
proofBuffer := make([]byte, mina_account.MAX_PROOF_SIZE)

pubInputFile, err := os.Open("../../scripts/test_files/mina_account/mina_account.pub")
if err != nil {
t.Errorf("could not open mina account pub inputs file")
}
pubInputBuffer := make([]byte, mina_account.MAX_PUB_INPUT_SIZE)
pubInputLen, err := pubInputFile.Read(pubInputBuffer)
if err != nil {
t.Errorf("could not read bytes from mina account pub inputs hash")
}

if mina_account.VerifyAccountInclusion(([mina_account.MAX_PROOF_SIZE]byte)(proofBuffer), mina_account.MAX_PROOF_SIZE, ([mina_account.MAX_PUB_INPUT_SIZE]byte)(pubInputBuffer), uint(pubInputLen)) {
t.Errorf("Empty proof should not verify but it did")
}
}

func TestMinaStateProofWithEmptyPubInputDoesNotVerify(t *testing.T) {
fmt.Println(os.Getwd())
proofFile, err := os.Open("../../scripts/test_files/mina_account/mina_account.proof")
if err != nil {
t.Errorf("could not open mina account proof file")
}

proofBuffer := make([]byte, mina_account.MAX_PROOF_SIZE)
proofLen, err := proofFile.Read(proofBuffer)
if err != nil {
t.Errorf("could not read bytes from mina account proof file")
}

pubInputBuffer := make([]byte, mina_account.MAX_PUB_INPUT_SIZE)

if mina_account.VerifyAccountInclusion(([mina_account.MAX_PROOF_SIZE]byte)(proofBuffer), uint(proofLen), ([mina_account.MAX_PUB_INPUT_SIZE]byte)(pubInputBuffer), mina_account.MAX_PUB_INPUT_SIZE) {
t.Errorf("proof with empty public input should not verify but id did")
}
}
Binary file modified scripts/test_files/mina/mina_state.proof
Binary file not shown.
Binary file modified scripts/test_files/mina/mina_state.pub
Binary file not shown.
Binary file modified scripts/test_files/mina_account/mina_account.proof
Binary file not shown.
Binary file modified scripts/test_files/mina_account/mina_account.pub
Binary file not shown.

0 comments on commit 05eccaf

Please sign in to comment.