diff --git a/adapters/celestia/src/types.rs b/adapters/celestia/src/types.rs index 591e7b636..951fca0d7 100644 --- a/adapters/celestia/src/types.rs +++ b/adapters/celestia/src/types.rs @@ -132,6 +132,7 @@ pub enum ValidationError { MissingTx, InvalidRowProof, InvalidSigner, + IncompleteData, } impl CelestiaHeader { diff --git a/adapters/celestia/src/verifier/mod.rs b/adapters/celestia/src/verifier/mod.rs index f0fef3d69..f5f62995f 100644 --- a/adapters/celestia/src/verifier/mod.rs +++ b/adapters/celestia/src/verifier/mod.rs @@ -248,9 +248,17 @@ impl da::DaVerifier for CelestiaVerifier { let mut blob_iter = blob_ref.data(); let mut blob_data = vec![0; blob_iter.remaining()]; blob_iter.copy_to_slice(blob_data.as_mut_slice()); - let tx_data = tx.data().acc(); - - assert_eq!(blob_data, *tx_data); + let tx_data = tx.data().accumulator(); + + match tx_data { + da::Accumulator::Completed(tx_data) => { + assert_eq!(blob_data, *tx_data); + } + // For now we bail and return, maybe want to change that behaviour in the future + da::Accumulator::InProgress(_) => { + return Err(ValidationError::IncompleteData); + } + } // Link blob commitment to e-tx commitment let expected_commitment = diff --git a/rollup-interface/src/state_machine/da.rs b/rollup-interface/src/state_machine/da.rs index 4a9f51853..b66f620fd 100644 --- a/rollup-interface/src/state_machine/da.rs +++ b/rollup-interface/src/state_machine/da.rs @@ -68,6 +68,17 @@ pub trait DaVerifier { ) -> Result<::ValidityCondition, Self::Error>; } +/// [`AccumulatorStatus`] is a wrapper around an accumulator vector that specifies +/// whether a [`CountedBufReader`] has finished reading the underlying buffer. +#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum Accumulator { + /// The underlying buffer has been completely read and [`Vec`] contains the result + Completed(Vec), + /// The underlying buffer still contains elements to be read. [`Vec`] contains the + /// accumulated elements. + InProgress(Vec), +} + #[derive(Debug, Clone, Serialize, Deserialize, BorshDeserialize, BorshSerialize, PartialEq)] /// Simple structure that implements the Read trait for a buffer and counts the number of bytes read from the beginning. /// Useful for the partial blob reading optimization: we know for each blob how many bytes have been read from the beginning. @@ -83,7 +94,7 @@ pub struct CountedBufReader { /// An accumulator that stores the data read from the blob buffer into a vector. /// Allows easy access to the data that has already been read - reading_acc: Vec, + accumulator: Accumulator, } impl CountedBufReader { @@ -93,7 +104,7 @@ impl CountedBufReader { CountedBufReader { inner, counter: 0, - reading_acc: Vec::with_capacity(buf_size), + accumulator: Accumulator::InProgress(Vec::with_capacity(buf_size)), } } @@ -103,9 +114,8 @@ impl CountedBufReader { } /// Getter: returns a reference to an accumulator of the blob data read by the rollup - /// TODO: Refactor - pub fn acc(&self) -> &Vec { - &self.reading_acc + pub fn accumulator(&self) -> &Accumulator { + &self.accumulator } /// Contains the total length of the data (length already read + length remaining) @@ -124,7 +134,25 @@ impl Read for CountedBufReader { let num_read = len_before_reading - self.inner.remaining(); - self.reading_acc.extend_from_slice(&buf[..buf_end]); + let inner_acc_vec = match &mut self.accumulator { + Accumulator::Completed(_) => { + // The accumulator is completed, we return 0 as no data was read into self + return Ok(0); + } + + Accumulator::InProgress(inner_vec) => inner_vec, + }; + + inner_acc_vec.extend_from_slice(&buf[..buf_end]); + + match self.inner.remaining() { + 0 => { + self.accumulator = Accumulator::Completed(inner_acc_vec.to_vec()); + } + _ => { + self.accumulator = Accumulator::InProgress(inner_acc_vec.to_vec()); + } + } self.counter += num_read;