Skip to main content

Scheme

Trait Scheme 

Source
pub trait Scheme:
    Debug
    + Clone
    + Send
    + Sync
    + 'static {
    type Commitment: Digest;
    type StrongShard: Clone + Debug + Eq + Codec<Cfg = CodecConfig> + Send + Sync + 'static;
    type WeakShard: Clone + Debug + Eq + Codec<Cfg = CodecConfig> + Send + Sync + 'static;
    type CheckingData: Clone + Send + Sync;
    type CheckedShard: Clone + Send + Sync;
    type Error: Debug + Send;

    // Required methods
    fn encode(
        config: &Config,
        data: impl Buf,
        strategy: &impl Strategy,
    ) -> Result<(Self::Commitment, Vec<Self::StrongShard>), Self::Error>;
    fn weaken(
        config: &Config,
        commitment: &Self::Commitment,
        index: u16,
        shard: Self::StrongShard,
    ) -> Result<(Self::CheckingData, Self::CheckedShard, Self::WeakShard), Self::Error>;
    fn check(
        config: &Config,
        commitment: &Self::Commitment,
        checking_data: &Self::CheckingData,
        index: u16,
        weak_shard: Self::WeakShard,
    ) -> Result<Self::CheckedShard, Self::Error>;
    fn decode(
        config: &Config,
        commitment: &Self::Commitment,
        checking_data: Self::CheckingData,
        shards: &[Self::CheckedShard],
        strategy: &impl Strategy,
    ) -> 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;
use commonware_parallel::Sequential;
use commonware_utils::NZU16;

const STRATEGY: Sequential = Sequential;

type RS = ReedSolomon<Sha256>;

let config = Config {
    minimum_shards: NZU16!(2),
    extra_shards: NZU16!(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(), &STRATEGY).unwrap();

// Each person produces weak shards, their own checked shard, and checking data
// to check other peoples weak shards.
let (mut checking_data_w_shard, weak_shards): (Vec<_>, Vec<_>) = shards
        .into_iter()
        .enumerate()
        .map(|(i, shard)| {
            let (checking_data, checked_shard, weak_shard) = RS::weaken(&config, &commitment, i as u16, shard).unwrap();
            ((checking_data, checked_shard), weak_shard)
        })
        .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, weak_shard) in weak_shards.into_iter().enumerate().skip(1) {
  checked_shards.push(RS::check(&config, &commitment, &checking_data, i as u16, weak_shard).unwrap())
}

let data2 = RS::decode(&config, &commitment, checking_data, &checked_shards[..2], &STRATEGY).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..], &STRATEGY).unwrap();
assert_eq!(&data[..], &data3[..]);

§Guarantees

Here are additional properties that implementors of this trait need to consider, and that users of this trait can rely on.

§Weaken vs Check

Scheme::weaken and Scheme::check should agree, even for malicious encoders.

It should not be possible for parties A and B to call weaken successfully, but then have either of them fail on the other’s shard when calling check.

In other words, if an honest party considers their shard to be correctly formed, then other honest parties which have successfully constructed their checking data will also agree with the shard being correct.

A violation of this property would be, for example, if a malicious payload could convince two parties that they both have valid shards, but then the checking data they produce from the malicious payload reports issues with those shards.

Required Associated Types§

Source

type Commitment: Digest

A commitment attesting to the shards of data.

Source

type StrongShard: Clone + Debug + Eq + Codec<Cfg = CodecConfig> + Send + Sync + 'static

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

Source

type WeakShard: Clone + Debug + Eq + Codec<Cfg = CodecConfig> + Send + Sync + 'static

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

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

Source

type CheckingData: Clone + Send + Sync

Data which can assist in checking shards.

Source

type CheckedShard: Clone + Send + Sync

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

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

Source

type Error: Debug + Send

The type of errors that can occur during encoding, weakening, checking, and decoding.

Required Methods§

Source

fn encode( config: &Config, data: impl Buf, strategy: &impl Strategy, ) -> Result<(Self::Commitment, Vec<Self::StrongShard>), 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 weaken( config: &Config, commitment: &Self::Commitment, index: u16, shard: Self::StrongShard, ) -> Result<(Self::CheckingData, Self::CheckedShard, Self::WeakShard), Self::Error>

Take your own shard, check it, and produce a Scheme::WeakShard 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, weak_shard: Self::WeakShard, ) -> Result<Self::CheckedShard, Self::Error>

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

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

This takes in an index, to make sure that the weak shard 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], strategy: &impl Strategy, ) -> 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§

Source§

impl<H: Hasher> Scheme for NoCoding<H>

Source§

impl<H: Hasher> Scheme for ReedSolomon<H>

Source§

type Commitment = <H as Hasher>::Digest

Source§

type StrongShard = Chunk<<H as Hasher>::Digest>

Source§

type WeakShard = Chunk<<H as Hasher>::Digest>

Source§

type CheckedShard = CheckedChunk<<H as Hasher>::Digest>

Source§

type CheckingData = ()

Source§

type Error = Error

Source§

impl<H: Hasher> Scheme for Zoda<H>

Source§

type Commitment = Summary

Source§

type StrongShard = StrongShard<<H as Hasher>::Digest>

Source§

type WeakShard = WeakShard<<H as Hasher>::Digest>

Source§

type CheckingData = CheckingData<<H as Hasher>::Digest>

Source§

type CheckedShard = CheckedShard

Source§

type Error = Error