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

Feature: transparency updates #2

Merged
merged 3 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 21 additions & 2 deletions src/codegen/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::codegen::{
};
use askama::{Error, Template};
use ruint::aliases::U256;
use std::fmt;
use std::fmt::{self, Display};


#[derive(Template)]
#[template(path = "Halo2VerifyingKey.sol")]
Expand Down Expand Up @@ -61,7 +62,7 @@ impl Halo2Verifier {
}

mod filters {
use std::fmt::LowerHex;
use std::fmt::{LowerHex, Display};

pub fn hex(value: impl LowerHex) -> ::askama::Result<String> {
let value = format!("{value:x}");
Expand All @@ -80,4 +81,22 @@ mod filters {
Ok(string)
}
}

pub fn left_pad(value: impl Display, width: usize) -> ::askama::Result<String> {
let string = format!("{:>width$}", value, width = width);
Ok(string)
}
}

pub fn index_coord(value: impl Display, index: &usize, coord: impl Display) -> String {
format!(
"{}_{}_{}",
value.to_string().to_uppercase(),
index,
coord.to_string().to_uppercase()
)
}

pub fn vk_var_name(value: impl Display) -> String {
format!("VK_{}_VAL", value.to_string().to_uppercase())
}
32 changes: 32 additions & 0 deletions src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ pub const FN_SIG_VERIFY_PROOF: [u8; 4] = [0x1e, 0x8e, 0x1e, 0x13];
/// Function signature of `verifyProof(address,bytes,uint256[])`.
pub const FN_SIG_VERIFY_PROOF_WITH_VK_ADDRESS: [u8; 4] = [0xaf, 0x83, 0xa1, 0x8d];

/// Function signature of `getVerifyingKey()`.
pub const FN_SIG_GET_VERIFYING_KEY: [u8; 4] = [0xaf, 0x7f, 0x43, 0x64];

/// Function signature of `getVerifyingKey(address)`.
pub const FN_SIG_GET_VERIFYING_KEY_WITH_VK_ADDRESS: [u8; 4] = [0x5f, 0xc4, 0x90, 0x4d];

/// Encode proof into calldata to invoke `Halo2Verifier.verifyProof`.
///
/// For `vk_address`:
Expand Down Expand Up @@ -46,6 +52,32 @@ pub fn encode_calldata(
.collect()
}

/// Encode calldata to invoke `Halo2Verifier.getVerifyingKey`.
///
/// For `vk_address`:
/// - Pass `None` if verifying key is embedded in `Halo2Verifier`
/// - Pass `Some(vk_address)` if verifying key is separated and deployed at `vk_address`
pub fn get_vkey_calldata(vk_address: Option<[u8; 20]>) -> Vec<u8> {
let fn_sig = if vk_address.is_some() {
FN_SIG_GET_VERIFYING_KEY_WITH_VK_ADDRESS
} else {
FN_SIG_GET_VERIFYING_KEY
};
let vk_address = if let Some(vk_address) = vk_address {
U256::try_from_be_slice(&vk_address)
.unwrap()
.to_be_bytes::<0x20>()
.to_vec()
} else {
Vec::new()
};
chain![
fn_sig, // function signature
vk_address, // verifying key address
]
.collect()
}

