Skip to content

Commit

Permalink
Fibonacci proof branch (0xProject#7)
Browse files Browse the repository at this point in the history
* Added abstract proofs library, multi threading, and improved other systems
  • Loading branch information
aleph-v authored Jun 18, 2019
1 parent 9b3988b commit 0a1ee92
Show file tree
Hide file tree
Showing 14 changed files with 2,491 additions and 74 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# IDEs
.vscode
.DS_Store

# Generated by Cargo
# will have compiled files and executables
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ members = [
]

[dependencies]
crossbeam = "0.3.0"
rayon = "1.0.3"
hex = ""
hex-literal = "0.1.4"
tiny-keccak = "1.4.2"
lazy_static = "1.3.0"
Expand Down
41 changes: 39 additions & 2 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ use hex_literal::*;
use starkcrypto::curve::Affine;
use starkcrypto::ecdsa::{private_to_public, sign, verify};
use starkcrypto::fft::fft_cofactor;
use starkcrypto::fibonacci::*;
use starkcrypto::field::FieldElement;
use starkcrypto::gcd::gcd;
use starkcrypto::jacobian::Jacobian;
use starkcrypto::merkle::*;
use starkcrypto::pedersen::hash;
use starkcrypto::proofs::*;
use starkcrypto::square_root::square_root;
use starkcrypto::u256::U256;
use starkcrypto::u256h;
Expand Down Expand Up @@ -414,7 +416,7 @@ fn merkle_proof_make(crit: &mut Criterion) {
leaves.push(U256::from((i + 10).pow(3)));
}
crit.bench_function("Making depth 6 Merkle Tree", move |bench| {
bench.iter(|| black_box(make_tree(leaves.clone())))
bench.iter(|| black_box(make_tree(leaves.as_slice())))
});
}

Expand Down Expand Up @@ -455,6 +457,36 @@ fn fft_timing(crit: &mut Criterion) {
bench.iter(|| black_box(fft_cofactor(root.clone(), &vector, cofactor.clone())))
});
}
fn fib_proof_make(crit: &mut Criterion) {
let witness = FieldElement::from(u256h!(
"00000000000000000000000000000000000000000000000000000000cafebabe"
));

crit.bench_function("Making a Fibonacci Proof", move |bench| {
bench.iter(|| black_box(fib_proof(witness.clone())))
});
}
fn abstracted_fib_proof_make(crit: &mut Criterion) {
let claim_index = 1000_u64;
let claim_fib = FieldElement::from(u256h!(
"0142c45e5d743d10eae7ebb70f1526c65de7dbcdb65b322b6ddc36a812591e8f"
));
let witness = FieldElement::from(u256h!(
"00000000000000000000000000000000000000000000000000000000cafebabe"
));

crit.bench_function("Making an abstracted Fibonacci proof", move |bench| {
bench.iter(|| {
black_box(stark_proof(
&get_trace_table(1024, witness.clone()),
&get_constraint(),
claim_index,
claim_fib.clone(),
2_u64.pow(4),
))
})
});
}

