Skip to content

Commit

Permalink
feat: add Groth16 Verify component (#42)
Browse files Browse the repository at this point in the history
* feat: add Groth16 Verify component

* chore: update rust toolchain

* chore: fix lint

* chore: lint
  • Loading branch information
jonathanpwang authored Aug 14, 2024
1 parent 7dca326 commit 9cf007d
Show file tree
Hide file tree
Showing 48 changed files with 1,908 additions and 245 deletions.
2 changes: 1 addition & 1 deletion axiom-codec/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub const FIELD_IDX_BYTES: usize = 4;
pub const MAX_SOLIDITY_MAPPING_KEYS: usize = 4;
pub const MAX_SUBQUERY_INPUTS: usize = 13;
pub const MAX_SUBQUERY_OUTPUTS: usize = 2;
pub const NUM_SUBQUERY_TYPES: usize = 8;
pub const NUM_SUBQUERY_TYPES: usize = 9;
pub const SOURCE_CHAIN_ID_BYTES: usize = 8;
pub const SUBQUERY_TYPE_BYTES: usize = 2;
pub const USER_ADVICE_COLS: usize = 4;
Expand Down
21 changes: 18 additions & 3 deletions axiom-codec/src/decoder/native.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::io::{self, Read, Result};

use axiom_components::ecdsa::ECDSAComponentNativeInput;
use axiom_eth::halo2curves::bn256::G1Affine;
use axiom_components::{
ecdsa::ECDSAComponentNativeInput,
groth16::types::{Groth16NativeInput, Groth16VerifierComponentInput},
utils::flatten::InputFlatten,
};
use axiom_eth::halo2curves::bn256::{Fr, G1Affine};
use byteorder::{BigEndian, ReadBytesExt};
use ethers_core::types::Bytes;
use ethers_core::types::{Bytes, H256};

use crate::{
constants::MAX_SOLIDITY_MAPPING_KEYS,
Expand Down Expand Up @@ -31,6 +35,7 @@ impl TryFrom<Subquery> for AnySubquery {
decode_solidity_nested_mapping_subquery(&mut reader)?,
),
SubqueryType::ECDSA => AnySubquery::ECDSA(decode_ecdsa_subquery(&mut reader)?),
SubqueryType::Groth16 => AnySubquery::Groth16(decode_groth16_subquery(&mut reader)?),
})
}
}
Expand All @@ -47,6 +52,7 @@ impl TryFrom<u16> for SubqueryType {
5 => Ok(Self::Receipt),
6 => Ok(Self::SolidityNestedMapping),
7 => Ok(Self::ECDSA),
8 => Ok(Self::Groth16),
// 7 => Ok(Self::BeaconValidator),
_ => Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid SubqueryType")),
}
Expand Down Expand Up @@ -162,3 +168,12 @@ pub fn decode_ecdsa_subquery(mut reader: impl Read) -> Result<ECDSAComponentNati
let out = ECDSAComponentNativeInput { pubkey: (pubkey_x, pubkey_y), r, s, msg_hash };
Ok(out)
}

pub fn decode_groth16_subquery(mut reader: impl Read) -> Result<Groth16NativeInput> {
let mut bytes: Vec<H256> = vec![];
for _ in 0..Groth16VerifierComponentInput::<Fr>::NUM_FE {
let fe = read_h256(&mut reader)?;
bytes.push(fe);
}
Ok(Groth16NativeInput { bytes })
}
25 changes: 24 additions & 1 deletion axiom-codec/src/encoder/field_elements.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::io;

use axiom_components::{ecdsa::ECDSAComponentInput, utils::flatten::InputFlatten};
use axiom_components::{
ecdsa::ECDSAComponentInput, groth16::types::Groth16VerifierComponentInput,
utils::flatten::InputFlatten,
};
use axiom_eth::halo2curves::bn256::Fr;
use ethers_core::types::{Bytes, H256};

