Skip to content

Commit

Permalink
fix(prover): Fix invalid proof across chunks (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Hennenfent authored Nov 21, 2020
1 parent 83f4c98 commit e627e2c
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 79 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
Cargo.lock
.idea/
16 changes: 16 additions & 0 deletions companion/src/instruction/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::fs::File;
use std::io::{self, prelude::*, BufReader, ErrorKind};

use reverie::algebra::gf2::BitScalar;
use reverie::algebra::RingElement;
use reverie::Instruction;

/// Simple relatively compact binary format
Expand Down Expand Up @@ -54,12 +55,22 @@ impl Parser<Instruction<BitScalar>> for InsParser {
let src_2 = read_index(&mut self.reader)?;
Ok(Some(Instruction::Add(dst, src_1, src_2)))
}
CODE_ADD_CONST => {
let dst = read_index(&mut self.reader)?;
let src = read_index(&mut self.reader)?;
Ok(Some(Instruction::AddConst(dst, src, BitScalar::ONE)))
}
CODE_MUL => {
let dst = read_index(&mut self.reader)?;
let src_1 = read_index(&mut self.reader)?;
let src_2 = read_index(&mut self.reader)?;
Ok(Some(Instruction::Mul(dst, src_1, src_2)))
}
CODE_MUL_CONST => {
let dst = read_index(&mut self.reader)?;
let src = read_index(&mut self.reader)?;
Ok(Some(Instruction::MulConst(dst, src, BitScalar::ZERO)))
}
CODE_INPUT => {
let dst = read_index(&mut self.reader)?;
Ok(Some(Instruction::Input(dst)))
Expand All @@ -72,6 +83,11 @@ impl Parser<Instruction<BitScalar>> for InsParser {
let src = read_index(&mut self.reader)?;
Ok(Some(Instruction::Output(src)))
}
CODE_LOCAL => {
let dst = read_index(&mut self.reader)?;
let src = read_index(&mut self.reader)?;
Ok(Some(Instruction::LocalOp(dst, src)))
}
_ => unimplemented!("unknown operation: {:?}", op[0]),
}
}
Expand Down
2 changes: 1 addition & 1 deletion companion/src/instruction/bristol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl Parser<Instruction<BitScalar>> for InsParser {
let dst = ins[1].parse().unwrap();
Ok(Some(Instruction::AddConst(dst, src, BitScalar::ZERO)))
}
_ => unimplemented!(),
_unk => unimplemented!("Parse error on token:: {}", _unk),
}
}
}
40 changes: 15 additions & 25 deletions companion/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ async fn verify<
proof_path: &str,
program_path: &str,
branch_paths: Option<Vec<&str>>,
) -> io::Result<Option<Vec<BitScalar>>> {
) -> io::Result<Result<Vec<BitScalar>, String>> {
let branch_vecs = load_branches::<BP>(branch_paths)?;

// collect branch slices
Expand All @@ -262,27 +262,18 @@ async fn verify<
let mut proof = BufReader::new(File::open(proof_path)?);

// parse preprocessing
let preprocessing: preprocessing::Proof<GF2P8> =
match read_vec(&mut proof)?.and_then(|v| preprocessing::Proof::<GF2P8>::deserialize(&v)) {
Some(proof) => proof,
None => {
return Ok(None);
}
};
let preprocessing: preprocessing::Proof<GF2P8> = read_vec(&mut proof)?
.and_then(|v| preprocessing::Proof::<GF2P8>::deserialize(&v))
.expect("Failed to deserialize proof after preprocessing");

let pp_output = match preprocessing.verify(&branches[..], program.rewind()?).await {
Some(output) => output,
None => {
return Ok(None);
}
None => panic!("Failed to verify preprocessed proof"),
};

let online = match read_vec(&mut proof)?.and_then(|v| online::Proof::<GF2P8>::deserialize(&v)) {
Some(proof) => proof,
None => {
return Ok(None);
}
};
let online = read_vec(&mut proof)?
.and_then(|v| online::Proof::<GF2P8>::deserialize(&v))
.expect("Failed to deserialize online proof");

// verify the online execution
let (send, recv) = bounded(100);
Expand All @@ -295,12 +286,11 @@ async fn verify<

mem::drop(send);

let online_output = match task_online.await {
Some(output) => output,
None => return Ok(None),
};
let online_output = task_online.await.unwrap();

Ok(online_output.check(&pp_output))
Ok(online_output
.check(&pp_output)
.ok_or_else(|| String::from("Online output check failed")))
}

