Skip to content

Commit

Permalink
feat: graffiti features (#212)
Browse files Browse the repository at this point in the history
  • Loading branch information
jtguibas authored Oct 12, 2023
1 parent d27860b commit b4530d5
Show file tree
Hide file tree
Showing 14 changed files with 543 additions and 41 deletions.
21 changes: 0 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 1 addition & 6 deletions plonky2x/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ num = { version = "0.4", default-features = false }
sha2 = "0.10.7"
curve25519-dalek = { git = "https://github.com/succinctlabs/curve25519-dalek.git", branch = "feature/edwards-point-getters" }
ff = { package = "ff", version = "0.13", features = ["derive"] }

ethers = { version = "2.0" }

hex = "0.4.3"
log = { version = "0.4.14", default-features = false }
rand = { version = "0.8.4", package = "rand" }
Expand All @@ -47,14 +45,11 @@ serde_with = "3.3.0"
bincode = "1.3.3"
uuid = { version = "1.4.1", features = ["serde"] }
serde_plain = "1.0.2"
jemallocator = "0.5.0"
ed25519-consensus = "2.1.0"
async-trait = "0.1.73"
digest = "0.10.7"
sha256 = "1.4.0"

[dev-dependencies]
plonky2 = { git = "https://github.com/mir-protocol/plonky2.git", features = [
"gate_testing",
] }
plonky2 = { git = "https://github.com/mir-protocol/plonky2.git", features = ["gate_testing"] }
env_logger = "0.10.0"
21 changes: 15 additions & 6 deletions plonky2x/core/src/backend/circuit/serialization/hints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,16 @@ use crate::frontend::curta::hash::sha::sha256::hint::Sha256ProofHint;
use crate::frontend::ecc::ed25519::field::ed25519_base::Ed25519Base;
use crate::frontend::eth::beacon::generators::{
BeaconAllWithdrawalsHint, BeaconBalanceBatchWitnessHint, BeaconBalanceGenerator,
BeaconBalanceWitnessHint, BeaconBalancesGenerator, BeaconExecutionPayloadHint,
BeaconHeaderHint, BeaconHistoricalBlockGenerator, BeaconPartialBalancesHint,
BeaconBalanceWitnessHint, BeaconBalancesGenerator, BeaconBlockRootsHint,
BeaconExecutionPayloadHint, BeaconGraffitiHint, BeaconHeaderHint,
BeaconHeadersFromOffsetRangeHint, BeaconHistoricalBlockGenerator, BeaconPartialBalancesHint,
BeaconPartialValidatorsHint, BeaconValidatorBatchHint, BeaconValidatorGenerator,
BeaconValidatorsGenerator, BeaconValidatorsHint, BeaconWithdrawalGenerator,
BeaconWithdrawalsGenerator, CompressedBeaconValidatorBatchHint, Eth1BlockToSlotHint,
};
use crate::frontend::eth::beacon::vars::{
BeaconBalancesVariable, BeaconValidatorVariable, BeaconValidatorsVariable,
BeaconWithdrawalVariable, BeaconWithdrawalsVariable,
BeaconBalancesVariable, BeaconHeaderVariable, BeaconValidatorVariable,
BeaconValidatorsVariable, BeaconWithdrawalVariable, BeaconWithdrawalsVariable,
};
use crate::frontend::eth::mpt::generators::LteGenerator;
use crate::frontend::eth::storage::generators::{
Expand All @@ -84,7 +85,7 @@ use crate::frontend::num::u32::gates::range_check_u32::U32RangeCheckGenerator;
use crate::frontend::num::u32::gates::subtraction_u32::U32SubtractionGenerator;
use crate::frontend::uint::uint64::U64Variable;
use crate::frontend::vars::{Bytes32Variable, SubArrayExtractorHint, U256Variable};
use crate::prelude::{BoolVariable, U32Variable, Variable};
use crate::prelude::{ArrayVariable, BoolVariable, U32Variable, Variable};

pub trait HintSerializer<L: PlonkParameters<D>, const D: usize>:
WitnessGeneratorSerializer<L::Field, D>
Expand Down Expand Up @@ -463,6 +464,12 @@ where

r.register_hint::<SubArrayExtractorHint>();

r.register_hint::<BeaconBlockRootsHint>();

r.register_hint::<BeaconGraffitiHint>();

register_powers_of_two!(r, BeaconHeadersFromOffsetRangeHint);

register_watch_generator!(
r,
L,
Expand All @@ -477,7 +484,9 @@ where
BeaconBalancesVariable,
BeaconWithdrawalsVariable,
BeaconWithdrawalVariable,
BeaconValidatorVariable
BeaconValidatorVariable,
BeaconHeaderVariable,
ArrayVariable<Bytes32Variable, 8192>
);

r
Expand Down
1 change: 1 addition & 0 deletions plonky2x/core/src/frontend/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod boolean;
pub mod io;
pub mod permutation;
mod proof;
pub mod watch;

Expand Down
149 changes: 149 additions & 0 deletions plonky2x/core/src/frontend/builder/permutation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
use serde::{Deserialize, Serialize};

use super::CircuitBuilder;
use crate::frontend::hint::simple::hint::Hint;
use crate::frontend::uint::uint32::U32Variable;
use crate::frontend::vars::{EvmVariable, ValueStream, VariableStream};
use crate::prelude::{ArrayVariable, PlonkParameters, Variable};
use crate::utils::hash::sha256;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct RandomPermutationHint<const B: usize>;

impl<L: PlonkParameters<D>, const D: usize, const B: usize> Hint<L, D>
for RandomPermutationHint<B>
{
fn hint(&self, input_stream: &mut ValueStream<L, D>, output_stream: &mut ValueStream<L, D>) {
let inputs = input_stream.read_value::<ArrayVariable<U32Variable, B>>();
let dummy = input_stream.read_value::<U32Variable>();
let nonce = input_stream.read_value::<U32Variable>();

let mut filtered_inputs = Vec::new();
for i in 0..inputs.len() {
if inputs[i] != dummy {
filtered_inputs.push(inputs[i]);
}
}

filtered_inputs.sort_by_key(|x| {
let mut bytes = Vec::new();
bytes.extend(x.to_be_bytes());
bytes.extend(nonce.to_be_bytes());
u32::from_be_bytes(sha256(&bytes)[0..4].try_into().unwrap())
});
filtered_inputs.resize(B, dummy);

output_stream.write_value::<ArrayVariable<U32Variable, B>>(filtered_inputs);
}
}

impl<L: PlonkParameters<D>, const D: usize> CircuitBuilder<L, D> {
pub fn permute_with_dummy<const B: usize>(
&mut self,
inputs: ArrayVariable<U32Variable, B>,
dummy: U32Variable,
gamma: Variable,
nonce: U32Variable,
) -> ArrayVariable<U32Variable, B>
where
<<L as PlonkParameters<D>>::Config as GenericConfig<D>>::Hasher:
AlgebraicHasher<<L as PlonkParameters<D>>::Field>,
{
// Compute the filtered accumulator.
let mut filtered_acc = self.one::<Variable>();
for i in 0..inputs.len() {
let is_dummy = self.is_equal(inputs[i], dummy);
let term = self.sub(gamma, inputs[i].0);
let acc = self.mul(filtered_acc, term);
filtered_acc = self.select(is_dummy, filtered_acc, acc);
}

// Get the permuted inputs.
let mut input_stream = VariableStream::new();
input_stream.write(&inputs);
input_stream.write(&dummy);
input_stream.write(&nonce);
let output_stream = self.hint(input_stream, RandomPermutationHint::<B> {});
let permuted_inputs = output_stream.read::<ArrayVariable<U32Variable, B>>(self);

// Compute the permtued filtered accumulator.
let mut permuted_filtered_acc = self.one::<Variable>();
for i in 0..inputs.len() {
let is_dummy = self.is_equal(permuted_inputs[i], dummy);
let term = self.sub(gamma, permuted_inputs[i].0);
let acc = self.mul(permuted_filtered_acc, term);
permuted_filtered_acc = self.select(is_dummy, permuted_filtered_acc, acc);
}

// Assert that the permuted filtered accumulator is the same as the filtered accumulator.
self.assert_is_equal(permuted_filtered_acc, filtered_acc);

// Check the metric ordering.
let mut metrics = Vec::new();
for i in 0..permuted_inputs.len() {
let mut bytes = Vec::new();
bytes.extend(permuted_inputs[i].encode(self));
bytes.extend(nonce.encode(self));
let h = self.curta_sha256(&bytes);
let metric = U32Variable::decode(self, &h.0[0..4]);
metrics.push(metric);
}

let t = self._true();
let f = self._false();
let mut seen_dummy = self._false();
for i in 0..metrics.len() - 1 {
// If the next is dummy and we've seen one, panic.
let next_is_dummy = self.is_equal(permuted_inputs[i + 1], dummy);
let not_next_is_dummy = self.not(next_is_dummy);
let seen_dummy_and_not_next_is_dummy = self.and(seen_dummy, not_next_is_dummy);
self.assert_is_equal(seen_dummy_and_not_next_is_dummy, f);

// The next metric should be less than or equal to or the next is valid.
let lte = self.lte(metrics[i], metrics[i + 1]);
let valid = self.or(lte, next_is_dummy);
self.assert_is_equal(valid, t);

// If the next thing is a dummy, we've seen a dummy.
seen_dummy = self.select(next_is_dummy, t, seen_dummy);
}

permuted_inputs
}
}

#[cfg(test)]
pub(crate) mod tests {

use plonky2::field::types::Field;

use crate::frontend::uint::uint32::U32Variable;
use crate::prelude::*;
use crate::utils;

#[test]
fn test_simple_circuit_with_field_io() {
utils::setup_logger();
let mut builder = DefaultBuilder::new();

let inputs = builder.constant::<ArrayVariable<U32Variable, 5>>(vec![0, 1, 2, 3, 4]);
let dummy = builder.constant::<U32Variable>(0);
let gamma = builder.constant::<Variable>(GoldilocksField::from_canonical_u64(3));
let nonce = builder.constant::<U32Variable>(1);

let permuted_inputs = builder.permute_with_dummy(inputs, dummy, gamma, nonce);
for i in 0..permuted_inputs.len() {
builder.watch(
&permuted_inputs[i],
format!("permuted_inputs[{}]", i).as_str(),
);
}

let circuit = builder.build();

let input = circuit.input();
let (proof, output) = circuit.prove(&input);
circuit.verify(&proof, &input, &output);
}
}
Loading

0 comments on commit b4530d5

Please sign in to comment.