Expand Down Expand Up @@ -30,7 +33,14 @@ pub const NUM_FE_ANY: [usize; NUM_SUBQUERY_TYPES] = [
NUM_FE_RECEIPT,
NUM_FE_SOLIDITY_NESTED_MAPPING,
ECDSAComponentInput::<Fr>::NUM_FE,
Groth16VerifierComponentInput::<Fr>::NUM_FE,
];
/// The enabled types affects the subquery hash calculation
/// (the circuit iterates through the NUM_FE of each enabled type) and so to maintain
/// backwards compatibility, the default is to enable the original V2 mainnet launch
/// enabled types.
pub const DEFAULT_V2_ENABLED_TYPES: [bool; NUM_SUBQUERY_TYPES] =
[true, true, true, true, true, true, true, false, false];

/// The index of the mapping depth in [`FieldSolidityNestedMappingSubquery`].
pub const FIELD_SOLIDITY_NESTED_MAPPING_DEPTH_IDX: usize = 4;
Expand All @@ -57,6 +67,8 @@ pub const BITS_PER_FE_SOLIDITY_NESTED_MAPPING: [usize; NUM_FE_SOLIDITY_NESTED_MA
bits_per_fe_solidity_nested_mapping();
pub const BYTES_PER_FE_ECDSA: [usize; ECDSAComponentInput::<Fr>::NUM_FE] =
[16; ECDSAComponentInput::<Fr>::NUM_FE];
pub const BYTES_PER_FE_GROTH16: [usize; Groth16VerifierComponentInput::<Fr>::NUM_FE] =
[32; Groth16VerifierComponentInput::<Fr>::NUM_FE];
pub const BYTES_PER_FE_ANY: [&[usize]; NUM_SUBQUERY_TYPES] = [
&[],
&BYTES_PER_FE_HEADER,
Expand All @@ -66,6 +78,7 @@ pub const BYTES_PER_FE_ANY: [&[usize]; NUM_SUBQUERY_TYPES] = [
&BYTES_PER_FE_RECEIPT,
&BYTES_PER_FE_SOLIDITY_NESTED_MAPPING,
&BYTES_PER_FE_ECDSA,
&BYTES_PER_FE_GROTH16,
];
pub const BYTES_PER_FE_SUBQUERY_OUTPUT: usize = 16;

Expand Down Expand Up @@ -160,6 +173,7 @@ impl<F: Field> From<AnySubquery> for FieldSubquery<F> {
FieldSolidityNestedMappingSubquery::from(subquery).into()
}
AnySubquery::ECDSA(subquery) => ECDSAComponentInput::from(subquery).into(),
AnySubquery::Groth16(subquery) => Groth16VerifierComponentInput::from(subquery).into(),
}
}
}
Expand Down Expand Up @@ -345,3 +359,12 @@ impl<F: Field> From<ECDSAComponentInput<F>> for FieldSubquery<F> {
Self { subquery_type: SubqueryType::ECDSA, encoded_subquery_data }
}
}

impl<F: Field> From<Groth16VerifierComponentInput<F>> for FieldSubquery<F> {
fn from(value: Groth16VerifierComponentInput<F>) -> Self {
let mut encoded_subquery_data = [F::ZERO; MAX_SUBQUERY_INPUTS];
encoded_subquery_data[..Groth16VerifierComponentInput::<F>::NUM_FE]
.copy_from_slice(&value.flatten());
Self { subquery_type: SubqueryType::Groth16, encoded_subquery_data }
}
}
27 changes: 26 additions & 1 deletion axiom-codec/src/encoder/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
iter,
};

use axiom_components::ecdsa::ECDSAComponentNativeInput;
use axiom_components::{ecdsa::ECDSAComponentNativeInput, groth16::types::Groth16NativeInput};
use byteorder::{BigEndian, WriteBytesExt};
use ethers_core::{types::H256, utils::keccak256};

