Skip to content

Commit

Permalink
feat!(types): Align with Shwap spec (#232)
Browse files Browse the repository at this point in the history
* feat!(types): Align with Shwap spec

* apply review suggestions
  • Loading branch information
oblique authored Feb 28, 2024
1 parent 11bec55 commit f9b6e96
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 41 deletions.
12 changes: 6 additions & 6 deletions proto/vendor/share/p2p/shwap/pb/shwap.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ message Row {
repeated bytes row_half = 2;
}

enum SampleProofType {
RowSampleProofType = 0;
ColSampleProofType = 1;
enum ProofType {
RowProofType = 0;
ColProofType = 1;
}

message Sample {
bytes sample_id = 1;
SampleProofType sample_type = 2;
bytes sample_share = 3;
proof.pb.Proof sample_proof = 4;
bytes sample_share = 2;
proof.pb.Proof sample_proof = 3;
ProofType proof_type = 4;
}

message Data {
Expand Down
4 changes: 4 additions & 0 deletions types/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ pub enum Error {
#[error("Invalid axis type: {0}")]
InvalidAxis(i32),

/// Invalid Shwap proof type in Protobuf.
#[error("Invalid proof type: {0}")]
InvalidShwapProofType(i32),

/// Range proof verification error.
#[error("Range proof verification failed: {0:?}")]
RangeProofError(nmt_rs::simple_merkle::error::RangeProofError),
Expand Down
22 changes: 15 additions & 7 deletions types/src/namespaced_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use cid::CidGeneric;
use multihash::Multihash;
use serde::{Deserialize, Serialize};

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

Expand Down Expand Up @@ -157,10 +157,8 @@ impl NamespacedDataId {

/// Number of bytes needed to represent [`NamespacedDataId`].
pub const fn size() -> usize {
// size of:
// RowId + Namespace
// 10 + 29 = 39
RowId::size() + NS_SIZE
// Size MUST be 39 by the spec.
39
}

fn encode(&self, bytes: &mut BytesMut) {
Expand Down Expand Up @@ -248,8 +246,8 @@ mod tests {
0xA0, 0xF0, 0x01, // CID codec = 7820
0xA1, 0xF0, 0x01, // multihash code = 7821
0x27, // len = NAMESPACED_DATA_ID_SIZE = 39
64, 0, 0, 0, 0, 0, 0, 0, // block height = 64
7, 0, // row = 7
0, 0, 0, 0, 0, 0, 0, 64, // block height = 64
0, 7, // row = 7
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, // NS = 1
];
Expand All @@ -265,6 +263,16 @@ mod tests {
assert_eq!(data_id.row.index, 7);
}

#[test]
fn namespaced_data_id_size() {
assert_eq!(NamespacedDataId::size(), 39);

let data_id = NamespacedDataId::new(Namespace::new_v0(&[1]).unwrap(), 0, 1).unwrap();
let mut bytes = BytesMut::new();
data_id.encode(&mut bytes);
assert_eq!(bytes.len(), NamespacedDataId::size());
}

#[test]
fn multihash_invalid_code() {
let multihash =
Expand Down
28 changes: 18 additions & 10 deletions types/src/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,15 @@ impl RowId {

/// Number of bytes needed to represent [`RowId`]
pub const fn size() -> usize {
// size of:
// u16 + u64
// 2 + 8
// Size MUST be 12 by the spec.
10
}

pub(crate) fn encode(&self, bytes: &mut BytesMut) {
bytes.reserve(ROW_ID_SIZE);

bytes.put_u64_le(self.block_height);
bytes.put_u16_le(self.index);
bytes.put_u64(self.block_height);
bytes.put_u16(self.index);
}

pub(crate) fn decode(buffer: &[u8]) -> Result<Self, CidError> {
Expand All @@ -163,8 +161,8 @@ impl RowId {
}

let mut cursor = Cursor::new(buffer);
let block_height = cursor.get_u64_le();
let index = cursor.get_u16_le();
let block_height = cursor.get_u64();
let index = cursor.get_u16();

if block_height == 0 {
return Err(CidError::InvalidCid("Zero block height".to_string()));
Expand Down Expand Up @@ -245,15 +243,25 @@ mod tests {
assert!(matches!(row_err, Error::EdsIndexOutOfRange(_)));
}

#[test]
fn row_id_size() {
assert_eq!(RowId::size(), 10);

let row_id = RowId::new(0, 1).unwrap();
let mut bytes = BytesMut::new();
row_id.encode(&mut bytes);
assert_eq!(bytes.len(), RowId::size());
}

#[test]
fn from_buffer() {
let bytes = [
0x01, // CIDv1
0x90, 0xF0, 0x01, // CID codec = 7810
0x91, 0xF0, 0x01, // multihash code = 7811
0x0A, // len = ROW_ID_SIZE = 10
64, 0, 0, 0, 0, 0, 0, 0, // block height = 64
7, 0, // row index = 7
0, 0, 0, 0, 0, 0, 0, 64, // block height = 64
0, 7, // row index = 7
];

let cid = CidGeneric::<ROW_ID_SIZE>::read_bytes(bytes.as_ref()).unwrap();
Expand All @@ -274,7 +282,7 @@ mod tests {
0x91, 0xF0, 0x01, // code = 7811
0x0A, // len = ROW_ID_SIZE = 10
0, 0, 0, 0, 0, 0, 0, 0, // invalid block height = 0 !
7, 0, // row index = 7
0, 7, // row index = 7
];

let cid = CidGeneric::<ROW_ID_SIZE>::read_bytes(bytes.as_ref()).unwrap();
Expand Down
52 changes: 34 additions & 18 deletions types/src/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
//! [`Share`]: crate::Share
//! [`ExtendedDataSquare`]: crate::rsmt2d::ExtendedDataSquare
use std::mem::size_of;

use blockstore::block::CidError;
use bytes::{BufMut, BytesMut};
use celestia_proto::share::p2p::shwap::Sample as RawSample;
use celestia_proto::share::p2p::shwap::{ProofType as RawProofType, Sample as RawSample};
use celestia_tendermint_proto::Protobuf;
use cid::CidGeneric;
use multihash::Multihash;
Expand Down Expand Up @@ -50,7 +48,7 @@ pub struct Sample {
/// Location of the sample in the EDS and associated block height
pub sample_id: SampleId,
/// Indication whether sampling was done row or column-wise
pub sample_proof_type: AxisType,
pub proof_type: AxisType,
/// Share that is being sampled
pub share: Vec<u8>,
/// Proof of the inclusion of the share
Expand Down Expand Up @@ -128,22 +126,22 @@ impl Sample {

Ok(Sample {
sample_id,
sample_proof_type: axis_type,
proof_type: axis_type,
share,
proof: proof.into(),
})
}

/// verify sample with root hash from ExtendedHeader
pub fn verify(&self, dah: &DataAvailabilityHeader) -> Result<()> {
let index = match self.sample_proof_type {
let index = match self.proof_type {
AxisType::Row => self.sample_id.row.index,
AxisType::Col => self.sample_id.index,
}
.into();

let root = dah
.root(self.sample_proof_type, index)
.root(self.proof_type, index)
.ok_or(Error::EdsIndexOutOfRange(index))?;

let ns = if is_ods_square(
Expand Down Expand Up @@ -173,13 +171,16 @@ impl TryFrom<RawSample> for Sample {
};

let sample_id = SampleId::decode(&sample.sample_id)?;
let sample_proof_type = u8::try_from(sample.sample_type)
.map_err(|_| Error::InvalidAxis(sample.sample_type))?
.try_into()?;

let proof_type = match RawProofType::try_from(sample.proof_type) {
Ok(RawProofType::RowProofType) => AxisType::Row,
Ok(RawProofType::ColProofType) => AxisType::Col,
Err(_) => return Err(Error::InvalidShwapProofType(sample.proof_type)),
};

Ok(Sample {
sample_id,
sample_proof_type,
proof_type,
share: sample.sample_share,
proof: proof.try_into()?,
})
Expand All @@ -194,8 +195,11 @@ impl From<Sample> for RawSample {
RawSample {
sample_id: sample_id_bytes.to_vec(),
sample_share: sample.share.to_vec(),
sample_type: sample.sample_proof_type as u8 as i32,
sample_proof: Some(sample.proof.into()),
proof_type: match sample.proof_type {
AxisType::Row => RawProofType::RowProofType.into(),
AxisType::Col => RawProofType::ColProofType.into(),
},
}
}
}
Expand Down Expand Up @@ -261,12 +265,14 @@ impl SampleId {

/// Number of bytes needed to represent `SampleId`.
pub const fn size() -> usize {
RowId::size() + size_of::<u16>()
// Size MUST be 12 by the spec.
12
}

fn encode(&self, bytes: &mut BytesMut) {
bytes.reserve(Self::size());
self.row.encode(bytes);
bytes.put_u16_le(self.index);
bytes.put_u16(self.index);
}

fn decode(buffer: &[u8]) -> Result<Self, CidError> {
Expand All @@ -278,7 +284,7 @@ impl SampleId {
// RawSampleId len is defined as RowId::size + u16::size, these are safe
Ok(Self {
row: RowId::decode(row_id)?,
index: u16::from_le_bytes(index.try_into().unwrap()),
index: u16::from_be_bytes(index.try_into().unwrap()),
})
}
}
Expand Down Expand Up @@ -352,16 +358,26 @@ mod tests {
assert!(matches!(sample_err, Error::EdsIndexOutOfRange(99)));
}

#[test]
fn sample_id_size() {
assert_eq!(SampleId::size(), 12);

let sample_id = SampleId::new(0, 4, 1).unwrap();
let mut bytes = BytesMut::new();
sample_id.encode(&mut bytes);
assert_eq!(bytes.len(), SampleId::size());
}

#[test]
fn from_buffer() {
let bytes = [
0x01, // CIDv1
0x80, 0xF0, 0x01, // CID codec = 7800
0x81, 0xF0, 0x01, // multihash code = 7801
0x0C, // len = SAMPLE_ID_SIZE = 12
64, 0, 0, 0, 0, 0, 0, 0, // block height = 64
7, 0, // row index = 7
5, 0, // sample index = 5
0, 0, 0, 0, 0, 0, 0, 64, // block height = 64
0, 7, // row index = 7
0, 5, // sample index = 5
];

let cid = CidGeneric::<SAMPLE_ID_SIZE>::read_bytes(bytes.as_ref()).unwrap();
Expand Down
Binary file modified types/test_data/shwap_samples/namespaced_data.data
Binary file not shown.
Binary file modified types/test_data/shwap_samples/row.data
Binary file not shown.
Binary file modified types/test_data/shwap_samples/sample.data
Binary file not shown.

0 comments on commit f9b6e96

Please sign in to comment.