Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
4 changes: 4 additions & 0 deletions derivation/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub enum Error {
NoPreimageDataFoundInVerifyBlob(Vec<u8>, Box<Error>),
#[error("NoPreimageKeyFoundInPrecompile: err={0:?}")]
NoPreimageKeyFoundInPrecompile(Box<Error>),
#[error("UnexpectedBlobKey: blob_key={0:?}")]
UnexpectedBlobKey(Vec<u8>),
#[error("UnexpectedSliceLength: {0} {1}")]
UnexpectedSliceLength(usize, usize),
#[error("OracleProviderError: err={0:?}")]
Expand All @@ -48,4 +50,6 @@ pub enum Error {
DriverError(#[from] kona_driver::DriverError<kona_executor::ExecutorError>),
#[error("PipelineError: err={0:?}")]
PipelineError(#[from] kona_derive::errors::PipelineErrorKind),
#[error("UnexpectedBlobSidecarLength: size={0}")]
UnexpectedBlobSidecarLength(usize),
}
107 changes: 88 additions & 19 deletions derivation/src/oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use kona_proof::l1::ROOTS_OF_UNITY;
use kona_proof::FlushableCache;
use sha2::{Digest, Sha256};

const SIDECAR_BLOB_SIZE: usize = 32;

#[derive(Clone, Debug, Default)]
pub struct MemoryOracleClient {
/// Avoid deepcopy by clone operation because the preimage size is so big.
Expand Down Expand Up @@ -104,9 +106,9 @@ impl TryFrom<Vec<Preimage>> for MemoryOracleClient {

// Ensure blob preimage is valid
let mut kzg_cache = HashSet::<Vec<u8>>::new();
for (key, data) in inner.iter() {
for (key, _) in inner.iter() {
if key.key_type() == PreimageKeyType::Blob {
verify_blob_preimage(key, data, &inner, &mut kzg_cache)?
verify_blob_preimage(key, &inner, &mut kzg_cache)?
} else if key.key_type() == PreimageKeyType::Precompile {
verify_precompile(key, &inner)?
}
Expand Down Expand Up @@ -169,12 +171,14 @@ fn verify_keccak256_preimage(key: &PreimageKey, data: &[u8]) -> Result<(), Error

fn verify_blob_preimage(
key: &PreimageKey,
data: &[u8],
preimages: &HashMap<PreimageKey, Vec<u8>>,
kzg_cache: &mut HashSet<Vec<u8>>,
) -> Result<(), Error> {
let blob_key = get_data_by_hash_key(key, preimages)
.map_err(|e| Error::NoPreimageKeyFoundInVerifyBlob(Box::new(e)))?;
if blob_key.len() != POSITION_FIELD_ELEMENT + 8 {
return Err(Error::UnexpectedBlobKey(blob_key.to_vec()));
}
let kzg_commitment = &blob_key[..BYTES_PER_COMMITMENT];
if kzg_cache.contains(kzg_commitment) {
return Ok(());
Expand All @@ -193,24 +197,19 @@ fn verify_blob_preimage(
.as_ref(),
)?;
let sidecar_blob = get_data_by_blob_key(blob_key, preimages)?;
if sidecar_blob.len() != SIDECAR_BLOB_SIZE {
return Err(Error::UnexpectedBlobSidecarLength(sidecar_blob.len()));
}
blob[(i as usize) << 5..(i as usize + 1) << 5].copy_from_slice(sidecar_blob);
}

// Require kzg_proof data to verify all the blob index
let kzg_proof = {
let field_element_index: [u8; 8] = blob_key[POSITION_FIELD_ELEMENT..]
.try_into()
.map_err(Error::UnexpectedBlobFieldIndex)?;
if u64::from_be_bytes(field_element_index) == FIELD_ELEMENTS_PER_BLOB {
data
} else {
// Get by 4096 index
let slice = &mut blob_key[POSITION_FIELD_ELEMENT..];
try_copy_slice(slice, FIELD_ELEMENTS_PER_BLOB.to_be_bytes().as_ref())?;
get_data_by_blob_key(blob_key, preimages).map_err(|e| {
Error::NoPreimageDataFoundInVerifyBlob(blob_key.to_vec(), Box::new(e))
})?
}
// Get by 4096 index
let slice = &mut blob_key[POSITION_FIELD_ELEMENT..];
try_copy_slice(slice, FIELD_ELEMENTS_PER_BLOB.to_be_bytes().as_ref())?;
get_data_by_blob_key(blob_key, preimages)
.map_err(|e| Error::NoPreimageDataFoundInVerifyBlob(blob_key.to_vec(), Box::new(e)))?
};
// Ensure valida blob
let kzg_blob = kzg_rs::Blob::from_slice(&blob).map_err(Error::UnexpectedKZGBlob)?;
Expand Down Expand Up @@ -251,7 +250,9 @@ fn try_copy_slice(slice: &mut [u8], value: &[u8]) -> Result<(), Error> {
#[cfg(test)]
mod test {
use crate::errors::Error;
use crate::oracle::{try_copy_slice, verify_blob_preimage, MemoryOracleClient};
use crate::oracle::{
try_copy_slice, verify_blob_preimage, MemoryOracleClient, SIDECAR_BLOB_SIZE,
};
use crate::types::Preimage;
use crate::POSITION_FIELD_ELEMENT;
use alloc::vec;
Expand Down Expand Up @@ -328,6 +329,28 @@ mod test {
}
}

#[test]
fn test_try_from_invalid_blob_key_error() {
let blob_key = [0u8; POSITION_FIELD_ELEMENT + 7];
let blob_key_hash = keccak256(blob_key);
let preimage = vec![
Preimage::new(
PreimageKey::new(*blob_key_hash, PreimageKeyType::Keccak256),
blob_key.to_vec(),
),
Preimage::new(
PreimageKey::new(*blob_key_hash, PreimageKeyType::Blob),
vec![].to_vec(),
),
];

let err = MemoryOracleClient::try_from(preimage).unwrap_err();
match err {
Error::UnexpectedBlobKey(_) => {}
_ => panic!("Unexpected error, got: {:?}", err),
}
}

#[test]
fn test_try_from_blob_no_kzg_proof_error() {
let mut blob_key = [0u8; POSITION_FIELD_ELEMENT + 8];
Expand Down Expand Up @@ -356,7 +379,7 @@ mod test {

let first_key = PreimageKey::new(*blob_key_hash, PreimageKeyType::Blob);
let mut cache = HashSet::new();
let err = verify_blob_preimage(&first_key, &[0u8; 10], &preimages, &mut cache).unwrap_err();
let err = verify_blob_preimage(&first_key, &preimages, &mut cache).unwrap_err();
match err {
Error::NoPreimageDataFoundInVerifyBlob(_, _) => {}
_ => panic!("Unexpected error, got: {:?}", err),
Expand Down Expand Up @@ -400,13 +423,59 @@ mod test {

let first_key = PreimageKey::new(*blob_key_hash, PreimageKeyType::Blob);
let mut cache = HashSet::new();
let err = verify_blob_preimage(&first_key, &[0u8; 10], &preimages, &mut cache).unwrap_err();
let err = verify_blob_preimage(&first_key, &preimages, &mut cache).unwrap_err();
match err {
Error::UnexpectedPreimageBlob(_) => {}
_ => panic!("Unexpected error, got: {:?}", err),
}
}

#[test]
fn test_verify_blob_preimage_error_invalid_sidecar() {
let mut blob_key = [0u8; POSITION_FIELD_ELEMENT + 8];
let mut preimages = HashMap::new();

for i in 0..FIELD_ELEMENTS_PER_BLOB {
blob_key[BYTES_PER_COMMITMENT..].copy_from_slice(
ROOTS_OF_UNITY[i as usize]
.into_bigint()
.to_bytes_be()
.as_ref(),
);
let blob_per_index_key = keccak256(blob_key);
let sidecar_blob = [0u8; SIDECAR_BLOB_SIZE - 1].to_vec();
preimages.insert(
PreimageKey::new(*blob_per_index_key, PreimageKeyType::Blob),
sidecar_blob,
);
}

let blob_key_hash = keccak256(blob_key);
let mut final_kzg_proof_key = blob_key;
final_kzg_proof_key[POSITION_FIELD_ELEMENT..]
.copy_from_slice((FIELD_ELEMENTS_PER_BLOB).to_be_bytes().as_ref());
let final_kzg_proof = [0u8; BYTES_PER_COMMITMENT];
let kzg_proof_key_hash = keccak256(final_kzg_proof_key);
preimages.insert(
PreimageKey::new(*blob_key_hash, PreimageKeyType::Keccak256),
blob_key.to_vec(),
);
preimages.insert(
PreimageKey::new(*kzg_proof_key_hash, PreimageKeyType::Blob),
final_kzg_proof.to_vec(),
);

let first_key = PreimageKey::new(*blob_key_hash, PreimageKeyType::Blob);
let mut cache = HashSet::new();
let err = verify_blob_preimage(&first_key, &preimages, &mut cache).unwrap_err();
match err {
Error::UnexpectedBlobSidecarLength(size) => {
assert_eq!(size, SIDECAR_BLOB_SIZE - 1);
}
_ => panic!("Unexpected error, got: {:?}", err),
}
}

#[test]
fn test_copy_slice_error() {
let mut slice = [0u8; 4];
Expand Down