Skip to content

Commit

Permalink
Final fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fl0rek committed Jan 12, 2024
1 parent 2bc4dab commit 4361077
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 21 deletions.
2 changes: 1 addition & 1 deletion types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub use crate::data_availability_header::*;
pub use crate::error::*;
pub use crate::extended_header::*;
pub use crate::fraud_proof::FraudProof;
pub use crate::rsmt2d::ExtendedDataSquare;
pub use crate::rsmt2d::{AxisType, ExtendedDataSquare};
pub use crate::share::*;
pub use crate::sync::*;
pub use crate::validate::*;
49 changes: 46 additions & 3 deletions types/src/namespaced_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use tendermint_proto::Protobuf;

use crate::nmt::{Namespace, NamespaceProof, NS_SIZE};
use crate::row::RowId;
use crate::{Error, Result};
use crate::{DataAvailabilityHeader, Error, Result};

/// The size of the [`NamespacedDataId`] hash in `multihash`.
const NAMESPACED_DATA_ID_SIZE: usize = NamespacedDataId::size();
Expand Down Expand Up @@ -46,7 +46,7 @@ pub struct NamespacedDataId {
/// shares belonging to a particular namespace and a proof of their inclusion. If, for
/// particular EDS, shares from the namespace span multiple rows, one needs multiple
/// NamespacedData instances to cover the whole range.
#[derive(Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(try_from = "RawNamespacedData", into = "RawNamespacedData")]
pub struct NamespacedData {
/// Location of the shares on EDS
Expand All @@ -57,7 +57,50 @@ pub struct NamespacedData {
pub shares: Vec<Vec<u8>>,
}

impl NamespacedData {}
impl NamespacedData {
/// Verifies proof inside `NamespacedData` using a row root from [`DataAvailabilityHeader`]
///
/// #Example
/// ```no_run
/// use celestia_types::nmt::Namespace;
/// # use celestia_types::{ExtendedDataSquare, ExtendedHeader};
/// # fn get_extended_data_square(height: usize) -> ExtendedDataSquare {
/// # unimplemented!()
/// # }
/// # fn get_extended_header(height: usize) -> ExtendedHeader {
/// # unimplemented!()
/// # }
///
/// let block_height = 100;
/// let eds = get_extended_data_square(block_height);
/// let header = get_extended_header(block_height);
///
/// let namespace = Namespace::new_v0(&[1, 2, 3]).unwrap();
///
/// let rows = eds.get_namespaced_data(namespace, &header.dah, block_height as u64).unwrap();
/// for namespaced_data in rows {
/// namespaced_data.validate(&header.dah).unwrap()
/// }
/// ```
///
/// [`DataAvailabilityHeader`]: crate::DataAvailabilityHeader
pub fn validate(&self, dah: &DataAvailabilityHeader) -> Result<()> {
if self.shares.is_empty() {
return Err(Error::WrongProofType);
}

let namespace = self.namespaced_data_id.namespace;

let row = self.namespaced_data_id.row.index;
let root = dah
.row_root(row.into())
.ok_or(Error::EdsIndexOutOfRange(row.into()))?;

self.proof
.verify_complete_namespace(&root, &self.shares, *namespace)
.map_err(Error::RangeProofError)
}
}

impl Protobuf<RawNamespacedData> for NamespacedData {}

Expand Down
71 changes: 63 additions & 8 deletions types/src/rsmt2d.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::result::Result as StdResult;

use nmt_rs::NamespaceMerkleHasher;
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize};

use crate::namespaced_data::{NamespacedData, NamespacedDataId};
use crate::nmt::{Namespace, NamespacedSha2Hasher, Nmt, NS_SIZE};
Expand Down Expand Up @@ -131,7 +131,7 @@ impl TryFrom<u8> for AxisType {
/// [`Nmt`]: crate::nmt::Nmt
/// [`Share`]: crate::share::Share
/// [`DataAvailabilityHeader`]: crate::DataAvailabilityHeader
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct ExtendedDataSquare {
/// The raw data of the EDS.
#[serde(with = "tendermint_proto::serializers::bytes::vec_base64string")]
Expand All @@ -144,8 +144,8 @@ pub struct ExtendedDataSquare {
}

impl ExtendedDataSquare {
/// Create a new EDS out of the provided shares. Returns error if share number doesn't
/// create a square
/// Create a new EDS out of the provided shares. Returns error if number of shares isn't
/// a square number
pub fn new(shares: Vec<Vec<u8>>, codec: String) -> Result<Self> {
let square_len = f64::sqrt(shares.len() as f64) as usize;
if square_len * square_len != shares.len() {
Expand Down Expand Up @@ -213,11 +213,15 @@ impl ExtendedDataSquare {
}

let mut shares = Vec::with_capacity(self.square_len);

let mut tree = Nmt::with_hasher(NamespacedSha2Hasher::with_ignore_max_ns(true));
for s in self.row(i.into())? {
let ns = Namespace::from_raw(&s[..NS_SIZE])?;
tree.push_leaf(&s, *ns).map_err(Error::Nmt)?;
for (col, s) in self.row(i.into())?.iter().enumerate() {
let ns = if col < self.square_len / 2 {
Namespace::from_raw(&s[..NS_SIZE])?
} else {
Namespace::PARITY_SHARE
};

tree.push_leaf(s, *ns).map_err(Error::Nmt)?;
if ns == namespace {
shares.push(s.clone());
}
Expand All @@ -238,6 +242,29 @@ impl ExtendedDataSquare {
}
}

#[derive(Deserialize)]
struct RawExtendedDataSquare {
#[serde(with = "tendermint_proto::serializers::bytes::vec_base64string")]
pub data_square: Vec<Vec<u8>>,
pub codec: String,
}

impl<'de> Deserialize<'de> for ExtendedDataSquare {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let eds = RawExtendedDataSquare::deserialize(deserializer)?;
let share_number = eds.data_square.len();
ExtendedDataSquare::new(eds.data_square, eds.codec).map_err(|_| {
<D::Error as serde::de::Error>::invalid_length(
share_number,
&"number of shares must be a perfect square",
)
})
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -258,4 +285,32 @@ mod tests {
let axis_type_err = AxisType::try_from(99).unwrap_err();
assert!(matches!(axis_type_err, Error::InvalidAxis(99)));
}

#[test]
fn get_namespaced_data() {
let eds_json = include_str!("../test_data/shwap_samples/eds.json");
let eds: ExtendedDataSquare = serde_json::from_str(eds_json).unwrap();
let dah_json = include_str!("../test_data/shwap_samples/dah.json");
let dah: DataAvailabilityHeader = serde_json::from_str(dah_json).unwrap();

let height = 45577;

let rows = eds
.get_namespaced_data(Namespace::new_v0(&[1, 170]).unwrap(), &dah, height)
.unwrap();
assert_eq!(rows.len(), 1);
let row = &rows[0];
row.validate(&dah).unwrap();
assert_eq!(row.shares.len(), 2);

let rows = eds
.get_namespaced_data(Namespace::new_v0(&[1, 187]).unwrap(), &dah, height)
.unwrap();
assert_eq!(rows.len(), 2);
assert_eq!(rows[0].shares.len(), 1);
assert_eq!(rows[1].shares.len(), 4);
for row in rows {
row.validate(&dah).unwrap();
}
}
}
17 changes: 8 additions & 9 deletions types/src/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ impl Sample {
///
/// # Example
///
/// ```
/// use celestia_types::rsmt2d::AxisType;
/// # use celestia_types::rsmt2d::ExtendedDataSquare;
/// # use celestia_types::ExtendedHeader;
/// ```no_run
/// use celestia_types::AxisType;
/// use celestia_types::sample::Sample;
/// # use celestia_types::{ExtendedDataSquare, ExtendedHeader};
/// # fn get_extended_data_square(height: usize) -> ExtendedDataSquare {
/// # unimplemented!()
/// # }
Expand All @@ -87,13 +87,13 @@ impl Sample {
///
/// let block_height = 15;
/// let eds = get_extended_data_square(block_height);
/// let index = 2 * eds.square_len() + 3 // 3rd row and 4th column as these are 0 indexed
/// let index = 2 * eds.square_len() + 3; // 3rd row and 4th column as these are 0 indexed
///
/// let header = get_extended_header(block_height);
///
/// let sample = Sample::new(AxisType::Row, index, &eds, block_height).unwrap();
/// let sample = Sample::new(AxisType::Row, index, &eds, block_height as u64).unwrap();
///
/// sample.verify(&header.dah).unwrap();
/// sample.validate(&header.dah).unwrap();
/// ```
///
/// [`Share`]: crate::Share
Expand Down Expand Up @@ -143,7 +143,6 @@ impl Sample {

/// Validate sample with root hash from ExtendedHeader
pub fn validate(&self, dah: &DataAvailabilityHeader) -> Result<()> {
// TODO: tests
let index = match self.sample_proof_type {
AxisType::Row => self.sample_id.row.index,
AxisType::Col => self.sample_id.index,
Expand Down Expand Up @@ -245,7 +244,7 @@ impl SampleId {
/// header_height,
/// ).unwrap();
///
/// assert_eq!(sample_id.axis.index, row as u16);
/// assert_eq!(sample_id.row.index, row as u16);
/// assert_eq!(sample_id.index, col as u16);
/// ```
///
Expand Down
1 change: 1 addition & 0 deletions types/test_data/shwap_samples/dah.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"row_roots":["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuzZim3qjDRZz1y/Av5Hnrcejbn6fqzf7cYprMN/Tf1a+","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABu7QqhzEW7oSi39utdL2VagKS96rAOMeR2hOuBuaUIAH0","//////////////////////////////////////7//////////////////////////////////////uLSam+eudl+PFq2saaqVHCQkAeVAjSjiuRc4PslqTaj","//////////////////////////////////////7//////////////////////////////////////uLSam+eudl+PFq2saaqVHCQkAeVAjSjiuRc4PslqTaj","/////////////////////////////////////////////////////////////////////////////+C9srOpEP8aIQPftaH5Nf/Yf++2PnqE2p00qxxzxXxh","/////////////////////////////////////////////////////////////////////////////7ReoYDE95Gzoon16LDjfd7QdOJIP/qXg2xT73TOA2eg","/////////////////////////////////////////////////////////////////////////////wcULEPkvZIe5vOL2AaswgmDWIInCDPyhQwLpgvJSj26","/////////////////////////////////////////////////////////////////////////////w1LB7O0v/1hYE3Q1n529EUVia14bDOmRRfBw2Ni9NeL"],"column_roots":["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT//////////////////////////////////////ik2zOwnPN5JQCFvzZhOquyp4LNye4qUNDPjizr/op86","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAar//////////////////////////////////////pvWLwU0w/94d91Y0kaJCVvZbt85SoKWrTO9CEeVeyfW","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAar//////////////////////////////////////uKK84np9p1ZTBKA9OUWx4KGWGGpmr8iVcShKbV+jh3l","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbv//////////////////////////////////////sHft8buRgRGAJFh0nDF9btCdCUSmO2/s+4brdxxkc0r","/////////////////////////////////////////////////////////////////////////////7ghS332xkksl/45Of/XkyOHBZWWrvGSBCfJWiUy2v/O","/////////////////////////////////////////////////////////////////////////////4iAz0pKTz8LfqBGkO5Y/0akzoICnIZLlsjau63c5jX3","/////////////////////////////////////////////////////////////////////////////5AVAimFXckCaaIjAY2CSuKDsRT7jKaO5DRz3+uj8pkL","/////////////////////////////////////////////////////////////////////////////8Q6pkRX3eFkGx9RS3K/iYLPvRJ+Zy4VYslYsREY4PB2"]}
1 change: 1 addition & 0 deletions types/test_data/shwap_samples/eds.json

Large diffs are not rendered by default.

0 comments on commit 4361077

Please sign in to comment.