diff --git a/proto/vendor/share/p2p/shwap/pb/shwap.proto b/proto/vendor/share/p2p/shwap/pb/shwap.proto index 6fe8bf39..cd042028 100644 --- a/proto/vendor/share/p2p/shwap/pb/shwap.proto +++ b/proto/vendor/share/p2p/shwap/pb/shwap.proto @@ -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 { diff --git a/types/src/error.rs b/types/src/error.rs index 27ff6848..b43cf588 100644 --- a/types/src/error.rs +++ b/types/src/error.rs @@ -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), diff --git a/types/src/namespaced_data.rs b/types/src/namespaced_data.rs index 7bc88ac4..c7750705 100644 --- a/types/src/namespaced_data.rs +++ b/types/src/namespaced_data.rs @@ -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}; @@ -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) { @@ -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 ]; @@ -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 = diff --git a/types/src/row.rs b/types/src/row.rs index 5fdff1b5..9ef91d3c 100644 --- a/types/src/row.rs +++ b/types/src/row.rs @@ -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 { @@ -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())); @@ -245,6 +243,16 @@ 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 = [ @@ -252,8 +260,8 @@ mod tests { 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::::read_bytes(bytes.as_ref()).unwrap(); @@ -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::::read_bytes(bytes.as_ref()).unwrap(); diff --git a/types/src/sample.rs b/types/src/sample.rs index 50ece608..184e5122 100644 --- a/types/src/sample.rs +++ b/types/src/sample.rs @@ -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; @@ -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, /// Proof of the inclusion of the share @@ -128,7 +126,7 @@ impl Sample { Ok(Sample { sample_id, - sample_proof_type: axis_type, + proof_type: axis_type, share, proof: proof.into(), }) @@ -136,14 +134,14 @@ impl Sample { /// 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( @@ -173,13 +171,16 @@ impl TryFrom 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()?, }) @@ -194,8 +195,11 @@ impl From 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(), + }, } } } @@ -261,12 +265,14 @@ impl SampleId { /// Number of bytes needed to represent `SampleId`. pub const fn size() -> usize { - RowId::size() + size_of::() + // 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 { @@ -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()), }) } } @@ -352,6 +358,16 @@ 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 = [ @@ -359,9 +375,9 @@ mod tests { 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::::read_bytes(bytes.as_ref()).unwrap(); diff --git a/types/test_data/shwap_samples/namespaced_data.data b/types/test_data/shwap_samples/namespaced_data.data index 55959180..590059d6 100644 Binary files a/types/test_data/shwap_samples/namespaced_data.data and b/types/test_data/shwap_samples/namespaced_data.data differ diff --git a/types/test_data/shwap_samples/row.data b/types/test_data/shwap_samples/row.data index fb572636..57c0d378 100644 Binary files a/types/test_data/shwap_samples/row.data and b/types/test_data/shwap_samples/row.data differ diff --git a/types/test_data/shwap_samples/sample.data b/types/test_data/shwap_samples/sample.data index b9f5e435..0432dee7 100644 Binary files a/types/test_data/shwap_samples/sample.data and b/types/test_data/shwap_samples/sample.data differ