Scheme

Trait Scheme 

Source
pub trait Scheme:
    Debug
    + Clone
    + Send
    + Sync
    + 'static {
    type Commitment: Digest;
    type Shard: Clone + Eq + Codec + Send + Sync + 'static;
    type ReShard: Clone + Eq + Codec + Send + Sync + 'static;
    type CheckingData: Clone + Send;
    type CheckedShard;
    type Error: Debug;

    // Required methods
    fn encode(
        config: &Config,
        data: impl Buf,
    ) -> Result<(Self::Commitment, Vec<Self::Shard>), Self::Error>;
    fn reshard(
        config: &Config,
        commitment: &Self::Commitment,
        index: u16,
        shard: Self::Shard,
    ) -> Result<(Self::CheckingData, Self::CheckedShard, Self::ReShard), Self::Error>;
    fn check(
        config: &Config,
        commitment: &Self::Commitment,
        checking_data: &Self::CheckingData,
        index: u16,
        reshard: Self::ReShard,
    ) -> Result<Self::CheckedShard, Self::Error>;
    fn decode(
        config: &Config,
        commitment: &Self::Commitment,
        checking_data: Self::CheckingData,
        shards: &[Self::CheckedShard],
    ) -> Result<Vec<u8>, Self::Error>;
}
Expand description

A scheme for encoding data into pieces, and recovering the data from those pieces.

§Example

use commonware_coding::{Config, ReedSolomon, Scheme as _};
use commonware_cryptography::Sha256;

type RS = ReedSolomon<Sha256>;

let config = Config { minimum_shards: 2, extra_shards: 1 };
let data = b"Hello!";
// Turn the data into shards, and a commitment to those shards.
let (commitment, shards) =
     RS::encode(&config, data.as_slice()).unwrap();

// Each person produces reshards, their own checked shard, and checking data
// to check other peoples reshards.
let (mut checking_data_w_shard, reshards): (Vec<_>, Vec<_>) = shards
        .into_iter()
        .enumerate()
        .map(|(i, shard)| {
            let (checking_data, checked_shard, reshard) = RS::reshard(&config, &commitment, i as u16, shard).unwrap();
            ((checking_data, checked_shard), reshard)
        })
        .collect();
// Let's pretend that the last item is "ours"
let (checking_data, checked_shard) = checking_data_w_shard.pop().unwrap();
// We can use this checking_data to check the other shards.
let mut checked_shards = Vec::new();
checked_shards.push(checked_shard);
for (i, reshard) in reshards.into_iter().enumerate().skip(1) {
  checked_shards.push(RS::check(&config, &commitment, &checking_data, i as u16, reshard).unwrap())
}

let data2 = RS::decode(&config, &commitment, checking_data, &checked_shards[..2]).unwrap();
assert_eq!(&data[..], &data2[..]);

// Decoding works with different shards, with a guarantee to get the same result.
let data3 = RS::decode(&config, &commitment, checking_data, &checked_shards[1..]).unwrap();
assert_eq!(&data[..], &data3[..]);

Required Associated Types§

Source

type Commitment: Digest

A commitment attesting to the shards of data.

Source

type Shard: Clone + Eq + Codec + Send + Sync + 'static

A shard of data, to be received by a participant.

Source

type ReShard: Clone + Eq + Codec + Send + Sync + 'static

A shard shared with other participants, to aid them in reconstruction.

In most cases, this will be the same as Shard, but some schemes might have extra information in Shard that may not be necessary to reconstruct the data.

Source

type CheckingData: Clone + Send

Data which can assist in checking shards.

Source

type CheckedShard

A shard that has been checked for inclusion in the commitment.

This allows excluding Scheme::ReShards which are invalid, and shouldn’t be considered as progress towards meeting the minimum number of shards.

Source

type Error: Debug

Required Methods§

Source

fn encode( config: &Config, data: impl Buf, ) -> Result<(Self::Commitment, Vec<Self::Shard>), Self::Error>

Encode a piece of data, returning a commitment, along with shards, and proofs.

Each shard and proof is intended for exactly one participant. The number of shards returned should equal config.minimum_shards + config.extra_shards.

Source

fn reshard( config: &Config, commitment: &Self::Commitment, index: u16, shard: Self::Shard, ) -> Result<(Self::CheckingData, Self::CheckedShard, Self::ReShard), Self::Error>

Take your own shard, check it, and produce a Scheme::ReShard to forward to others.

This takes in an index, which is the index you expect the shard to be.

This will produce a Scheme::CheckedShard which counts towards the minimum number of shards you need to reconstruct the data, in Scheme::decode.

You also get Scheme::CheckingData, which has information you can use to check the shards you receive from others.

Source

fn check( config: &Config, commitment: &Self::Commitment, checking_data: &Self::CheckingData, index: u16, reshard: Self::ReShard, ) -> Result<Self::CheckedShard, Self::Error>

Check the integrity of a reshard, producing a checked shard.

This requires the Scheme::CheckingData produced by Scheme::reshard.

This takes in an index, to make sure that the reshard you’re checking is associated with the participant you expect it to be.

Source

fn decode( config: &Config, commitment: &Self::Commitment, checking_data: Self::CheckingData, shards: &[Self::CheckedShard], ) -> Result<Vec<u8>, Self::Error>

Decode the data from shards received from other participants.

The data must be decodeable with as few as config.minimum_shards, including your own shard.

Calls to this function with the same commitment, but with different shards, or shards in a different should also result in the same output data, or in failure. In other words, when using the decoding function in a broader system, you get a guarantee that every participant decoding will see the same final data, even if they receive different shards, or receive them in a different order.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§