Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: poseidon2 hash #885

Merged
merged 88 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
6cd6c00
Merge branch 'dev' into kevjue/static_proofs
kevjue Jun 3, 2024
00f1372
new columns for hash
kevjue Jun 4, 2024
cd453f6
compiler and runtime changes
kevjue Jun 5, 2024
b7b3439
Revert "new columns for hash"
kevjue Jun 5, 2024
824b6fa
compiler fixes
kevjue Jun 5, 2024
a098543
fixed some bugs
kevjue Jun 5, 2024
ec243f3
state_idx increment working
kevjue Jun 5, 2024
c9cfba4
working
kevjue Jun 5, 2024
a33f358
unit test work
kevjue Jun 5, 2024
20928e1
saved proofs
kevjue Jun 5, 2024
afcb78d
more saved tests
kevjue Jun 5, 2024
47e0413
test_e2e_runtime
kevjue Jun 5, 2024
50d4f57
new p2 columns
kevjue Jun 9, 2024
19b2098
runtime and event changes
kevjue Jun 9, 2024
35f1a4a
trace gen of inputs
kevjue Jun 10, 2024
22c23b9
compress trace gen
kevjue Jun 10, 2024
aa72ac8
compress output trace gen
kevjue Jun 10, 2024
d2f1982
generate trace test
kevjue Jun 10, 2024
accafb7
compress air
kevjue Jun 10, 2024
1088914
degree 3 tests pass
kevjue Jun 10, 2024
ee40c16
two row compress
kevjue Jun 10, 2024
df42465
fixed some bugs
kevjue Jun 10, 2024
5afd0c8
fixed bugs
kevjue Jun 10, 2024
cbc50b3
some refactor
kevjue Jun 10, 2024
7e58386
constrain the next row's output
kevjue Jun 10, 2024
7bb609c
split up files
kevjue Jun 10, 2024
88dca0c
fixed too high degree bug
kevjue Jun 10, 2024
64669e8
check cumulative sum
kevjue Jun 11, 2024
c25eecc
fixed cumulative sum bug
kevjue Jun 11, 2024
17a5736
no sbox version works
kevjue Jun 12, 2024
79f6778
changed degree 7 to degree 9 and new half_external permutation struct
kevjue Jun 12, 2024
7acbf13
control flow contraints
kevjue Jun 12, 2024
70172e4
control flow and syscall constraints work
kevjue Jun 12, 2024
341faa7
memory constraints working
kevjue Jun 13, 2024
3eb18e2
compress permutation constraints working
kevjue Jun 13, 2024
a0c34e5
refactor of the trace gen
kevjue Jun 13, 2024
e6d96e0
p2 hash permutation constraints work
kevjue Jun 14, 2024
f3b132d
compress transition constraint
kevjue Jun 14, 2024
633bce1
absorb state transition constraints
kevjue Jun 14, 2024
bf3715b
finalize state transition constraint
kevjue Jun 14, 2024
016eab9
global control flow constraints
kevjue Jun 15, 2024
6724e28
checkpoint
kevjue Jun 15, 2024
9b3dba0
removed is_input column
kevjue Jun 15, 2024
37ad95b
some cleanup
kevjue Jun 15, 2024
b24c048
control flow flags done
kevjue Jun 16, 2024
5996ad3
checkpoint
kevjue Jun 16, 2024
fbb9331
some refactoring
kevjue Jun 17, 2024
ca4e4d0
removed do_perm column
kevjue Jun 17, 2024
ef4110b
more cleanup, comments
kevjue Jun 17, 2024
9e1facd
cleanup and commenting of ctonrol_flow.rs
kevjue Jun 17, 2024
482b59a
comment and cleanup syscall_params air
kevjue Jun 17, 2024
a1665d3
bug fix
kevjue Jun 17, 2024
2d8f7a1
initial changes
kevjue Jun 17, 2024
8b23849
cleanup of air/memory.rs
kevjue Jun 17, 2024
1096682
comments and cleanup for permutation and state_transition airs
kevjue Jun 17, 2024
8635f6a
removed warnings
kevjue Jun 17, 2024
a5a636c
removed copy paste derive function
kevjue Jun 18, 2024
19e3b8e
merged from og branch
kevjue Jun 18, 2024
bbc14ee
merged dev
kevjue Jun 18, 2024
f938ef2
Merge branch 'kevjue/p2_hash' into kevjue/degree_17
kevjue Jun 18, 2024
5ec0e76
some changes for multi
kevjue Jun 18, 2024
eb29a77
multi table changes for fri fold
kevjue Jun 18, 2024
37dee33
changes to multi for poseidon2
kevjue Jun 18, 2024
70d815d
multi working
kevjue Jun 18, 2024
03bbc96
merged dev
kevjue Jun 18, 2024
7375e76
removed skinny poseidon2
kevjue Jun 18, 2024
95a1c99
degree 17 support
kevjue Jun 18, 2024
d136a52
cleanup
kevjue Jun 18, 2024
0e610a4
address ci
kevjue Jun 19, 2024
5415e67
smaller size for multi
kevjue Jun 19, 2024
8f7eda4
lots of comments
kevjue Jun 19, 2024
8bee6b1
changed back the fixed sizes
kevjue Jun 19, 2024
f35e24c
more comments
kevjue Jun 19, 2024
781aac2
Merge branch 'dev' into kevjue/p2_hash
kevjue Jun 19, 2024
0503aed
fixed some unit tests
kevjue Jun 19, 2024
dcf4e0c
Merge branch 'dev' into kevjue/p2_hash
kevjue Jun 19, 2024
3a170b8
clean up of runtime
kevjue Jun 19, 2024
f855f21
fixed unit tests
kevjue Jun 19, 2024
70a04a9
some cleanup and comments in trace gen
kevjue Jun 19, 2024
8c7d770
Merge branch 'dev' into kevjue/p2_hash
kevjue Jun 19, 2024
4dbd2c6
fixed unit tests
kevjue Jun 20, 2024
b64d1a8
addressed some comments, added documentation, and pushed 'derivative'…
kevjue Jun 20, 2024
29e61e7
range check num_remaining_rows
kevjue Jun 20, 2024
48fdf29
updated p3 dependency
kevjue Jun 20, 2024
ec76c9f
updated p3 dependency
kevjue Jun 20, 2024
5434d78
addressed PR comments
kevjue Jun 21, 2024
f7a4ee5
fixed comment
kevjue Jun 21, 2024
9464fd7
fixed markdown in comment
kevjue Jun 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions core/src/stark/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,16 +340,18 @@ impl<SC: StarkGenericConfig, A: MachineAir<Val<SC>>> StarkMachine<SC, A> {
})?;