async fn async_main() -> io::Result<()> {
Expand Down Expand Up @@ -425,11 +415,11 @@ async fn async_main() -> io::Result<()> {
_ => unreachable!(),
};
match res {
None => {
eprintln!("invalid proof");
Err(e) => {
eprintln!("Invalid proof: {}", e);
exit(-1)
}
Some(output) => println!("{:?}", output),
Ok(output) => println!("{:?}", output),
}
Ok(())
}
Expand Down
76 changes: 76 additions & 0 deletions src/algebra/gf2/domain8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,82 @@ mod test {
assert_eq!(batches_2, batches);
}
}

// test the platform dependent optimized version against the generic implementation
#[test]
fn test_pack_batch() {
let mut rng = thread_rng();
for _ in 0..100 {
let batches: [_; 16] = [
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
BitBatch::gen(&mut rng),
];

// serialize into a vector
let mut serialized: Vec<u8> = vec![];
BitBatch::pack(&mut serialized, batches.iter()).unwrap();

// deserialize and check equality
let mut result: Vec<BitBatch> = vec![];
BitBatch::unpack(&mut result, &serialized).unwrap();
assert_eq!(result.len(), batches.len());
for (i, res) in result.iter().enumerate() {
assert_eq!(batches[i], *res);
}
}
}

// test the platform dependent optimized version against the generic implementation
#[test]
fn test_pack_scalar() {
let mut rng = thread_rng();
for _ in 0..100 {
let batches: [_; 16] = [
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
BitScalar::gen(&mut rng),
];

// serialize into a vector
let mut serialized: Vec<u8> = vec![];
BitScalar::pack(&mut serialized, batches.iter()).unwrap();

// deserialize and check equality
let mut result: Vec<BitScalar> = vec![];
BitScalar::unpack(&mut result, &serialized).unwrap();
assert_eq!(result.len(), batches.len());
for (i, res) in result.iter().enumerate() {
assert_eq!(batches[i], *res);
}
}
}
}

#[cfg(test)]
Expand Down
6 changes: 6 additions & 0 deletions src/algebra/gf2/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,9 @@ impl RingElement for BitScalar {
const ONE: Self = Self(1);
const ZERO: Self = Self(0);
}

impl Samplable for BitScalar {
fn gen<R: RngCore>(rng: &mut R) -> BitScalar {
BitScalar(rng.gen::<u8>() & 1)
}
}
44 changes: 28 additions & 16 deletions src/online/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ mod test {
use crate::algebra::gf2::*;
use crate::preprocessing::PreprocessingOutput;
use crate::tests::*;
use std::future::Future;
use rand::thread_rng;
use rand::Rng;
Expand All @@ -105,37 +106,48 @@ mod test {
inputs: &[D::Scalar],
) {
let mut rng = thread_rng();
const R: usize = 32;
let mut seeds: [[u8; KEY_SIZE]; R] = [[0; KEY_SIZE]; R];
for i in 0..R {
rng.fill_bytes(&mut seeds[i]);
}
// create a proof of the program execution
let proof: Proof<D> = Proof::new(PreprocessingOutput::dummy(), program, inputs);
for seed in seeds.iter() {
// create a proof of the program execution
let (proof, _pp_output) =
preprocessing::Proof::new(*seed, &[], program.iter().cloned());
// evaluate program in the clear
let correct_output = evaluate_program::<D>(program, inputs);
// evaluate program in the clear
let correct_output = evaluate_program::<D>(program, inputs, &[]);
// extract the output from the proof
let proof_output = proof.verify(program).unwrap();
// extract the output from the proof
let proof_output = proof.verify(&[], program.iter().cloned());
// since the proof is generated correctly the proof output is "Some"
// with the same value as the clear evaluation
assert_eq!(
proof_output.unsafe_output(),
&correct_output[..],
"program = {:?}, inputs = {:?}",
program,
inputs
);
match proof_output.poll() {
Poll::Pending => (),
Poll::Ready(output) => {
// since the proof is generated correctly the proof output is "Some"
// with the same value as the clear evaluation
assert_eq!(
output.unsafe_output(),
&correct_output[..],
"program = {:?}, inputs = {:?}",
program,
inputs
);
}
}
}
}
fn test_random_proof<D: Domain>() {
let mut rng = thread_rng();
let inputs = (rng.gen::<usize>() % 126) + 1;
let length = (rng.gen::<usize>() % 1024) + 1;
let program = random_program::<D, _>(&mut rng, inputs, length, true);
let (ninputs, nbranch, program) = random_program::<D, _>(&mut rng, inputs, length);
for ins in program.iter() {
println!("{:?}", ins);
}
Expand Down
Loading

0 comments on commit e627e2c

Please sign in to comment.