use ark_bls12_381::{Fr, G1Projective};
use ark_ec::CurveGroup;
use ark_ff::PrimeField;
use ark_poly::univariate::DensePolynomial;
use ark_poly::DenseUVPolynomial;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
use ark_std::{ops::Div, test_rng};
use komodo::{
algebra::linalg::Matrix,
error::KomodoError,
fec::{decode, encode},
semi_avid::{build, prove, recode, verify, Block},
zk::setup,
};
fn run<F, G, P>() -> Result<(), KomodoError>
where
F: PrimeField,
G: CurveGroup<ScalarField = F>,
P: DenseUVPolynomial<F>,
for<'a, 'b> &'a P: Div<&'b P, Output = P>,
{
let mut rng = test_rng();
let (k, n) = (3, 6_usize);
let bytes = include_bytes!("../assets/dragoon_133x133.png").to_vec();
eprintln!("loaded {} bytes of data", bytes.len());
eprint!("creating trusted setup... ");
let powers = setup::<F, G>(bytes.len(), &mut rng)?;
eprintln!("done");
eprint!("building blocks... ");
let encoding_mat = &Matrix::random(k, n, &mut rng);
let shards = encode(&bytes, encoding_mat)?;
let proof = prove(&bytes, &powers, encoding_mat.height)?;
let blocks = build::<F, G, P>(&shards, &proof);
eprintln!("done");
eprint!("verifying blocks... ");
for block in &blocks {
assert!(verify(block, &powers)?);
}
let mut serialized = vec![0; blocks[0].serialized_size(Compress::No)];
blocks[0]
.serialize_with_mode(&mut serialized[..], Compress::No)
.unwrap();
let field_element_size = (F::MODULUS_BIT_SIZE as usize + 7) / 8;
const VEC_LEN_SIZE: usize = 8;
const HASH_SIZE: usize = 32;
const U32_SIZE: usize = 4;
let data_start_index =
U32_SIZE + VEC_LEN_SIZE + k * field_element_size + VEC_LEN_SIZE + HASH_SIZE + VEC_LEN_SIZE;
serialized[data_start_index] = 0x00;
let block: Block<F, G> =
Block::deserialize_with_mode(&serialized[..], Compress::No, Validate::No).unwrap();
assert!(!verify(&block, &powers)?);
eprintln!("all good");
eprint!("some recoding scenarii... ");
let b_0_1 = recode(&blocks[0..=1], &mut rng).unwrap().unwrap();
let shards = vec![
b_0_1.shard,
blocks[2].shard.clone(),
blocks[3].shard.clone(),
];
assert_eq!(bytes, decode(shards).unwrap());
let b_0_1 = recode(&[blocks[0].clone(), blocks[1].clone()], &mut rng)
.unwrap()
.unwrap();
let shards = vec![
blocks[0].shard.clone(),
blocks[1].shard.clone(),
b_0_1.shard,
];
assert!(decode(shards).is_err());
let b_0_1 = recode(&blocks[0..=1], &mut rng).unwrap().unwrap();
let b_2_3 = recode(&blocks[2..=3], &mut rng).unwrap().unwrap();
let b_1_4 = recode(&[blocks[1].clone(), blocks[4].clone()], &mut rng)
.unwrap()
.unwrap();
let shards = vec![b_0_1.shard, b_2_3.shard, b_1_4.shard];
assert_eq!(bytes, decode(shards).unwrap());
let fully_recoded_shards = (0..3)
.map(|_| recode(&blocks[0..=2], &mut rng).unwrap().unwrap().shard)
.collect();
assert_eq!(bytes, decode(fully_recoded_shards).unwrap());
eprintln!("all good");
Ok(())
}
fn main() {
run::<Fr, G1Projective, DensePolynomial<Fr>>().unwrap();
}