// Verify the cumulative sum is 0.
tracing::debug_span!("verify cumulative sum is 0").in_scope(|| {
let mut sum = SC::Challenge::zero();
for proof in proof.shard_proofs.iter() {
sum += proof.cumulative_sum();
}
match sum.is_zero() {
true => Ok(()),
false => Err(MachineVerificationError::NonZeroCumulativeSum),
}
})
// tracing::debug_span!("verify cumulative sum is 0").in_scope(|| {
// let mut sum = SC::Challenge::zero();
// for proof in proof.shard_proofs.iter() {
// sum += proof.cumulative_sum();
// }
// match sum.is_zero() {
// true => Ok(()),
// false => Err(MachineVerificationError::NonZeroCumulativeSum),
// }
// })

Ok(())
}

#[instrument("debug constraints", level = "debug", skip_all)]
Expand Down
15 changes: 9 additions & 6 deletions prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,8 @@ mod tests {
use sp1_core::io::SP1Stdin;
use sp1_core::utils::setup_logger;

use sp1_recursion_core::poseidon2_wide::columns::NUM_POSEIDON2_COLS;

/// Tests an end-to-end workflow of proving a program across the entire proof generation
/// pipeline.
///
Expand All @@ -715,6 +717,7 @@ mod tests {
#[serial]
fn test_e2e() -> Result<()> {
setup_logger();
println!("column count for p2-wide is {:?}", NUM_POSEIDON2_COLS);
let elf = include_bytes!("../../tests/fibonacci/elf/riscv32im-succinct-zkvm-elf");

tracing::info!("initializing prover");
Expand Down Expand Up @@ -769,13 +772,13 @@ mod tests {
let vk_digest_bn254 = wrapped_bn254_proof.sp1_vkey_digest_bn254();
assert_eq!(vk_digest_bn254, vk.hash_bn254());

tracing::info!("generate plonk bn254 proof");
let artifacts_dir =
try_build_plonk_bn254_artifacts_dev(&prover.wrap_vk, &wrapped_bn254_proof.proof);
let plonk_bn254_proof = prover.wrap_plonk_bn254(wrapped_bn254_proof, &artifacts_dir);
println!("{:?}", plonk_bn254_proof);
// tracing::info!("generate plonk bn254 proof");
// let artifacts_dir =
// try_build_plonk_bn254_artifacts_dev(&prover.wrap_vk, &wrapped_bn254_proof.proof);
// let plonk_bn254_proof = prover.wrap_plonk_bn254(wrapped_bn254_proof, &artifacts_dir);
// println!("{:?}", plonk_bn254_proof);

prover.verify_plonk_bn254(&plonk_bn254_proof, &vk, &public_values, &artifacts_dir)?;
// prover.verify_plonk_bn254(&plonk_bn254_proof, &vk, &public_values, &artifacts_dir)?;

Ok(())
}
Expand Down
28 changes: 28 additions & 0 deletions recursion/compiler/src/asm/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,12 +511,40 @@ impl<F: PrimeField32 + TwoAdicField, EF: ExtensionField<F> + TwoAdicField> AsmCo
result.fp(),
left.fp(),
right.fp(),
F::zero(),
),
trace,
),
_ => unimplemented!(),
}
}
DslIr::Poseidon2AbsorbBabyBear(p2_hash_num, input) => match input {
Array::Dyn(input, input_size) => {
if let Usize::Var(input_size) = input_size {
self.push(
AsmInstruction::Poseidon2Absorb(
p2_hash_num.fp(),
input.fp(),
input_size.fp(),
),
trace,
);
} else {
unimplemented!();
}
}
_ => unimplemented!(),
},