Expand Down Expand Up @@ -219,6 +219,16 @@ pub fn encode_ecdsa_component_native_input(
Ok(())
}

pub fn encode_groth16_native_input(
writer: &mut impl Write,
input: Groth16NativeInput,
) -> Result<()> {
for fe in input.bytes {
writer.write_all(&fe[..])?;
}
Ok(())
}

impl From<HeaderSubquery> for Subquery {
fn from(value: HeaderSubquery) -> Self {
let mut bytes = vec![];
Expand Down Expand Up @@ -278,6 +288,14 @@ impl From<ECDSAComponentNativeInput> for Subquery {
}
}

impl From<Groth16NativeInput> for Subquery {
fn from(value: Groth16NativeInput) -> Self {
let mut bytes = vec![];
encode_groth16_native_input(&mut bytes, value).unwrap();
Self { subquery_type: SubqueryType::Groth16, encoded_subquery_data: bytes.into() }
}
}

impl From<AnySubquery> for Subquery {
fn from(value: AnySubquery) -> Self {
match value {
Expand All @@ -291,6 +309,7 @@ impl From<AnySubquery> for Subquery {
AnySubquery::Receipt(subquery) => subquery.into(),
AnySubquery::SolidityNestedMapping(subquery) => subquery.into(),
AnySubquery::ECDSA(subquery) => subquery.into(),
AnySubquery::Groth16(subquery) => subquery.into(),
}
}
}
Expand Down Expand Up @@ -331,3 +350,9 @@ impl From<ECDSAComponentNativeInput> for AnySubquery {
AnySubquery::ECDSA(value)
}
}

impl From<Groth16NativeInput> for AnySubquery {
fn from(value: Groth16NativeInput) -> Self {
AnySubquery::Groth16(value)
}
}
1 change: 0 additions & 1 deletion axiom-codec/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![feature(trait_alias)]
#![feature(io_error_other)]

pub use axiom_eth::utils::hilo::HiLo;
pub use axiom_eth::Field;
Expand Down
3 changes: 2 additions & 1 deletion axiom-codec/src/types/field_elements.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fmt::Debug, ops::Deref};

use axiom_components::ecdsa::ECDSAComponentInput;
use axiom_components::{ecdsa::ECDSAComponentInput, groth16::types::Groth16VerifierComponentInput};
use serde::{Deserialize, Serialize};

use crate::{
Expand Down Expand Up @@ -173,3 +173,4 @@ pub type FieldReceiptSubqueryResult<T> = AnySubqueryResult<FieldReceiptSubquery<
pub type FieldSolidityNestedMappingSubqueryResult<T> =
AnySubqueryResult<FieldSolidityNestedMappingSubquery<T>, HiLo<T>>;
pub type FieldECDSASubqueryResult<T> = AnySubqueryResult<ECDSAComponentInput<T>, T>;
pub type FieldGroth16SubqueryResult<T> = AnySubqueryResult<Groth16VerifierComponentInput<T>, T>;
4 changes: 3 additions & 1 deletion axiom-codec/src/types/native.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use axiom_components::ecdsa::ECDSAComponentNativeInput;
use axiom_components::{ecdsa::ECDSAComponentNativeInput, groth16::types::Groth16NativeInput};
use axiom_eth::halo2curves::bn256::G1Affine;
use ethers_core::types::{Address, Bytes, H256, U256};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -78,6 +78,7 @@ pub enum SubqueryType {
Receipt = 5,
SolidityNestedMapping = 6,
ECDSA = 7,
Groth16 = 8,
}

#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
Expand All @@ -90,6 +91,7 @@ pub enum AnySubquery {
Receipt(ReceiptSubquery),
SolidityNestedMapping(SolidityNestedMappingSubquery),
ECDSA(ECDSAComponentNativeInput),
Groth16(Groth16NativeInput),
}

#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
Expand Down
Loading

0 comments on commit 9cf007d

Please sign in to comment.