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§
Sourcetype Commitment: Digest
type Commitment: Digest
A commitment attesting to the shards of data.
Sourcetype Shard: Clone + Eq + Codec + Send + Sync + 'static
type Shard: Clone + Eq + Codec + Send + Sync + 'static
A shard of data, to be received by a participant.
Sourcetype ReShard: Clone + Eq + Codec + Send + Sync + 'static
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.
Sourcetype CheckingData: Clone + Send
type CheckingData: Clone + Send
Data which can assist in checking shards.
Sourcetype CheckedShard
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.
type Error: Debug
Required Methods§
Sourcefn encode(
config: &Config,
data: impl Buf,
) -> Result<(Self::Commitment, Vec<Self::Shard>), Self::Error>
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.
Sourcefn reshard(
config: &Config,
commitment: &Self::Commitment,
index: u16,
shard: Self::Shard,
) -> Result<(Self::CheckingData, Self::CheckedShard, Self::ReShard), Self::Error>
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.
Sourcefn check(
config: &Config,
commitment: &Self::Commitment,
checking_data: &Self::CheckingData,
index: u16,
reshard: Self::ReShard,
) -> Result<Self::CheckedShard, Self::Error>
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.
Sourcefn decode(
config: &Config,
commitment: &Self::Commitment,
checking_data: Self::CheckingData,
shards: &[Self::CheckedShard],
) -> Result<Vec<u8>, Self::Error>
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.