DslIr::Poseidon2FinalizeBabyBear(p2_hash_num, output) => match output {
Array::Dyn(output, _) => {
self.push(
AsmInstruction::Poseidon2Finalize(p2_hash_num.fp(), output.fp()),
trace,
);
}
_ => unimplemented!(),
},

DslIr::Commit(val, index) => {
self.push(AsmInstruction::Commit(val.fp(), index.fp()), trace);
Expand Down
60 changes: 51 additions & 9 deletions recursion/compiler/src/asm/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,15 @@ pub enum AsmInstruction<F, EF> {

/// Perform a permutation of the Poseidon2 hash function on the array specified by the ptr.
Poseidon2Permute(i32, i32),
Poseidon2Compress(i32, i32, i32),

/// Perform a Poseidon2 compress.
Poseidon2Compress(i32, i32, i32, F),

/// Performs a Posedion2 absorb.
Poseidon2Absorb(i32, i32, i32),

/// Perform a Poseidon2 finalize.
Poseidon2Finalize(i32, i32),

/// Print a variable.
PrintV(i32),
Expand Down Expand Up @@ -731,7 +739,7 @@ impl<F: PrimeField32, EF: ExtensionField<F>> AsmInstruction<F, EF> {
"".to_string(),
),
AsmInstruction::Poseidon2Permute(dst, src) => Instruction::new(
Opcode::Poseidon2Compress,
Opcode::Poseidon2,
i32_f(dst),
i32_f_arr(src),
i32_f_arr(src),
Expand Down Expand Up @@ -829,17 +837,40 @@ impl<F: PrimeField32, EF: ExtensionField<F>> AsmInstruction<F, EF> {
true,
"".to_string(),
),
AsmInstruction::Poseidon2Compress(result, src1, src2) => Instruction::new(
Opcode::Poseidon2Compress,
AsmInstruction::Poseidon2Compress(result, op_1, op_2, operation) => Instruction::new(
Opcode::Poseidon2,
i32_f(result),
i32_f_arr(src1),
i32_f_arr(src2),
i32_f_arr(op_1),
i32_f_arr(op_2),
F::zero(),
operation,
false,
false,
"".to_string(),
),
AsmInstruction::Poseidon2Absorb(hash_num, input_ptr, input_len) => Instruction::new(
Opcode::Poseidon2Absorb,
i32_f(hash_num),
i32_f_arr(input_ptr),
i32_f_arr(hash_len),
F::zero(),
F::zero(),
false,
false,
"".to_string(),
),
AsmInstruction::Poseidon2Finalize(hash_num, output_ptr) => Instruction::new(
Opcode::Poseidon2Finalize,
i32_f(hash_num),
i32_f_arr(output_ptr),
i32_f_arr(F::zero()),
F::zero(),
operation,
false,
false,
"".to_string(),
),

AsmInstruction::Commit(val, index) => Instruction::new(
Opcode::Commit,
i32_f(val),
Expand Down Expand Up @@ -1120,13 +1151,24 @@ impl<F: PrimeField32, EF: ExtensionField<F>> AsmInstruction<F, EF> {
AsmInstruction::FriFold(m, input_ptr) => {
write!(f, "fri_fold ({})fp, ({})fp", m, input_ptr)
}
AsmInstruction::Poseidon2Compress(result, src1, src2) => {
AsmInstruction::Poseidon2Compress(result, op_1, op_2, operation) => {
write!(
f,
"poseidon2_compress ({})fp, {})fp, ({})fp, {}",
result, op_1, op_2, operation,
)
}
AsmInstruction::Poseidon2Absorb(hash_num, input_ptr, input_len) => {
write!(
f,
"poseidon2_compress ({})fp, {})fp, {})fp",
result, src1, src2
"poseidon2_absorb ({})fp, {})fp, ({})fp",
hash_num, input_ptr, input_len,
)
}
AsmInstruction::Poseidon2Finalize(hash_num, output_ptr) => {
write!(f, "poseidon2_finalize ({})fp, {})fp", hash_num, output_ptr,)
}

AsmInstruction::Commit(val, index) => {
write!(f, "commit ({})fp ({})fp", val, index)
}
Expand Down
19 changes: 19 additions & 0 deletions recursion/compiler/src/ir/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub struct Builder<C: Config> {
pub(crate) witness_var_count: u32,
pub(crate) witness_felt_count: u32,
pub(crate) witness_ext_count: u32,
pub(crate) p2_hash_num: Option<Var<C::N>>,
pub(crate) debug: bool,
pub(crate) is_sub_builder: bool,
}
Expand All @@ -111,6 +112,7 @@ impl<C: Config> Builder<C> {
felt_count: u32,
ext_count: u32,
nb_public_values: Option<Var<C::N>>,
p2_hash_num: Option<Var<C::N>>,
debug: bool,
) -> Self {
Self {
Expand All @@ -124,6 +126,7 @@ impl<C: Config> Builder<C> {
witness_ext_count: 0,
operations: Default::default(),
nb_public_values,
p2_hash_num,
debug,
is_sub_builder: true,
}
Expand Down Expand Up @@ -151,6 +154,18 @@ impl<C: Config> Builder<C> {
dst
}

/// Calcluates the remainder of num / den.
pub fn rem(&mut self, num: Felt<C::F>, den: Felt<C::F>) -> Felt<C::F> {
kevjue marked this conversation as resolved.
Show resolved Hide resolved
self.print_f(num);
self.print_f(den);
let quotient: Felt<_> = self.eval(num / den);
self.print_f(quotient);
let product: Felt<_> = self.eval(quotient * den);
self.print_f(product);

self.eval(num - product)
}

/// Evaluates a constant expression and returns a variable.
pub fn constant<V: FromConstant<C>>(&mut self, value: V::Constant) -> V {
V::constant(value, self)
Expand Down Expand Up @@ -517,6 +532,7 @@ impl<'a, C: Config> IfBuilder<'a, C> {
self.builder.felt_count,
self.builder.ext_count,
self.builder.nb_public_values,
self.builder.p2_hash_num,
self.builder.debug,
);
f(&mut f_builder);
Expand Down Expand Up @@ -565,6 +581,7 @@ impl<'a, C: Config> IfBuilder<'a, C> {
self.builder.felt_count,
self.builder.ext_count,
self.builder.nb_public_values,
self.builder.p2_hash_num,
self.builder.debug,
);

Expand All @@ -577,6 +594,7 @@ impl<'a, C: Config> IfBuilder<'a, C> {
self.builder.felt_count,
self.builder.ext_count,
self.builder.nb_public_values,
self.builder.p2_hash_num,
self.builder.debug,
);
else_f(&mut else_builder);
Expand Down Expand Up @@ -711,6 +729,7 @@ impl<'a, C: Config> RangeBuilder<'a, C> {
self.builder.felt_count,
self.builder.ext_count,
self.builder.nb_public_values,
self.builder.p2_hash_num,
self.builder.debug,
);

Expand Down
2 changes: 2 additions & 0 deletions recursion/compiler/src/ir/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ pub enum DslIr<C: Config> {
Array<C, Felt<C::F>>,
Array<C, Felt<C::F>>,
),
Poseidon2AbsorbBabyBear(Var<C::N>, Array<C, Felt<C::F>>),
Poseidon2FinalizeBabyBear(Var<C::N>, Array<C, Felt<C::F>>),
/// Permutes an array of Bn254 elements using Poseidon2 (output = p2_permute(array)). Should only
/// be used when target is a gnark circuit.
CircuitPoseidon2Permute([Var<C::N>; 3]),
Expand Down
63 changes: 60 additions & 3 deletions recursion/compiler/src/ir/poseidon.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
use crate::ir::MemIndex;
use crate::ir::MemVariable;
use crate::ir::Ptr;
use crate::ir::Variable;

use p3_field::AbstractField;
use sp1_recursion_core::runtime::{DIGEST_SIZE, HASH_RATE, PERMUTATION_WIDTH};
use sp1_recursion_derive::DslVariable;

use super::{Array, Builder, Config, DslIr, Ext, Felt, Usize, Var};

#[derive(DslVariable, Debug, Clone)]
pub struct Poseidon2State<C: Config> {
pub state: Array<C, Felt<C::F>>,
pub state_idx: Var<C::N>,
}

impl<C: Config> Builder<C> {
/// Applies the Poseidon2 permutation to the given array.
///
Expand Down Expand Up @@ -32,6 +44,24 @@ impl<C: Config> Builder<C> {
));
}

pub fn poseidon2_absorb(&mut self, p2_hash_num: &Var<C::N>, input: &Array<C, Felt<C::F>>) {
self.operations.push(DslIr::Poseidon2AbsorbBabyBear(
p2_hash_num.clone(),
input.clone(),
));
}

pub fn poseidon2_finalize_mut(
&mut self,
p2_hash_num: &Var<C::N>,
output: &Array<C, Felt<C::F>>,
) {
self.operations.push(DslIr::Poseidon2FinalizeBabyBear(
p2_hash_num,
output.clone(),
));
}

/// Applies the Poseidon2 compression function to the given array.
///
/// Reference: [p3_symmetric::TruncatedPermutation]
Expand Down Expand Up @@ -99,11 +129,11 @@ impl<C: Config> Builder<C> {
state
}

pub fn poseidon2_hash_x(
pub fn poseidon2_hash_x_orig(
&mut self,
array: &Array<C, Array<C, Felt<C::F>>>,
) -> Array<C, Felt<C::F>> {
self.cycle_tracker("poseidon2-hash");
self.cycle_tracker("poseidon2-hash-orig");
let mut state: Array<C, Felt<C::F>> = self.dyn_array(PERMUTATION_WIDTH);

let idx: Var<_> = self.eval(C::N::zero());
Expand All @@ -129,10 +159,37 @@ impl<C: Config> Builder<C> {
});

state.truncate(self, Usize::Const(DIGEST_SIZE));
self.cycle_tracker("poseidon2-hash");
self.cycle_tracker("poseidon2-hash-orig");
state
}

pub fn poseidon2_hash_x(
&mut self,
array: &Array<C, Array<C, Felt<C::F>>>,
) -> Array<C, Felt<C::F>> {
self.cycle_tracker("poseidon2-hash");

if self.p2_hash_num.is_none() {
self.p2_hash_num = Some(self.eval(C::N::zero()));
}

let p2_hash_num = self.p2_hash_num.unwrap();

self.range(0, array.len()).for_each(|i, builder| {
let subarray = builder.get(array, i);
builder.poseidon2_absorb(&p2_hash_num, &subarray);
});

let output: Array<C, Felt<C::F>> = self.dyn_array(DIGEST_SIZE);
self.poseidon2_finalize_mut(&p2_hash_num, &output);

let p2_hash_num = *self.p2_hash_num.as_ref().unwrap();
self.assign(p2_hash_num, p2_hash_num + C::N::one());

self.cycle_tracker("poseidon2-hash");
output
}

pub fn poseidon2_hash_ext(
&mut self,
array: &Array<C, Array<C, Ext<C::F, C::EF>>>,
Expand Down
Loading