mirror of
https://github.com/logos-storage/rust-poseidon-bn254-pure.git
synced 2026-05-17 18:09:55 +00:00
add some quickcheck tests for bigint
This commit is contained in:
parent
f6c30ed6e0
commit
0628b17ca1
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rust-poseidon-bn254-pure"
|
||||
version = "0.0.1"
|
||||
version = "0.0.2"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
authors = ["Balazs Komuves"]
|
||||
@ -11,13 +11,16 @@ default-run = "testmain"
|
||||
unroll = ">= 0.1.5"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = ">= 0.8"
|
||||
criterion = ">= 0.8"
|
||||
quickcheck = "1"
|
||||
quickcheck_macros = "1"
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
debug = false
|
||||
# debug = true
|
||||
|
||||
[[bin]]
|
||||
name = "testmain"
|
||||
|
||||
17
README.md
17
README.md
@ -39,24 +39,25 @@ There are three main types:
|
||||
- `BigInt<N>` is an unsigned big integer consisting of `N` words (so `2^(32*N)` or `2^(64*N)` bits);
|
||||
- `Felt`, short for "Field Element", is a prime field element in the standard representation
|
||||
(integers modulo `p`);
|
||||
- `Mont` is a field element in the Montgomery represntation. This is used internally
|
||||
for calculations, as the multiplications is much faster this way.
|
||||
- `Mont` is a field element in the Montgomery representation. This is used internally
|
||||
for calculations, as multiplication (the main bottleneck) is much faster this way.
|
||||
|
||||
The core functionality of the Poseidon family of hash functions is the _permutation_,
|
||||
which takes an array of `t` field elements, and returns the same:
|
||||
which takes an array of `t >= 2` field elements, and returns the same:
|
||||
|
||||
fn permute( [Felt; t] ) -> [Felt; t]
|
||||
|
||||
From this one can build all kind of stuff, including a proper hash function (using
|
||||
From this one can build all kinds of stuff, including a proper hash function (using
|
||||
the so-called "sponge construction). The latter is not implemented in `circomlib`,
|
||||
instead, what they have is a compression function parametrized by `t`:
|
||||
instead, what they have is a _compression function_ parametrized by `t`:
|
||||
|
||||
fn compress( [Felt; t-1] ) -> Felt
|
||||
|
||||
This takes `t-1` field elements and returns one (which is interpreted as a hash).
|
||||
This takes `t-1` field elements and returns a single one (which is interpreted as a hash.
|
||||
Note that a field element contains about 254 bits of information, which is pretty fine for a cryptographic hash output)
|
||||
|
||||
This is implemented by extending the input with a 0, applying the permutation, and
|
||||
taking the first element of the output vector (note: in `circomlib`, the extra 0 is
|
||||
This is implemented by extending the input with a `0`, applying the permutation, and
|
||||
taking the first element of the output vector (note: in `circomlib`, the extra `0` is
|
||||
at the beginning, not at the end, but that doesn't matter at all; just be consistent).
|
||||
|
||||
Remark: That extra zero (called the "capacity") is _extremely important_, without
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
use std::fmt;
|
||||
use std::cmp::{Ordering,min};
|
||||
use std::ops::{Add,Sub,RangeFull};
|
||||
use std::ops::{Neg,Add,Sub,RangeFull};
|
||||
|
||||
use std::random::{RandomSource,Distribution};
|
||||
|
||||
@ -22,7 +22,7 @@ use crate::bn254::constant::{PRIME_ARRAY};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct BigInt<const N: usize>([u32; N]);
|
||||
|
||||
pub type BigInt256 = BigInt<8>;
|
||||
@ -50,6 +50,11 @@ impl<const N: usize> BigInt<N> {
|
||||
//------------------------------------------------------------------------------
|
||||
// standard numeric traits
|
||||
|
||||
impl<const N: usize> Neg for BigInt<N> {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self { BigInt::neg(self) }
|
||||
}
|
||||
|
||||
impl<const N: usize> Add for BigInt<N> {
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self { BigInt::add(self,other) }
|
||||
@ -274,6 +279,11 @@ impl<const N: usize> BigInt<N> {
|
||||
out
|
||||
}
|
||||
|
||||
pub fn neg(big: BigInt<N>) -> BigInt<N> {
|
||||
BigInt::sub( BigInt::zero() , big )
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------
|
||||
// multiplication
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ use crate::bn254::montgomery::*;
|
||||
|
||||
type Big = BigInt<8>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Felt(Big);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -3,10 +3,15 @@
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
use quickcheck_macros::quickcheck;
|
||||
|
||||
use crate::bn254::bigint::*;
|
||||
use crate::bn254::test::properties::*;
|
||||
|
||||
type Big = BigInt<8>;
|
||||
type Big = BigInt<8>;
|
||||
type Big7 = BigInt<7>;
|
||||
type Big9 = BigInt<9>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -50,3 +55,82 @@ fn prop_to_from_bytes_be<const N: usize>(bs: [u8; 4*N]) -> bool {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// quickcheck property-based testing
|
||||
|
||||
impl<const N: usize> Group for BigInt<N> {}
|
||||
|
||||
// ...as you apparently cannot have an impl for an array...
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct ByteArray<const K: usize>([u8; K]);
|
||||
|
||||
impl<const K: usize> Arbitrary for ByteArray<K> {
|
||||
fn arbitrary(g: &mut Gen) -> ByteArray<K> {
|
||||
let mut bs: [u8; K] = [0; K];
|
||||
for i in 0..K {
|
||||
bs[i] = u8::arbitrary(g);
|
||||
}
|
||||
ByteArray(bs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Arbitrary for BigInt<N> {
|
||||
fn arbitrary(g: &mut Gen) -> BigInt<N> {
|
||||
let mut xs: [u32; N] = [0; N];
|
||||
for i in 0..N {
|
||||
xs[i] = u32::arbitrary(g);
|
||||
}
|
||||
BigInt::make(xs)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
#[quickcheck]
|
||||
fn from_to_bytes_le(x: Big7) -> bool { prop_from_to_bytes_le::<7>(x) }
|
||||
|
||||
#[quickcheck]
|
||||
fn from_to_bytes_be(x: Big7) -> bool { prop_from_to_bytes_be::<7>(x) }
|
||||
|
||||
#[quickcheck]
|
||||
fn to_fom_bytes_le(bs: ByteArray<{7*4}>) -> bool { prop_to_from_bytes_le::<7>(bs.0) }
|
||||
|
||||
#[quickcheck]
|
||||
fn to_fom_bytes_be (bs: ByteArray<{7*4}>) -> bool { prop_to_from_bytes_be::<7>(bs.0) }
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
#[quickcheck]
|
||||
fn left_additive_unit(x: Big) -> bool { prop_left_additive_unit(x) }
|
||||
|
||||
#[quickcheck]
|
||||
fn right_additive_unit(x: Big) -> bool { prop_right_additive_unit(x) }
|
||||
|
||||
#[quickcheck]
|
||||
fn sub_zero(x: Big) -> bool { prop_sub_zero(x) }
|
||||
|
||||
#[quickcheck]
|
||||
fn zero_sub(x: Big) -> bool { prop_zero_sub(x) }
|
||||
|
||||
#[quickcheck]
|
||||
fn add_commutative(x: Big, y: Big) -> bool { prop_add_commutative(x,y) }
|
||||
|
||||
#[quickcheck]
|
||||
fn sub_anticommutative(x: Big, y: Big) -> bool { prop_sub_anticommutative(x,y) }
|
||||
|
||||
#[quickcheck]
|
||||
fn neg_involutive(x: Big) -> bool { prop_neg_involutive(x) }
|
||||
|
||||
#[quickcheck]
|
||||
fn add_sub(x: Big, y: Big) -> bool { prop_add_sub(x,y) }
|
||||
|
||||
#[quickcheck]
|
||||
fn sub_add(x: Big, y: Big) -> bool { prop_sub_add(x,y) }
|
||||
|
||||
#[quickcheck]
|
||||
fn sub_neg_add(x: Big, y: Big) -> bool { prop_sub_neg_add(x,y) }
|
||||
|
||||
#[quickcheck]
|
||||
fn sub_add_neg(x: Big, y: Big) -> bool { prop_sub_add_neg(x,y) }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -9,9 +9,13 @@ use std::ops::{Neg,Add,Sub,Mul,Div};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
pub trait Group = Copy + Clone + Default + From<u32> + Eq + Neg<Output=Self> + Add<Output=Self> + Sub<Output=Self>;
|
||||
pub trait Ring = Group + Mul<Output=Self>;
|
||||
pub trait Field = Ring + Div<Output=Self>;
|
||||
// pub trait Group = Copy + Clone + Default + From<u32> + Eq + Neg<Output=Self> + Add<Output=Self> + Sub<Output=Self>;
|
||||
// pub trait Ring = Group + Mul<Output=Self>;
|
||||
// pub trait Field = Ring + Div<Output=Self>;
|
||||
|
||||
pub trait Group : Copy + Clone + Default + From<u32> + Eq + Neg<Output=Self> + Add<Output=Self> + Sub<Output=Self> {}
|
||||
pub trait Ring : Group + Mul<Output=Self> {}
|
||||
pub trait Field : Ring + Div<Output=Self> {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -42,7 +46,7 @@ pub fn prop_sub_zero<A: Group>(x: A) -> bool {
|
||||
x - zero::<A>() == x
|
||||
}
|
||||
|
||||
pub fn prop_zero_subo<A: Group>(x: A) -> bool {
|
||||
pub fn prop_zero_sub<A: Group>(x: A) -> bool {
|
||||
zero::<A>() - x == xneg(x)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user