mirror of
https://github.com/logos-storage/rust-bn254-hash.git
synced 2026-01-02 13:53:09 +00:00
impl skyscraper
This commit is contained in:
parent
0db2f80df0
commit
88a662f034
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
.DS_Store
|
||||
.idea
|
||||
Cargo.lock
|
||||
/target
|
||||
/tmp
|
||||
|
||||
@ -9,6 +9,7 @@ Hash functions implemented:
|
||||
|
||||
- [x] Poseidon2
|
||||
- [x] Griffin
|
||||
- [x] skyscraper
|
||||
|
||||
We plan to integrate this into Plonky2, to allow an efficient BN254 recursive wrapper.
|
||||
For this we need some custom features: For example when computing the Fiat-Shamir
|
||||
|
||||
@ -3,7 +3,7 @@ use ark_ff::prelude::{Zero};
|
||||
use ark_bn254::Fr as F;
|
||||
|
||||
use crate::state::*;
|
||||
use crate::poseidon2;
|
||||
use crate::{poseidon2, skyscraper};
|
||||
use crate::griffin;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -7,3 +7,4 @@ pub mod hash;
|
||||
pub mod poseidon2;
|
||||
pub mod griffin;
|
||||
pub mod sponge;
|
||||
pub mod skyscraper;
|
||||
|
||||
90
src/skyscraper/constants.rs
Normal file
90
src/skyscraper/constants.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use std::str::FromStr;
|
||||
use lazy_static::lazy_static;
|
||||
use ark_bn254::Fr as F;
|
||||
use ark_ff::BigInteger256;
|
||||
|
||||
|
||||
/// enum for deciding which function (Square or Bar) to apply
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum FunctionBlock {
|
||||
Square,
|
||||
Bar,
|
||||
}
|
||||
|
||||
/// round schedule
|
||||
pub static RF1: [FunctionBlock; 10] = [
|
||||
FunctionBlock::Square, FunctionBlock::Square,
|
||||
FunctionBlock::Bar, FunctionBlock::Bar,
|
||||
FunctionBlock::Square, FunctionBlock::Square,
|
||||
FunctionBlock::Bar, FunctionBlock::Bar,
|
||||
FunctionBlock::Square, FunctionBlock::Square,
|
||||
];
|
||||
|
||||
/// round constants - same as in:
|
||||
/// https://extgit.isec.tugraz.at/krypto/zkfriendlyhashzoo/-/blob/master/plain_impls/src/skyscraper/skyscraper_instances.rs?ref_type=heads
|
||||
static RC_STR: [&str; 24] = [
|
||||
"17829420340877239108687448009732280677191990375576158938221412342251481978692",
|
||||
"27740342931201890067831390843279536630457710544396725670188095857896839417202",
|
||||
"17048088173265532689680903955395019356591870902241717143279822196003888806966",
|
||||
"109512792282736997633398631034649037613028427788284511060520396554381700616124",
|
||||
"23518768991468467328187394347260979305359711922005254253047385842741274989784",
|
||||
"95360373645575887695357714105933674592754581048282220961740831584356266637451",
|
||||
"57106046715138585370392400429108362862843547132381623658436718362793140581845",
|
||||
"16971509144034029782226530622087626979814683266929655790026304723118124142299",
|
||||
"8608910393531852188108777530736778805001620473682472554749734455948859886057",
|
||||
"54566392379700209585884878067585451869449334062644668287971552334629853792764",
|
||||
"18708129585851494907644197977764586873688181219062643217509404046560774277231",
|
||||
"52159802752268413629255578890890486811485406260370834838036769779232029980820",
|
||||
"98108525134123848500172941527936985409086875223276518679938863940387852105202",
|
||||
"105831033594660236721345339515389948186304708551041643590872398526195732523291",
|
||||
"53084450331558915295247017186532447841918727727492403087452333633170905880952",
|
||||
"78730946611419899835403512890231154575719512053287438310527615801825503526967",
|
||||
"62089842541186043938517187437087053794210809382724083686360536771123796704819",
|
||||
"32303085017979849099049635709265581104054174293154472699090841350494692332148",
|
||||
"19361794324495443451354916303398190341881571975219162871160427826227778850994",
|
||||
"65021267664773559966759214868166670507376995901124257419858229816098767301789",
|
||||
"94847021352352647235478120180321422709509900436733319635143815989658015262598",
|
||||
"51591271359432809566841356156562526830388219805637947403945613063492005256674",
|
||||
"44534956566050763472510245910556224585100739093572801527559057220740673520964",
|
||||
"84085239597197409225577945757724209425761279846653606664394225962327262179862",
|
||||
];
|
||||
|
||||
/// same as above but in raw representation (just for checking consistency)
|
||||
static RC_STR_RAW: [&str; 24] = [
|
||||
"17829420340877239108687448009732280677191990375576158938221412342251481978692",
|
||||
"5852100059362614845584985098022261541909346143980691326489891671321030921585",
|
||||
"17048088173265532689680903955395019356591870902241717143279822196003888806966",
|
||||
"71577923540621522166602308362662170286605786204339342029375621502658138039",
|
||||
"1630526119629192105940988602003704216811347521589219909349181656165466494167",
|
||||
"7807402158218786806372091124904574238561123446618083586948014838053032654983",
|
||||
"13329560971460034925899588938593812685746818331549554971040309989641523590611",
|
||||
"16971509144034029782226530622087626979814683266929655790026304723118124142299",
|
||||
"8608910393531852188108777530736778805001620473682472554749734455948859886057",
|
||||
"10789906636021659141392066577070901692352605261812599600575143961478236801530",
|
||||
"18708129585851494907644197977764586873688181219062643217509404046560774277231",
|
||||
"8383317008589863184762767400375936634388677459538766150640361406080412989586",
|
||||
"10555553646766747611187318546907885054893417621612381305146047194084618122734",
|
||||
"18278062107303135832359716534360847832111250949377506216079581779892498540823",
|
||||
"9307964587880364850754205696017897664821998926660334400055925260019288889718",
|
||||
"13066217995902074168664295654459329310074418852039335279433003242098078040116",
|
||||
"18313356797507493494024375946572503617114080581892014998964128397972179713585",
|
||||
"10414842146140573876803229964008306015505809892738438355392637163918883836531",
|
||||
"19361794324495443451354916303398190341881571975219162871160427826227778850994",
|
||||
"21244781921095009522266403377652120330280267100292188732461821442947150310555",
|
||||
"7294049864995546346492497199292322355316442835069182260350999243354781280130",
|
||||
"7814785615754259122348544666047976653291491004805878716549204690340388265440",
|
||||
"758470822372213028017434420041674408004010292740732840162648847589056529730",
|
||||
"18420510981679583558838728521952384160116186645405503633299613402599836693011",
|
||||
];
|
||||
|
||||
lazy_static! {
|
||||
pub static ref RC: Vec<F> = RC_STR
|
||||
.iter()
|
||||
.map(|s| F::new_unchecked(BigInteger256::from_str(s).unwrap()))
|
||||
.collect();
|
||||
|
||||
pub static ref RC_RAW: Vec<F> = RC_STR_RAW
|
||||
.iter()
|
||||
.map(|s| F::new_unchecked(BigInteger256::from_str(s).unwrap()))
|
||||
.collect();
|
||||
}
|
||||
2
src/skyscraper/mod.rs
Normal file
2
src/skyscraper/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod permutation;
|
||||
mod constants;
|
||||
145
src/skyscraper/permutation.rs
Normal file
145
src/skyscraper/permutation.rs
Normal file
@ -0,0 +1,145 @@
|
||||
use ark_bn254::{Fr as F};
|
||||
use ark_ff::{BigInteger256, Field, One, PrimeField};
|
||||
use core::str::FromStr;
|
||||
use crate::skyscraper::constants::{FunctionBlock, RF1, RC, RC_RAW};
|
||||
|
||||
pub fn bars_inplace_mont(x: &mut F) {
|
||||
// x → two 128‐bit chunks.
|
||||
let bi = x.0;
|
||||
let limbs = bi.0;
|
||||
let mut data = [0u128; 2];
|
||||
data[0] = (limbs[0] as u128) | ((limbs[1] as u128) << 64);
|
||||
data[1] = (limbs[2] as u128) | ((limbs[3] as u128) << 64);
|
||||
|
||||
let t_function = |value: u128| {
|
||||
let t1 = ((value & 0x80808080808080808080808080808080) >> 7) | ((value & 0x7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F) << 1); //circular left rot by 1
|
||||
let t2 = ((value & 0xC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0) >> 6) | ((value & 0x3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F) << 2); //circular left rot by 2
|
||||
let t3 = ((value & 0xE0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0) >> 5) | ((value & 0x1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F) << 3); //circular left rot by 3
|
||||
let tmp = (!t1 & t2 & t3) ^ value;
|
||||
((tmp & 0x80808080808080808080808080808080) >> 7) | ((tmp & 0x7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F) << 1) // Final left rot by 1
|
||||
};
|
||||
|
||||
// T‐function to each chunk.
|
||||
let tmp_lo = t_function(data[1]);
|
||||
let tmp_hi = t_function(data[0]);
|
||||
data[0] = tmp_lo;
|
||||
data[1] = tmp_hi;
|
||||
|
||||
// reduce
|
||||
reduce_small::<F>(&mut data);
|
||||
|
||||
// put back into x
|
||||
let (lo, hi) = (data[0], data[1]);
|
||||
let mut out = BigInteger256::new([0, 0, 0, 0]);
|
||||
out.0[0] = (lo & 0xFFFFFFFFFFFFFFFF) as u64;
|
||||
out.0[1] = (lo >> 64) as u64;
|
||||
out.0[2] = (hi & 0xFFFFFFFFFFFFFFFF) as u64;
|
||||
out.0[3] = (hi >> 64) as u64;
|
||||
|
||||
*x = F::new_unchecked(out)
|
||||
}
|
||||
|
||||
// same reduction strategy as in the zkfriendlyhashzoo
|
||||
fn reduce_small<F: PrimeField>(lhs: &mut [u128; 2]) {
|
||||
let p = F::characteristic(); // same as Modulus
|
||||
let pa = p.as_ref();
|
||||
// prime in two 128‐bit limbs
|
||||
let mut prime = [0u128; 2];
|
||||
prime[0] = (pa[0] as u128) | ((pa[1] as u128) << 64);
|
||||
prime[1] = (pa[2] as u128) | ((pa[3] as u128) << 64);
|
||||
|
||||
loop {
|
||||
for idx in (0..2).rev() {
|
||||
if lhs[idx] < prime[idx] {
|
||||
return;
|
||||
}
|
||||
if lhs[idx] > prime[idx] {
|
||||
sub_full(lhs, &prime);
|
||||
break;
|
||||
}
|
||||
if idx == 0 && lhs[idx] == prime[idx] {
|
||||
lhs[0] = 0;
|
||||
lhs[1] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sub_full(lhs: &mut [u128], rhs: &[u128]) {
|
||||
let mut overflow: bool;
|
||||
let mut overflow_part: u128;
|
||||
(lhs[0], overflow) = lhs[0].overflowing_sub(rhs[0]);
|
||||
overflow_part = if overflow {1} else {0};
|
||||
|
||||
for index in 1..rhs.len(){
|
||||
(lhs[index], overflow) = lhs[index].overflowing_sub(overflow_part);
|
||||
overflow_part = if overflow {1} else {0};
|
||||
(lhs[index], overflow) = lhs[index].overflowing_sub(rhs[index]);
|
||||
incr(&mut overflow_part, overflow);
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn incr(left: &mut u128, right: bool){
|
||||
if right {
|
||||
*left += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn square_inplace(x: &mut F) {
|
||||
*x *= *x;
|
||||
}
|
||||
|
||||
pub fn permute(input: [F; 2]) -> [F; 2] {
|
||||
let mut current_state = input;
|
||||
let mut left = current_state[0];
|
||||
let mut right = current_state[1];
|
||||
|
||||
for (i, &fun) in RF1.iter().enumerate() {
|
||||
// s‐box on `left`
|
||||
match fun {
|
||||
FunctionBlock::Square => square_inplace(&mut left),
|
||||
FunctionBlock::Bar => bars_inplace_mont(&mut left),
|
||||
}
|
||||
|
||||
if i > 0 && i < (RF1.len() - 1) {
|
||||
right += RC_RAW[i - 1];
|
||||
}
|
||||
|
||||
// combine
|
||||
left += right;
|
||||
|
||||
// the feistel rotation
|
||||
right = current_state[0];
|
||||
current_state[0] = left;
|
||||
}
|
||||
current_state[1] = right;
|
||||
current_state
|
||||
}
|
||||
|
||||
pub fn compress(x: F, y: F) -> F {
|
||||
let p_out = permute([x, y]);
|
||||
let out = x + p_out[0];
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_k_permutation() {
|
||||
let init = [F::from(1234u64), F::from(5678u64)];
|
||||
let init_mont = [F::new_unchecked(init[0].into_bigint()), F::new_unchecked(init[1].into_bigint())];
|
||||
let out = permute(init_mont);
|
||||
println!("Permutation on (1234,5678) => ({},{})", out[0].0, out[1].0);
|
||||
let expected = [
|
||||
BigInteger256::from_str("10398388528337208913702213361515546865573572771332206462397283188708690721181").unwrap(),
|
||||
BigInteger256::from_str("21827939006013637437091304277086947125806852726479468249428384625000968262245").unwrap()
|
||||
];
|
||||
|
||||
assert_eq!(out[0].0, expected[0]);
|
||||
assert_eq!(out[1].0, expected[1]);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user