fn criterion_benchmark(c: &mut Criterion) {
u256_add(c);
Expand Down Expand Up @@ -485,4 +517,9 @@ fn criterion_benchmark(c: &mut Criterion) {
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
criterion_group! {
name = slow_benches;
config = Criterion::default().sample_size(20);
targets = fib_proof_make, abstracted_fib_proof_make
}
criterion_main!(benches, slow_benches);
35 changes: 35 additions & 0 deletions examples/large_fib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use hex_literal::*;
use rayon::prelude;
use starkcrypto::fibonacci::*;
use starkcrypto::field::FieldElement;
use starkcrypto::proofs::*;
use starkcrypto::u256::*;
use starkcrypto::u256h;
use std::env;
use std::time::Instant;

fn main() {
let args: Vec<String> = env::args().collect();
rayon::ThreadPoolBuilder::new()
.num_threads(args[1].parse::<usize>().unwrap())
.build_global()
.unwrap();

let claim_index = 1000000_u64;
let witness = FieldElement::from(u256h!(
"00000000000000000000000000000000000000000000000000000000cafebabe"
));
let trace_table = get_trace_table(1048576, witness.clone());
let claim_fib = trace_table.elements[2000000].clone();
let start = Instant::now();
let potential_proof = stark_proof(
&trace_table,
&get_constraint(),
claim_index,
claim_fib,
2_u64.pow(4),
);
let duration = start.elapsed();
println!("{:?}", potential_proof.digest);
println!("Time elapsed in proof function is: {:?}", duration);
}
30 changes: 30 additions & 0 deletions examples/small_fib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use hex_literal::*;
use starkcrypto::fibonacci::*;
use starkcrypto::field::FieldElement;
use starkcrypto::proofs::*;
use starkcrypto::u256::*;
use starkcrypto::u256h;
use std::env;
use std::time::Instant;

fn main() {
let claim_index = 1000_u64;
let claim_fib = FieldElement::from(u256h!(
"0142c45e5d743d10eae7ebb70f1526c65de7dbcdb65b322b6ddc36a812591e8f"
));
let witness = FieldElement::from(u256h!(
"00000000000000000000000000000000000000000000000000000000cafebabe"
));
let trace_table = get_trace_table(1024, witness.clone());
let start = Instant::now();
let potential_proof = stark_proof(
&trace_table,
&get_constraint(),
claim_index,
claim_fib,
2_u64.pow(4),
);
let duration = start.elapsed();
println!("{:?}", potential_proof.digest);
println!("Time elapsed in proof function is: {:?}", duration);
}
82 changes: 82 additions & 0 deletions src/channel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use crate::field::*;
use crate::u256::U256;
use crate::u256h;
use hex_literal::*;
use tiny_keccak::Keccak;

#[derive(PartialEq, Eq, Clone, Default)]
pub struct Channel {
pub digest: [u8; 32],
pub counter: u64,
pub proof: Vec<u8>,
}

impl Channel {
pub fn new(data: &[u8]) -> Self {
let mut digest: [u8; 32] = [0; 32];
let mut sha3 = Keccak::new_keccak256();
sha3.update(data);
sha3.finalize(&mut digest);
let counter = 0;
let proof = data.to_vec();
Self {
digest,
counter,
proof,
}
}
pub fn write(&mut self, data: &[u8]) {
self.proof.extend_from_slice(data);
let mut res: [u8; 32] = [0; 32];
let mut sha3 = Keccak::new_keccak256();
sha3.update(&self.digest);
sha3.update(data);
sha3.finalize(&mut res);
self.digest = res;
self.counter = 0;
}
pub fn write_element(&mut self, data: &FieldElement) {
self.write(&data.0.to_bytes_be());
}
pub fn write_element_list(&mut self, data: &[FieldElement]) {
let mut container = Vec::with_capacity(32 * data.len());
for element in data {
for byte in U256::to_bytes_be(&element.0).iter() {
container.push(byte.clone());
}
}
self.write(&container.as_slice());
}
pub fn element(&mut self) -> FieldElement {
loop {
let mut res: [u8; 32] = [0; 32];
let zero = [0_u8; 24];
let mut sha3 = Keccak::new_keccak256();
sha3.update(&self.digest);
sha3.update(&zero);
sha3.update(&self.counter.to_be_bytes());
sha3.finalize(&mut res);
self.counter += 1;
let seed = U256::from_bytes_be(&res)
% u256h!("1000000000000000000000000000000000000000000000000000000000000000"); //2^256
if seed < MODULUS {
return FieldElement::from(seed)
/ FieldElement::from(u256h!(
"07fffffffffffdf0ffffffffffffffffffffffffffffffffffffffffffffffe1"
));
}
}
}
pub fn bytes(&mut self) -> [u8; 32] {
let mut res = [0; 32];
let zero = [0_u8; 24];
let mut sha3 = Keccak::new_keccak256();

sha3.update(&self.digest);
sha3.update(&zero);
sha3.update(&self.counter.to_be_bytes());
sha3.finalize(&mut res);
self.counter += 1;
res
}
}
75 changes: 49 additions & 26 deletions src/fft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,16 @@ use crate::u256::U256;
pub fn fft(root: FieldElement, vector: &[FieldElement]) -> Vec<FieldElement> {
//debug_assert(root.pow(vector.len()) == FieldElement::ONE); //Todo - Add a pow method to field element

let mut vector_type = (vector.clone()).to_vec();
let n = vector_type.len();

if n == 1 {
return vector_type;
}

let mut even = Vec::with_capacity(n / 2);
let mut odd = Vec::with_capacity(n / 2);
for index in (0..n).step_by(2) {
even.push(vector_type[index].clone());
odd.push(vector_type[index + 1].clone());
let mut data = (vector.to_vec()).clone();
let mut temp = FieldElement::ONE;
let mut pow_table = Vec::with_capacity(vector.len());
for _i in 0..(vector.len() / 2) {
pow_table.push(temp.clone());
temp *= &root;
}

even = fft((&root).square(), &(even.as_slice()));
odd = fft((&root).square(), &(odd.as_slice()));
let mut power = FieldElement::ONE;
for (even, odd) in even.iter_mut().zip(odd.iter_mut()) {
*odd *= &power;
let temp = even.clone(); //OPT - Check if this is compiled away
*even += odd.clone();
*odd = temp - odd.clone();
power *= &root;
}
(even).append(&mut odd);
even
fft_inplace(data.as_mut_slice(), pow_table.as_slice());
data
}

//We can implement this function using an option for the cofactor input, depending on what we want
Expand All @@ -38,8 +22,7 @@ pub fn fft_cofactor(
vector: &[FieldElement],
cofactor: FieldElement,
) -> Vec<FieldElement> {
let mut vector_type = (vector.clone()).to_vec();
let n = vector_type.len();
let mut vector_type = vector.to_vec();

let mut c = FieldElement::ONE;

Expand Down Expand Up @@ -77,6 +60,46 @@ pub fn ifft_cofactor(
}
r
}
//Using the Radix-2 algoritim
pub fn fft_inplace(vector: &mut [FieldElement], pow_table: &[FieldElement]) {
let n = vector.len();
let level = 64 - n.leading_zeros() - 1;
debug_assert_eq!(1 << level, n);

for i in 0..n {
let j = reverse(i as u64, level as usize);
if j > i {
vector.swap(j, i) //.swap is unsafe when i == j but this is impossible here TODO - potentially implement pure safe version
}
}
let mut size = 2;
while size <= n {
let halfstep = size / 2;
let tablestep = n / size;
for i in (0..n).step_by(size) {
let mut k = 0;
for j in i..(i + halfstep) {
let l = j + halfstep;
let left = vector[j].clone();
let right = &vector[l] * &pow_table[k];
vector[l] = &left - &right;
vector[j] = left + right;
k += tablestep;
}
}
size *= 2;
}
}

fn reverse(x: u64, bits: usize) -> usize {
let mut x_hold = x;
let mut y = 0;
for _i in 0..bits {
y = (y << 1) | (x_hold & 1);
x_hold >>= 1;
}
y as usize
}

#[cfg(test)]
mod tests {
Expand Down
Loading

0 comments on commit 0a1ee92

Please sign in to comment.