Skip to content

Commit

Permalink
feat: bytes32 <-> uint256, bytes32.bytes() (#106)
Browse files Browse the repository at this point in the history
* feat: assert_is_equal CircuitVariable

* chad -> self-hosted

* add shortcuts

* Revert "chad -> self-hosted"

This reverts commit 22ec10b.

* fmt
  • Loading branch information
ctian1 authored Aug 30, 2023
1 parent 5660785 commit 3e5f281
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 10 deletions.
3 changes: 3 additions & 0 deletions plonky2x/examples/circuit_function_evm.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]

//! An example of a basic circuit function which wraps an existing circuit and makes it compatible
//! with a standard for serializing and deserializing inputs and outputs.
//!
Expand Down
3 changes: 3 additions & 0 deletions plonky2x/examples/circuit_function_field.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]

//! An example of a basic circuit function which wraps an existing circuit and makes it compatible
//! with a standard for serializing and deserializing inputs and outputs.
//!
Expand Down
5 changes: 3 additions & 2 deletions plonky2x/src/backend/circuit/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
use plonky2::recursion::dummy_circuit::DummyProofGenerator;
use plonky2::util::serialization::{Buffer, IoResult, WitnessGeneratorSerializer};

use crate::frontend::eth::storage::generators::storage::EthStorageProofGenerator;
use crate::frontend::eth::storage::generators::block::EthBlockGenerator;
use crate::frontend::eth::storage::generators::storage::{
EthStorageKeyGenerator, EthStorageProofGenerator,
};
use crate::frontend::hash::keccak::keccak256::Keccack256Generator;
use crate::frontend::eth::storage::generators::storage::EthStorageKeyGenerator;

#[macro_export]
macro_rules! impl_generator_serializer {
Expand Down
7 changes: 5 additions & 2 deletions plonky2x/src/frontend/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}

/// Fails if i1 != i2.
pub fn assert_is_equal(&mut self, i1: Variable, i2: Variable) {
self.api.connect(i1.0, i2.0);
pub fn assert_is_equal<V: CircuitVariable>(&mut self, i1: V, i2: V) {
assert_eq!(i1.targets().len(), i2.targets().len());
for (t1, t2) in i1.targets().iter().zip(i2.targets().iter()) {
self.api.connect(*t1, *t2);
}
}
}

Expand Down
10 changes: 7 additions & 3 deletions plonky2x/src/frontend/eth/storage/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use plonky2::field::extension::Extendable;
use plonky2::hash::hash_types::RichField;

use super::generators::block::EthBlockGenerator;
use super::generators::storage::{EthStorageProofGenerator, EthStorageKeyGenerator};
use super::generators::storage::{EthStorageKeyGenerator, EthStorageProofGenerator};
use super::vars::{EthAccountVariable, EthHeaderVariable, EthLogVariable};
use crate::frontend::builder::CircuitBuilder;
use crate::frontend::eth::vars::AddressVariable;
Expand Down Expand Up @@ -144,11 +144,15 @@ mod tests {
// mapping_location
input.write::<U256Variable>(mapping_location);

let map_key = bytes32!("0x281dc31bb78779a1ede7bf0f4d2bc5f07ddebc9f9d1155e413d8804384604bbe");
let map_key =
bytes32!("0x281dc31bb78779a1ede7bf0f4d2bc5f07ddebc9f9d1155e413d8804384604bbe");
// map_key
input.write::<Bytes32Variable>(map_key);

println!("storage key: {:?}", get_map_storage_location(mapping_location.as_u128(), map_key));
println!(
"storage key: {:?}",
get_map_storage_location(mapping_location.as_u128(), map_key)
);

// Generate a proof.
let (proof, output) = circuit.prove(&input);
Expand Down
2 changes: 1 addition & 1 deletion plonky2x/src/frontend/eth/storage/generators/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D>
fn run_once(&self, witness: &PartitionWitness<F>, buffer: &mut GeneratedValues<F>) {
let mapping_location = self.mapping_location.get(witness);
let map_key = self.map_key.get(witness);

let location = get_map_storage_location(mapping_location.as_u128(), map_key);
self.value.set(buffer, location);
}
Expand Down
2 changes: 1 addition & 1 deletion plonky2x/src/frontend/hash/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod bit_operations;
pub mod blake2;
pub mod sha;
pub mod keccak;
pub mod sha;
2 changes: 2 additions & 0 deletions plonky2x/src/frontend/uint/uint32_n.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ where
) -> Vec<ByteVariable> {
self.limbs
.iter()
.rev()
.flat_map(|x| x.encode(builder))
.collect::<Vec<_>>()
}
Expand All @@ -114,6 +115,7 @@ where
for i in 0..N {
limbs[i] = U32Variable::decode(builder, &bytes[i * 4..(i + 1) * 4]);
}
limbs.reverse();
Self {
limbs,
_marker: core::marker::PhantomData,
Expand Down
54 changes: 53 additions & 1 deletion plonky2x/src/frontend/vars/bytes32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,27 @@ use plonky2::field::extension::Extendable;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::witness::{Witness, WitnessWrite};

use super::{ByteVariable, CircuitVariable, EvmVariable, Variable};
use super::{ByteVariable, CircuitVariable, EvmVariable, U256Variable, Variable};
use crate::frontend::builder::CircuitBuilder;
use crate::frontend::vars::BytesVariable;

/// A variable in the circuit representing a byte32 value.
#[derive(Debug, Clone, Copy)]
pub struct Bytes32Variable(pub BytesVariable<32>);

impl Bytes32Variable {
pub fn as_bytes(&self) -> [ByteVariable; 32] {
self.0 .0
}

pub fn as_u256<F: RichField + Extendable<D>, const D: usize>(
&self,
builder: &mut CircuitBuilder<F, D>,
) -> U256Variable {
U256Variable::decode(builder, &self.0 .0)
}
}

impl CircuitVariable for Bytes32Variable {
type ValueType<F: RichField> = H256;

Expand Down Expand Up @@ -73,3 +86,42 @@ impl EvmVariable for Bytes32Variable {
H256::from_slice(bytes)
}
}

#[cfg(test)]
mod test {
use ethers::types::U256;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::config::PoseidonGoldilocksConfig;

use super::Bytes32Variable;
use crate::frontend::uint::uint256::U256Variable;
use crate::prelude::{CircuitBuilderX, CircuitVariable};
use crate::utils::bytes32;

type C = PoseidonGoldilocksConfig;

#[test]
fn test_bytes32_as_u256() {
let mut builder = CircuitBuilderX::new();

let b32 = Bytes32Variable::constant(
&mut builder,
bytes32!("0xf0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b"),
);

let u256 = b32.as_u256(&mut builder);
let expected = U256Variable::constant(
&mut builder,
U256::from_dec_str(
"108959270400061671294053818573968651411470832267186275529291850190552309358907",
)
.unwrap(),
);
builder.assert_is_equal(u256, expected);

let circuit = builder.build::<C>();
let pw = PartialWitness::new();
let proof = circuit.data.prove(pw).unwrap();
circuit.data.verify(proof).unwrap();
}
}

0 comments on commit 3e5f281

Please sign in to comment.