From 5f50eea70dca0c285acd58cd1e866fee79cb3fde Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Fri, 16 Sep 2016 17:11:46 -0600 Subject: [PATCH] Added public verifier tool. --- .gitignore | 1 + Cargo.toml | 6 +++ src/coordinator.rs | 51 ++++++++++++++++++++---- src/player.rs | 6 +-- src/protocol/secrets.rs | 7 ++++ src/verifier.rs | 87 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 146 insertions(+), 12 deletions(-) create mode 100644 src/verifier.rs diff --git a/.gitignore b/.gitignore index 6c52cca..18beffd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ target r1cs pk vk +transcript diff --git a/Cargo.toml b/Cargo.toml index 3c8936a..3239242 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,12 @@ path = "src/coordinator.rs" # avoid duplicate tests test = false +[[bin]] +name = "verifier" +path = "src/verifier.rs" +# avoid duplicate tests +test = false + [[bin]] name = "player" path = "src/player.rs" diff --git a/src/coordinator.rs b/src/coordinator.rs index a61f10c..9ec9929 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -32,10 +32,11 @@ use bincode::SizeLimit::Infinite; use bincode::rustc_serialize::{encode_into, decode_from}; use std::time::Duration; -const LISTEN_ADDR: &'static str = "0.0.0.0:65530"; +const USE_DUMMY_CS: bool = true; +const LISTEN_ADDR: &'static str = "127.0.0.1:65530"; const NETWORK_MAGIC: [u8; 8] = [0xff, 0xff, 0x1f, 0xbb, 0x1c, 0xee, 0x00, 0x19]; -const PLAYERS: usize = 3; -pub const THREADS: usize = 128; +const PLAYERS: usize = 2; +pub const THREADS: usize = 8; #[derive(Clone)] struct ConnectionHandler { @@ -105,9 +106,21 @@ impl ConnectionHandler { fn run(&self, new_peers: Receiver<[u8; 8]>) { + use std::fs::File; + info!("Loading R1CS from disk and performing QAP reduction..."); - let cs = CS::from_file(); + let cs = { + if USE_DUMMY_CS { + CS::dummy() + } else { + CS::from_file() + } + }; + + info!("Creating transcript file..."); + let mut transcript = File::create("transcript").unwrap(); + encode_into(&PLAYERS, &mut transcript, Infinite).unwrap(); info!("Waiting for players to connect..."); @@ -117,9 +130,13 @@ impl ConnectionHandler { for peerid in new_peers.into_iter().take(PLAYERS) { info!("Initializing new player (peerid={})", peerid.to_hex()); info!("Asking for commitment to PublicKey (peerid={})", peerid.to_hex()); - commitments.push(self.read(&peerid)); + let comm = self.read(&peerid); + commitments.push(comm); info!("PublicKey Commitment received (peerid={})", peerid.to_hex()); peers.push(peerid); + + info!("Writing commitment to transcript"); + encode_into(&comm, &mut transcript, Infinite).unwrap(); } // The remote end should never hang up, so this should always be `PLAYERS`. @@ -135,10 +152,15 @@ impl ConnectionHandler { self.write(peerid, &stage1); - info!("Receiving stage1 transformation from peerid={}", peerid.to_hex()); - - // TODO: verify pubkey against comm + info!("Receiving public key from peerid={}", peerid.to_hex()); let pubkey = self.read::(peerid); + + if pubkey.hash() != *comm { + error!("Peer did not properly commit to their public key (peerid={})", peerid.to_hex()); + panic!("cannot recover."); + } + + info!("Receiving stage1 transformation from peerid={}", peerid.to_hex()); let new_stage1 = self.read::(peerid); info!("Verifying transformation of stage1 from peerid={}", peerid.to_hex()); @@ -147,6 +169,11 @@ impl ConnectionHandler { error!("Peer did not perform valid stage1 transformation (peerid={})", peerid.to_hex()); panic!("cannot recover."); } else { + info!("Writing `PublicKey` to transcript"); + encode_into(&pubkey, &mut transcript, Infinite).unwrap(); + info!("Writing new stage1 to transcript"); + encode_into(&new_stage1, &mut transcript, Infinite).unwrap(); + pubkeys.push(pubkey); stage1 = new_stage1; } @@ -170,6 +197,8 @@ impl ConnectionHandler { error!("Peer did not perform valid stage2 transformation (peerid={})", peerid.to_hex()); panic!("cannot recover."); } else { + info!("Writing new stage2 to transcript"); + encode_into(&new_stage2, &mut transcript, Infinite).unwrap(); stage2 = new_stage2; } } @@ -192,6 +221,8 @@ impl ConnectionHandler { error!("Peer did not perform valid stage3 transformation (peerid={})", peerid.to_hex()); panic!("cannot recover."); } else { + info!("Writing new stage3 to transcript"); + encode_into(&new_stage3, &mut transcript, Infinite).unwrap(); stage3 = new_stage3; } } @@ -203,6 +234,10 @@ impl ConnectionHandler { kp.write_to_disk(); info!("Keypair written to disk."); + + transcript.flush().unwrap(); + + info!("Transcript flushed to disk."); } fn accept(&self, peerid: [u8; 8], stream: TcpStream) { diff --git a/src/player.rs b/src/player.rs index f9f576e..731abfc 100644 --- a/src/player.rs +++ b/src/player.rs @@ -25,7 +25,7 @@ use std::time::Duration; use bincode::SizeLimit::Infinite; use bincode::rustc_serialize::{encode_into, decode_from}; -const COORDINATOR_ADDR: &'static str = "testrun.z.cash:65530"; +const COORDINATOR_ADDR: &'static str = "127.0.0.1:65530"; const NETWORK_MAGIC: [u8; 8] = [0xff, 0xff, 0x1f, 0xbb, 0x1c, 0xee, 0x00, 0x19]; pub const THREADS: usize = 8; @@ -113,9 +113,7 @@ fn main() { let privkey = PrivateKey::new(rng); let pubkey = privkey.pubkey(rng); - let commitment: [u8; 32] = [0; 32]; - - // TODO + let commitment = pubkey.hash(); handler.write(&commitment); // Get powers of tau. diff --git a/src/protocol/secrets.rs b/src/protocol/secrets.rs index e393479..178a221 100644 --- a/src/protocol/secrets.rs +++ b/src/protocol/secrets.rs @@ -5,6 +5,8 @@ use spair::*; use snark::*; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; +pub type PublicKeyHash = [u8; 32]; + pub struct PublicKey { f1: G2, // f1 f1pA: G2, // f1 * rho_a @@ -41,6 +43,11 @@ impl PublicKey { same_power(&self.gamma, &Spair::new(self.f2beta, self.f2betagamma).unwrap()) } + pub fn hash(&self) -> PublicKeyHash { + // TODO + [0xff; 32] + } + pub fn tau_g2(&self) -> Spair { self.tau.clone() } diff --git a/src/verifier.rs b/src/verifier.rs new file mode 100644 index 0000000..cd38680 --- /dev/null +++ b/src/verifier.rs @@ -0,0 +1,87 @@ +extern crate bn; +extern crate rand; +extern crate snark; +extern crate crossbeam; +extern crate rustc_serialize; +extern crate bincode; + +mod multicore; +mod qap; +mod protocol; +mod spair; + +use std::fs::File; +use std::io::{Read, Write}; +use protocol::*; +use snark::*; + +use bincode::SizeLimit::Infinite; +use bincode::rustc_serialize::{encode_into, decode_from}; + +const USE_DUMMY_CS: bool = true; +pub const THREADS: usize = 8; + +fn main() { + let mut f = File::open("transcript").unwrap(); + + let cs = { + if USE_DUMMY_CS { + CS::dummy() + } else { + CS::from_file() + } + }; + + let num_players: usize = decode_from(&mut f, Infinite).unwrap(); + println!("Number of players: {}", num_players); + + let mut commitments = vec![]; + let mut pubkeys = vec![]; + for i in 0..num_players { + let comm: [u8; 32] = decode_from(&mut f, Infinite).unwrap(); + commitments.push(comm); + } + + let mut stage1 = Stage1Contents::new(&cs); + + for i in 0..num_players { + let pubkey: PublicKey = decode_from(&mut f, Infinite).unwrap(); + + if pubkey.hash() != commitments[i] { + panic!("Invalid commitment from player {}", i); + } + + let new_stage: Stage1Contents = decode_from(&mut f, Infinite).unwrap(); + if !new_stage.verify_transform(&stage1, &pubkey) { + panic!("Invalid stage1 transformation from player {}", i); + } + + stage1 = new_stage; + pubkeys.push(pubkey); + } + + let mut stage2 = Stage2Contents::new(&cs, &stage1); + + for i in 0..num_players { + let new_stage: Stage2Contents = decode_from(&mut f, Infinite).unwrap(); + if !new_stage.verify_transform(&stage2, &pubkeys[i]) { + panic!("Invalid stage2 transformation from player {}", i); + } + + stage2 = new_stage; + } + + let mut stage3 = Stage3Contents::new(&stage2); + + for i in 0..num_players { + let new_stage: Stage3Contents = decode_from(&mut f, Infinite).unwrap(); + if !new_stage.verify_transform(&stage3, &pubkeys[i]) { + panic!("Invalid stage3 transformation from player {}", i); + } + + stage3 = new_stage; + } + + let kp = keypair(&cs, &stage1, &stage2, &stage3); + kp.write_to_disk(); +}