Set up basic client/server interaction.

This commit is contained in:
Sean Bowe 2016-02-09 00:36:09 -07:00
parent 96f05c11a4
commit eeb627aff7
4 changed files with 139 additions and 12 deletions

View File

@ -23,6 +23,8 @@ extern "C" void decrypt_solution(uint32_t n, uint8_t *enc, unsigned char* key) {
}
extern "C" void mysnark_init_public_params() {
libsnark::inhibit_profiling_info = true;
libsnark::inhibit_profiling_counters = true;
default_r1cs_ppzksnark_pp::init_public_params();
}

View File

@ -29,7 +29,7 @@ extern "C" {
fn decrypt_solution(n: uint32_t, enc: *mut uint8_t, key: *const uint8_t);
fn snark_verify(keypair: *const Keypair,
n: uint32_t,
proof: *const c_char,
proof: *const uint8_t,
proof_len: int32_t,
puzzle: *const uint8_t,
h_of_key: *const uint8_t,
@ -89,8 +89,8 @@ pub fn get_context(pk: &[u8], vk: &[u8], n: usize) -> Context {
}
}
pub fn prove<F: for<'a> FnMut(&'a [u8], &'a [i8])>(ctx: Context, puzzle: &[u8], solution: &[u8], key: &[u8], h_of_key: &[u8], mut f: F) -> bool {
let mut cb: &mut for<'a> FnMut(&'a [u8], &'a [i8]) = &mut f;
pub fn prove<F: for<'a> FnMut(&'a [u8], &'a [u8])>(ctx: &Context, puzzle: &[u8], solution: &[u8], key: &[u8], h_of_key: &[u8], mut f: F) -> bool {
let mut cb: &mut for<'a> FnMut(&'a [u8], &'a [u8]) = &mut f;
let cells = ctx.n.pow(4);
assert_eq!(puzzle.len(), cells);
@ -110,7 +110,7 @@ pub fn decrypt(ctx: Context, enc_solution: &mut [u8], key: &[u8])
unsafe { decrypt_solution(ctx.n as u32, &mut enc_solution[0], &key[0]); }
}
pub fn verify(ctx: Context, proof: &[i8], puzzle: &[u8], h_of_key: &[u8], encrypted_solution: &[u8]) -> bool
pub fn verify(ctx: &Context, proof: &[u8], puzzle: &[u8], h_of_key: &[u8], encrypted_solution: &[u8]) -> bool
{
assert_eq!(ctx.n.pow(4), encrypted_solution.len());
assert_eq!(ctx.n.pow(4), puzzle.len());

View File

@ -58,6 +58,18 @@ fn main() {
.required(true)
.validator(is_number))
)
.subcommand(SubCommand::with_name("serve")
.about("Opens a server for paying people to solve sudoku puzzles")
.arg(Arg::with_name("n")
.required(true)
.validator(is_number))
)
.subcommand(SubCommand::with_name("client")
.about("Connects to a server to receive payment to solve sudoku puzzles")
.arg(Arg::with_name("n")
.required(true)
.validator(is_number))
)
.get_matches();
if let Some(ref matches) = matches.subcommand_matches("gen") {
@ -74,6 +86,54 @@ fn main() {
});
}
if let Some(ref matches) = matches.subcommand_matches("client") {
println!("Loading proving/verifying keys...");
let n: usize = matches.value_of("n").unwrap().parse().unwrap();
let ctx = {
println!("\tProving key...");
let pk = decompress(&format!("{}.pk", n));
println!("\tVerifying key...");
let vk = decompress(&format!("{}.vk", n));
println!("\tDeserializing...");
get_context(&pk, &vk, n)
};
let mut stream = TcpStream::connect("127.0.0.1:25519").unwrap();
handle_server(&mut stream, &ctx, n);
}
if let Some(ref matches) = matches.subcommand_matches("serve") {
println!("Loading proving/verifying keys...");
let n: usize = matches.value_of("n").unwrap().parse().unwrap();
let ctx = {
println!("\tProving key...");
let pk = decompress(&format!("{}.pk", n));
println!("\tVerifying key...");
let vk = decompress(&format!("{}.vk", n));
println!("\tDeserializing...");
get_context(&pk, &vk, n)
};
let listener = TcpListener::bind("0.0.0.0:25519").unwrap();
println!("Opened listener. Instruct client to connect.");
for stream in listener.incoming() {
match stream {
Ok(mut stream) => {
handle_client(&mut stream, &ctx, n);
},
Err(_) => {}
}
}
}
if let Some(ref matches) = matches.subcommand_matches("test") {
println!("Loading proving/verifying keys...");
let n: usize = matches.value_of("n").unwrap().parse().unwrap();
@ -103,12 +163,77 @@ fn main() {
println!("Generating proof...");
assert!(prove(ctx, &puzzle, &solution, &key, &h_of_key,
assert!(prove(&ctx, &puzzle, &solution, &key, &h_of_key,
|encrypted_solution, proof| {}));
}
}
}
fn handle_client(stream: &mut TcpStream, ctx: &Context, n: usize) -> Result<(), ProtoError> {
println!("Connected!");
println!("Generating puzzle...");
let puzzle = Sudoku::gen(n);
try!(serialize_into(stream, &puzzle, Infinite));
println!("Waiting for proof that the client has a solution...");
let proof: Cow<[u8]> = deserialize_from(stream, Infinite).unwrap();
let encrypted_solution: Cow<[u8]> = deserialize_from(stream, Infinite).unwrap();
let mut h_of_key: Vec<u8> = deserialize_from(stream, Infinite).unwrap();
println!("Verifying proof.");
if (!verify(ctx, &proof, &puzzle, &h_of_key, &encrypted_solution)) {
println!("Proof is invalid!");
return Err(ProtoError);
}
println!("Proof verified!");
Ok(())
}
fn handle_server(stream: &mut TcpStream, ctx: &Context, n: usize) -> Result<(), ProtoError> {
println!("Waiting for server to give us a puzzle...");
let puzzle: Vec<u8> = deserialize_from(stream, Infinite).unwrap();
println!("Received puzzle:");
print_sudoku(n*n, &puzzle);
println!("Solving puzzle...");
let solution: Vec<u8> = Sudoku::import_and_solve(n, &puzzle).unwrap();
print_sudoku(n*n, &solution);
let key = vec![206, 64, 25, 10, 245, 205, 246, 107, 191, 157, 114, 181, 63, 40, 95, 134, 6, 178, 210, 43, 243, 10, 217, 251, 246, 248, 0, 21, 86, 194, 100, 94];
let h_of_key = vec![253, 199, 66, 55, 24, 155, 80, 121, 138, 60, 36, 201, 186, 221, 164, 65, 194, 53, 192, 159, 252, 7, 194, 24, 200, 217, 57, 55, 45, 204, 71, 9];
println!("Generating proof...");
assert!(prove(ctx, &puzzle, &solution, &key, &h_of_key, |encrypted_solution, proof| {
println!("Sending proof, encrypted_solution and h_of_key to the server.");
let encrypted_solution = Cow::Borrowed(encrypted_solution);
let proof = Cow::Borrowed(proof);
serialize_into(stream, &proof, Infinite);
serialize_into(stream, &encrypted_solution, Infinite);
serialize_into(stream, &h_of_key, Infinite);
}));
Ok(())
}
struct ProtoError;
impl From<bincode::serde::SerializeError> for ProtoError {
fn from(a: bincode::serde::SerializeError) -> ProtoError {
ProtoError
}
}
/*
fn main() {
initialize();

View File

@ -80,7 +80,7 @@ pub struct Sudoku {
}
impl Sudoku {
pub fn gen(n: usize) -> Vec<usize> {
pub fn gen(n: usize) -> Vec<u8> {
use rand::thread_rng;
let mut rng = thread_rng();
@ -90,7 +90,7 @@ impl Sudoku {
grid.export()
}
pub fn import_and_solve(n: usize, puzzle: &[usize]) -> Option<Vec<usize>> {
pub fn import_and_solve(n: usize, puzzle: &[u8]) -> Option<Vec<u8>> {
use rand::thread_rng;
let mut rng = thread_rng();
@ -136,21 +136,21 @@ impl Sudoku {
}
}
pub fn inject(&self, other: &[usize]) {
pub fn inject(&self, other: &[u8]) {
for (i, &to) in other.iter().enumerate() {
if to != 0 {
self.cells[i].set(to);
self.cells[i].set(to as usize);
}
}
}
pub fn export(&self) -> Vec<usize> {
pub fn export(&self) -> Vec<u8> {
let mut acc = vec![];
for i in 0..(self.dimension * self.dimension) {
match self.cells[i].get() {
Some(val) => {
acc.push(val);
acc.push(val as u8);
},
None => {
acc.push(0);
@ -231,7 +231,7 @@ impl Sudoku {
pub fn clearsome<R: Rng>(&mut self, rng: &mut R) {
for i in 0..(self.dimension * self.dimension) {
if rng.gen_weighted_bool(5) {
if rng.gen_weighted_bool(2) {
self.cells[i].unset();
}
}