celestia_types/
namespace_data.rs1use bytes::{BufMut, BytesMut};
10use celestia_proto::shwap::RowNamespaceData as RawRowNamespaceData;
11use serde::{Deserialize, Serialize};
12
13use crate::eds::{EDS_ID_SIZE, EdsId};
14use crate::nmt::{NS_SIZE, Namespace};
15use crate::row_namespace_data::{RowNamespaceData, RowNamespaceDataId};
16use crate::{DataAvailabilityHeader, Error, Result, bail_verification};
17
18pub const NAMESPACE_DATA_ID_SIZE: usize = EDS_ID_SIZE + NS_SIZE;
20
21#[derive(Debug, PartialEq, Clone, Copy)]
26pub struct NamespaceDataId {
27 eds_id: EdsId,
28 namespace: Namespace,
29}
30
31#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35#[serde(transparent)]
36pub struct NamespaceData {
37 rows: Vec<RowNamespaceData>,
38}
39
40impl NamespaceData {
41 pub fn new(rows: Vec<RowNamespaceData>) -> Self {
43 NamespaceData { rows }
44 }
45
46 pub fn rows(&self) -> &[RowNamespaceData] {
48 &self.rows[..]
49 }
50
51 pub fn into_inner(self) -> Vec<RowNamespaceData> {
53 self.rows
54 }
55
56 pub fn verify(&self, id: NamespaceDataId, dah: &DataAvailabilityHeader) -> Result<()> {
58 if self.rows.len() > u16::MAX as usize {
59 return Err(Error::NamespaceDataTooLarge);
60 }
61
62 let row_idxs = (0..dah.square_width())
63 .filter(|&row| dah.row_contains(row, id.namespace).unwrap_or(false))
64 .collect::<Vec<_>>();
65
66 if row_idxs.len() != self.rows.len() {
67 bail_verification!(
68 "expected {} rows, found {} rows",
69 row_idxs.len(),
70 self.rows.len()
71 );
72 }
73
74 for (row, row_index) in self.rows.iter().zip(row_idxs.into_iter()) {
75 let ns_row_id = RowNamespaceDataId::new(id.namespace, row_index, id.block_height())?;
76 row.verify(ns_row_id, dah)?;
77 }
78
79 Ok(())
80 }
81
82 pub fn from_raw(id: NamespaceDataId, namespace_data: Vec<RawRowNamespaceData>) -> Result<Self> {
84 if namespace_data.len() > u16::MAX as usize {
85 return Err(Error::NamespaceDataTooLarge);
86 }
87
88 let mut rows = Vec::with_capacity(namespace_data.len());
89
90 for (row_index, raw_ns_data) in namespace_data.into_iter().enumerate() {
91 let ns_row_id =
92 RowNamespaceDataId::new(id.namespace, row_index as u16, id.block_height())?;
93 let ns_data = RowNamespaceData::from_raw(ns_row_id, raw_ns_data)?;
94 rows.push(ns_data);
95 }
96
97 Ok(NamespaceData::new(rows))
98 }
99}
100
101impl NamespaceDataId {
102 pub fn new(namespace: Namespace, block_height: u64) -> Result<Self> {
108 Ok(Self {
109 eds_id: EdsId::new(block_height)?,
110 namespace,
111 })
112 }
113
114 pub fn block_height(&self) -> u64 {
116 self.eds_id.block_height()
117 }
118
119 pub fn namespace(&self) -> Namespace {
123 self.namespace
124 }
125
126 pub fn encode(&self, bytes: &mut BytesMut) {
128 bytes.reserve(NAMESPACE_DATA_ID_SIZE);
129 self.eds_id.encode(bytes);
130 bytes.put(self.namespace.as_bytes());
131 }
132
133 pub fn decode(buffer: &[u8]) -> Result<Self> {
135 if buffer.len() != NAMESPACE_DATA_ID_SIZE {
136 return Err(Error::InvalidLength(buffer.len(), NAMESPACE_DATA_ID_SIZE));
137 }
138
139 let (eds_bytes, ns_bytes) = buffer.split_at(EDS_ID_SIZE);
140 let eds_id = EdsId::decode(eds_bytes)?;
141 let namespace = Namespace::from_raw(ns_bytes)?;
142
143 Ok(Self { eds_id, namespace })
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn decode_namespaced_shares() {
153 let get_shares_by_namespace_response = r#"[
154 {
155 "shares": [
156 "AAAAAAAAAAAAAAAAAAAAAAAAAAAADCBNOWAP3dMBAAAAG/HyDKgAfpEKO/iy5h2g8mvKB+94cXpupUFl9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
157 ],
158 "proof": {
159 "start": 1,
160 "end": 2,
161 "nodes": [
162 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFmTiyJVvgoyHdw7JGii/wyMfMbSdN3Nbi6Uj0Lcprk+",
163 "/////////////////////////////////////////////////////////////////////////////0WE8jz9lbFjpXWj9v7/QgdAxYEqy4ew9TMdqil/UFZm"
164 ],
165 "leaf_hash": null,
166 "is_max_namespace_ignored": true
167 }
168 }
169 ]"#;
170
171 let ns_shares: NamespaceData =
172 serde_json::from_str(get_shares_by_namespace_response).unwrap();
173
174 assert_eq!(ns_shares.rows()[0].shares.len(), 1);
175 assert!(!ns_shares.rows()[0].proof.is_of_absence());
176 }
177}