#[cfg(any(test, feature = "evm"))]
pub(crate) mod test {
pub use revm;
Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ mod transcript;
mod test;

pub use codegen::{AccumulatorEncoding, BatchOpenScheme, SolidityGenerator};
pub use evm::{encode_calldata, FN_SIG_VERIFY_PROOF, FN_SIG_VERIFY_PROOF_WITH_VK_ADDRESS};
pub use evm::{
encode_calldata, get_vkey_calldata, FN_SIG_GET_VERIFYING_KEY,
FN_SIG_GET_VERIFYING_KEY_WITH_VK_ADDRESS, FN_SIG_VERIFY_PROOF,
FN_SIG_VERIFY_PROOF_WITH_VK_ADDRESS,
};
pub use transcript::Keccak256Transcript;

#[cfg(feature = "evm")]
Expand Down
51 changes: 46 additions & 5 deletions templates/Halo2Verifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,47 @@ contract Halo2Verifier {
uint256 internal constant PAIRING_RHS_X_MPTR = {{ theta_mptr + 24 }};
uint256 internal constant PAIRING_RHS_Y_MPTR = {{ theta_mptr + 25 }};

{%- if let Some(vk_) = vk %}

// verifying key parameters
{%- for (name, chunk) in vk_.constants %}
uint256 internal constant {{ self::vk_var_name(name)|left_pad(24) }} = {{ chunk|hex_padded(64) }};
sifnoc marked this conversation as resolved.
Show resolved Hide resolved
{%- endfor %}
{%- for (x, y) in vk_.fixed_comms %}
uint256 internal constant {{ self::index_coord("fixed_comms", loop.index0, "x")|left_pad(24) }} = {{ x|hex_padded(64) }};
uint256 internal constant {{ self::index_coord("fixed_comms", loop.index0, "y")|left_pad(24) }} = {{ y|hex_padded(64) }};
{%- endfor %}
{%- for (x, y) in vk_.permutation_comms %}
uint256 internal constant {{ self::index_coord("permutation_comms", loop.index0, "x")|left_pad(24) }} = {{ x|hex_padded(64) }};
uint256 internal constant {{ self::index_coord("permutation_comms", loop.index0, "y")|left_pad(24) }} = {{ y|hex_padded(64) }};
{%- endfor %}

function getVerifyingKey() public view returns (uint256[{{ vk_len / 32 }}] memory) {
return [
{%- for (name, chunk) in vk_.constants %}
{{ self::vk_var_name(name)|left_pad(24) }},
{%- endfor %}
{%- for (x, y) in vk_.fixed_comms %}
{{ self::index_coord("fixed_comms", loop.index0, "x")|left_pad(24) }},
{{ self::index_coord("fixed_comms", loop.index0, "y")|left_pad(24) }},
{%- endfor %}
{%- for (x, y) in vk_.permutation_comms %}
{{ self::index_coord("permutation_comms", loop.index0, "x")|left_pad(24) }},
{{ self::index_coord("permutation_comms", loop.index0, "y")|left_pad(24) }}{%- if loop.index < vk_.permutation_comms.len() %},{%- endif %}
{%- endfor %}
];
}

{%- else %}

function getVerifyingKey(address vk) public view returns (uint256[{{ vk_len / 32 }}] memory) {
assembly {
extcodecopy(vk, VK_MPTR, 0x00, {{ vk_len|hex() }})
return (VK_MPTR, {{ vk_len|hex() }})
}
}
{%- endif %}

function verifyProof(
{%- match vk %}
{%- when Some with (vk) %}
Expand Down Expand Up @@ -227,17 +268,17 @@ contract Halo2Verifier {
{%- when Some with (vk) %}
// Load vk into memory
{%- for (name, chunk) in vk.constants %}
mstore({{ vk_mptr + loop.index0 }}, {{ chunk|hex_padded(64) }}) // {{ name }}
mstore({{ vk_mptr + loop.index0 }}, {{ self::vk_var_name(name)|left_pad(24) }}) // {{ name }}
{%- endfor %}
{%- for (x, y) in vk.fixed_comms %}
{%- let offset = vk.constants.len() %}
mstore({{ vk_mptr + offset + 2 * loop.index0 }}, {{ x|hex_padded(64) }}) // fixed_comms[{{ loop.index0 }}].x
mstore({{ vk_mptr + offset + 2 * loop.index0 + 1 }}, {{ y|hex_padded(64) }}) // fixed_comms[{{ loop.index0 }}].y
mstore({{ vk_mptr + offset + 2 * loop.index0 }}, {{ self::index_coord("fixed_comms", loop.index0, "x")|left_pad(24) }}) // fixed_comms[{{ loop.index0 }}].x
mstore({{ vk_mptr + offset + 2 * loop.index0 + 1 }}, {{ self::index_coord("fixed_comms", loop.index0, "y")|left_pad(24) }}) // fixed_comms[{{ loop.index0 }}].y
{%- endfor %}
{%- for (x, y) in vk.permutation_comms %}
{%- let offset = vk.constants.len() + 2 * vk.fixed_comms.len() %}
mstore({{ vk_mptr + offset + 2 * loop.index0 }}, {{ x|hex_padded(64) }}) // permutation_comms[{{ loop.index0 }}].x
mstore({{ vk_mptr + offset + 2 * loop.index0 + 1 }}, {{ y|hex_padded(64) }}) // permutation_comms[{{ loop.index0 }}].y
mstore({{ vk_mptr + offset + 2 * loop.index0 }}, {{ self::index_coord("permutation_comms", loop.index0, "x")|left_pad(24) }}) // permutation_comms[{{ loop.index0 }}].x
mstore({{ vk_mptr + offset + 2 * loop.index0 + 1 }}, {{ self::index_coord("permutation_comms", loop.index0, "y")|left_pad(24) }}) // permutation_comms[{{ loop.index0 }}].y
{%- endfor %}
{%- when None %}
// Copy vk into memory
Expand Down