Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

In-circuit blockhash calculation #129

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
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
5 changes: 2 additions & 3 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ members = [

[patch.crates-io]
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2023_04_20" }
ethers-core = {git = "https://github.com/ggkitsas/ethers-rs/", rev = "6059806c17fa1a1d7534044bcdbecfef869392e1"}
smtmfft marked this conversation as resolved.
Show resolved Hide resolved

# Definition of benchmarks profile to use.
[profile.bench]
Expand Down
18 changes: 18 additions & 0 deletions gadgets/src/less_than.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ impl<F: Field, const N_BYTES: usize> LtConfig<F, N_BYTES> {
pub fn is_lt(&self, meta: &mut VirtualCells<F>, rotation: Option<Rotation>) -> Expression<F> {
meta.query_advice(self.lt, rotation.unwrap_or_else(Rotation::cur))
}

fn annotations(&self) -> Vec<String> {
smtmfft marked this conversation as resolved.
Show resolved Hide resolved
[
vec![String::from("lt"), String::from("u8")],
(0..N_BYTES).map(|i| format!("diff byte #{}", i)).collect(),
]
.concat()
}
/// Annotates columns of an LtChip embedded within a circuit region.
pub fn annotate_columns_in_region(&self, region: &mut Region<F>) {
let annotations = self.annotations();
region.name_column(|| &annotations[0], self.lt);
region.name_column(|| &annotations[1], self.u8);
self.diff
.iter()
.zip(self.annotations().iter().skip(2))
.for_each(|(&col, ann)| region.name_column(|| ann, col))
}
}

/// Chip that compares lhs < rhs.
Expand Down
6 changes: 5 additions & 1 deletion mock/src/block.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Mock Block definition and builder related methods.

use crate::{MockTransaction, MOCK_BASEFEE, MOCK_CHAIN_ID, MOCK_DIFFICULTY, MOCK_GASLIMIT};
use eth_types::{Address, Block, Bytes, Hash, Transaction, Word, H64, U64};
use eth_types::{Address, Block, Bytes, Hash, Transaction, Word, H256, H64, U64};
use ethers_core::types::{Bloom, OtherFields};

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -31,6 +31,7 @@ pub struct MockBlock {
size: Word,
mix_hash: Hash,
nonce: H64,
withdrawals_root: H256,
// This field is handled here as we assume that all block txs have the same ChainId.
// Also, the field is stored in the block_table since we don't have a chain_config
// structure/table.
Expand Down Expand Up @@ -63,6 +64,7 @@ impl Default for MockBlock {
mix_hash: Hash::zero(),
nonce: H64::zero(),
chain_id: *MOCK_CHAIN_ID,
withdrawals_root: H256::zero(),
}
}
}
Expand Down Expand Up @@ -96,6 +98,7 @@ impl From<MockBlock> for Block<Transaction> {
mix_hash: Some(mock.mix_hash),
nonce: Some(mock.nonce),
base_fee_per_gas: Some(mock.base_fee_per_gas),
withdrawals_root: Some(mock.withdrawals_root),
other: OtherFields::default(),
}
}
Expand Down Expand Up @@ -126,6 +129,7 @@ impl From<MockBlock> for Block<()> {
mix_hash: Some(mock.mix_hash),
nonce: Some(mock.nonce),
base_fee_per_gas: Some(mock.base_fee_per_gas),
withdrawals_root: Some(mock.withdrawals_root),
other: OtherFields::default(),
}
}
Expand Down
2 changes: 2 additions & 0 deletions zkevm-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ snark-verifier = { git = "https://github.com/brechtpd/snark-verifier.git", branc
snark-verifier-sdk = { git = "https://github.com/brechtpd/snark-verifier.git", branch = "feat/add-sdk", default-features = false, features = ["loader_halo2", "loader_evm", "parallel", "display", "halo2_circuit_params"] }
cli-table = { version = "0.4", optional = true }
once_cell = "1.17.1"
bytes = "1.4.0"
hex = "0.4.3"

[dev-dependencies]
bus-mapping = { path = "../bus-mapping", features = ["test"] }
Expand Down
47 changes: 34 additions & 13 deletions zkevm-circuits/src/evm_circuit/util/constraint_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
};
use bus_mapping::{operation::Target, state_db::EMPTY_CODE_HASH_LE};
use eth_types::Field;
use gadgets::util::not;
use gadgets::util::{and, not};
use halo2_proofs::{
circuit::Value,
plonk::{
Expand Down Expand Up @@ -180,15 +180,12 @@ pub(crate) trait ConstrainBuilderCommon<F: Field> {
pub struct BaseConstraintBuilder<F> {
pub constraints: Vec<(&'static str, Expression<F>)>,
pub max_degree: usize,
pub condition: Option<Expression<F>>,
conditions: Vec<Expression<F>>,
smtmfft marked this conversation as resolved.
Show resolved Hide resolved
}

impl<F: Field> ConstrainBuilderCommon<F> for BaseConstraintBuilder<F> {
fn add_constraint(&mut self, name: &'static str, constraint: Expression<F>) {
let constraint = match &self.condition {
Some(condition) => condition.clone() * constraint,
None => constraint,
};
let constraint = self.get_condition_expr() * constraint;
self.validate_degree(constraint.degree(), name);
self.constraints.push((name, constraint));
}
Expand All @@ -199,25 +196,49 @@ impl<F: Field> BaseConstraintBuilder<F> {
BaseConstraintBuilder {
constraints: Vec::new(),
max_degree,
condition: None,
conditions: Vec::new(),
}
}

pub(crate) fn get_condition(&self) -> Option<Expression<F>> {
if self.conditions.is_empty() {
None
} else {
Some(and::expr(self.conditions.iter()))
}
}

fn get_condition_expr(&self) -> Expression<F> {
self.get_condition().unwrap_or_else(|| 1.expr())
}

pub(crate) fn condition<R>(
&mut self,
condition: Expression<F>,
constraint: impl FnOnce(&mut Self) -> R,
) -> R {
debug_assert!(
self.condition.is_none(),
"Nested condition is not supported"
);
self.condition = Some(condition);
self.conditions.push(condition);
let ret = constraint(self);
self.condition = None;
self.conditions.pop();
ret
}

fn condition_expr_opt(&self) -> Option<Expression<F>> {
let mut iter = self.conditions.iter();
let first = match iter.next() {
Some(e) => e,
None => return None,
};
Some(iter.fold(first.clone(), |acc, e| acc * e.clone()))
}

fn condition_expr(&self) -> Expression<F> {
match self.condition_expr_opt() {
Some(condition) => condition,
None => 1.expr(),
}
}

pub(crate) fn validate_degree(&self, degree: usize, name: &'static str) {
if self.max_degree > 0 {
debug_assert!(
Expand Down
28 changes: 25 additions & 3 deletions zkevm-circuits/src/table/block_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::*;

/// Tag to identify the field in a Block Table row
// Keep the sequence consistent with OpcodeId for scalar
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BlockContextFieldTag {
/// Coinbase field
Coinbase = 1,
Expand All @@ -21,6 +21,28 @@ pub enum BlockContextFieldTag {
/// Chain ID field. Although this is not a field in the block header, we
/// add it here for convenience.
ChainId,
/// Beneficiary field
Beneficiary,
/// StateRoot field
StateRoot,
/// TX Root field
TransactionsRoot,
/// Receipts Root field
ReceiptsRoot,
/// Gas Used field
GasUsed,
/// Mix Hash field
MixHash,
/// Withdrawals Root field
WithdrawalsRoot,
/// Previous Hashes field
PreviousHash,
/// Previous Hashes hi part
PreviousHashHi,
/// Previous Hashes lo part
PreviousHashLo,
/// None for the all zeros row needed in block table
None,
}
impl_expr!(BlockContextFieldTag);

Expand Down Expand Up @@ -49,7 +71,7 @@ impl BlockTable {
pub fn load<F: Field>(
&self,
layouter: &mut impl Layouter<F>,
block: &BlockContext,
block_context: &BlockContext,
randomness: Value<F>,
) -> Result<(), Error> {
layouter.assign_region(
Expand All @@ -67,7 +89,7 @@ impl BlockTable {
offset += 1;

let block_table_columns = <BlockTable as LookupTable<F>>::advice_columns(self);
for row in block.table_assignments(randomness) {
for row in block_context.table_assignments(randomness) {
for (&column, value) in block_table_columns.iter().zip_eq(row) {
region.assign_advice(
|| format!("block table row {}", offset),
Expand Down
Loading
Loading