Struct celestia_types::ExtendedDataSquare

source ·
pub struct ExtendedDataSquare { /* private fields */ }
Expand description

The data matrix in Celestia blocks extended with parity data.

It is created by a fixed size chunks of data, called Shares. Each share is a cell of the ExtendedDataSquare.

§Structure

The ExtendedDataSquare consists of four quadrants. The first quadrant (upper-left) is the original data submitted to the network, referred to as OriginalDataSquare. The other three quadrants are the parity data encoded row-wise or column-wise using Reed-Solomon codec specified in EDS.

The below diagram shows how the EDS is constructed. First, the 2nd and 3rd quadrants are created by computing Reed-Solomon parity data of the original data square, row-wise for 2nd and column-wise for 3rd quadrant. Then, the 4th quadrant is computed either row-wise from 3rd or column-wise from 2nd quadrant.

 ---------------------------
|             |             |
|           --|->           |
|      1    --|->    2      |
|           --|->           |
|    | | |    |             |
 -------------+-------------
|    v v v    |             |
|           --|->           |
|      3    --|->    4      |
|           --|->           |
|             |             |
 ---------------------------

§Data availability

The DataAvailabilityHeader is created by computing Nmt merkle roots of each row and column of ExtendedDataSquare. By putting those together there are some key properties those have in terms of data availability.

Thanks to the parity data, to make original data unrecoverable, a malicious actor would need to hide more than a half of the data from each row and column. If we take k as the width of the OriginalDataSquare, then the attacker needs to hide more than (k + 1)^2 shares from the ExtendedDataSquare. For the EDS with a width of 4, the attacker needs to hide more than 50% of all the shares and that value approaches 25% as the square grows.

This allows for really efficient data sampling, as the sampling node can reach very high confidence that whole data is available by taking only a few samples.

§Example

This example shows rebuilding the merkle trees for each row of the EDS and compares them with the root hashes stored in data availability header.

use celestia_types::Share;

let block_height = 15;
let header = get_header(block_height);
let eds = get_eds(block_height);
let width = header.dah.square_width();

// for each row of the data square, build an nmt
for row in 0..eds.square_width() {
    // check if the root corresponds to the one from the dah
    let root = eds.row_nmt(row).unwrap().root();
    assert_eq!(root, header.dah.row_root(row).unwrap());
}

Implementations§

source§

impl ExtendedDataSquare

source

pub fn new(shares: Vec<Vec<u8>>, codec: String) -> Result<Self>

Create a new EDS out of the provided shares.

Shares should be provided in a row-major order, i.e. first shares of the first row, then of the second row and so on.

§Errors

Returns an error if:

  • shares are of sizes different than SHARE_SIZE
  • amount of shares doesn’t allow for forming a square
  • width of the square is smaller than MIN_EXTENDED_SQUARE_WIDTH
  • width of the square is bigger than MAX_EXTENDED_SQUARE_WIDTH
  • width of the square isn’t a power of 2
  • namespaces of shares aren’t in non-decreasing order row and column wise
source

pub fn empty() -> ExtendedDataSquare

Crate a new EDS that represents an empty block

source

pub fn from_ods(ods_shares: Vec<Vec<u8>>) -> Result<ExtendedDataSquare>

Create a new EDS out of the provided original data square shares.

This method is similar to the ExtendedDataSquare::new but parity data will be encoded automatically using the leopard_codec

Shares should be provided in a row-major order.

§Errors

The same errors as in ExtendedDataSquare::new applies. The constrain will be checked after the parity data is generated.

Additionally, this function will propagate any error from encoding parity data.

source

pub fn data_square(&self) -> &[Vec<u8>]

The raw data of the EDS.

source

pub fn codec(&self) -> &str

The codec used to encode parity shares.

source

pub fn share(&self, row: u16, column: u16) -> Result<&[u8]>

Returns the share of the provided coordinates.

source

pub fn row(&self, index: u16) -> Result<Vec<Vec<u8>>>

Returns the shares of a row.

source

pub fn row_nmt(&self, index: u16) -> Result<Nmt>

Returns the Nmt of a row.

source

pub fn column(&self, index: u16) -> Result<Vec<Vec<u8>>>

Returns the shares of a column.

source

pub fn column_nmt(&self, index: u16) -> Result<Nmt>

Returns the Nmt of a column.

source

pub fn axis(&self, axis: AxisType, index: u16) -> Result<Vec<Vec<u8>>>

Returns the shares of column or row.

source

pub fn axis_nmt(&self, axis: AxisType, index: u16) -> Result<Nmt>

Returns the Nmt of column or row.

source

pub fn square_width(&self) -> u16

Get EDS square length.

source

pub fn get_namespaced_data( &self, namespace: Namespace, dah: &DataAvailabilityHeader, height: u64, ) -> Result<Vec<NamespacedData>>

Return all the shares that belong to the provided namespace in the EDS. Results are returned as a list of rows of shares with the inclusion proof.

Trait Implementations§

source§

impl Clone for ExtendedDataSquare

source§

fn clone(&self) -> ExtendedDataSquare

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for ExtendedDataSquare

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for ExtendedDataSquare

source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl PartialEq for ExtendedDataSquare

source§

fn eq(&self, other: &ExtendedDataSquare) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Serialize for ExtendedDataSquare

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Eq for ExtendedDataSquare

source§

impl StructuralPartialEq for ExtendedDataSquare

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<S> CondSend for S
where S: Send,

source§

impl<S> CondSync for S
where S: Send + Sync,

source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,