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

Commit

Permalink
Merge pull request #116 from taikoxyz/feat/anchor_tx-small-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
johntaiko authored Jun 21, 2023
2 parents 3a43132 + 615dd25 commit 769bffb
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 185 deletions.
98 changes: 58 additions & 40 deletions zkevm-circuits/src/anchor_tx_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,22 @@ use std::marker::PhantomData;

use self::sign_verify::GOLDEN_TOUCH_ADDRESS;

// The first of txlist is the anchor tx
// The anchor tx is the first tx
const ANCHOR_TX_ID: usize = 1;
const ANCHOR_TX_VALUE: u64 = 0;
const ANCHOR_TX_IS_CREATE: bool = false;
const ANCHOR_TX_GAS_PRICE: u64 = 0;
// TODO: calculate the method_signature
const ANCHOR_TX_METHOD_SIGNATURE: u32 = 0;
const MAX_DEGREE: usize = 9;
const BYTE_POW_BASE: u64 = 1 << 8;

// anchor(bytes32,bytes32,uint64,uint64) = method_signature(4B)+1st(32B)+2nd(32B)+3rd(8B)+4th(8B)
// function anchor(
// bytes32 l1Hash,
// bytes32 l1SignalRoot,
// uint64 l1Height,
// uint64 parentGasUsed
// )
// anchor(bytes32,bytes32,uint64,uint64) =
// method_signature(4B)+l1Hash(32B)+l1SignalRoot(32B)+l1Height(8B)+parentGasUsed(8B)
const ANCHOR_CALL_DATA_LEN: usize = 84;

struct CallData {
Expand All @@ -59,11 +64,11 @@ pub struct AnchorTxCircuitConfig<F: Field> {
use_rlc: Column<Fixed>,

// check: method_signature, l1Hash, l1SignalRoot, l1Height, parentGasUsed
q_call_data_start: Selector,
q_call_data_step: Selector,
q_call_data_end: Selector,
call_data_rlc_acc: Column<Advice>,
call_data_tag: Column<Fixed>,
q_call_data_part_start: Selector,
q_call_data_part_step: Selector,
q_call_data_part_end: Selector,
call_data_part_rlc_acc: Column<Advice>,
call_data_part_tag: Column<Fixed>,

sign_verify: SignVerifyConfig<F>,
}
Expand Down Expand Up @@ -94,14 +99,17 @@ impl<F: Field> SubCircuitConfig<F> for AnchorTxCircuitConfig<F> {
let tag = meta.fixed_column();
let use_rlc = meta.fixed_column();

let q_call_data_start = meta.complex_selector();
let q_call_data_step = meta.complex_selector();
let q_call_data_end = meta.complex_selector();
let call_data_rlc_acc = meta.advice_column_in(SecondPhase);
let call_data_tag = meta.fixed_column();
let q_call_data_part_start = meta.complex_selector();
let q_call_data_part_step = meta.complex_selector();
let q_call_data_part_end = meta.complex_selector();
let call_data_part_rlc_acc = meta.advice_column_in(SecondPhase);
let call_data_part_tag = meta.fixed_column();
let sign_verify = SignVerifyConfig::configure(meta, tx_table.clone(), &challenges);

// anchor transaction constants
// Verify the constant values of the anchor tx in the tx table.
// The tag and its corresponding constant value are stored next to each other vertically.
// (if the tag is at row i, its value is at row i + 1).
// Because of this, this lookup is enabled every other row.
meta.lookup_any("anchor fixed fields", |meta| {
let q_tag = meta.query_selector(q_tag);
[
Expand All @@ -116,15 +124,16 @@ impl<F: Field> SubCircuitConfig<F> for AnchorTxCircuitConfig<F> {
.collect()
});

// call data
// RLC/decode the calldata (per part) of the anchor tx (all bytes except the first one)
meta.create_gate(
"call_data_rlc_acc[i+1] = call_data_rlc_acc[i] * t + call_data[i+1]",
|meta| {
let mut cb = BaseConstraintBuilder::new(MAX_DEGREE);

let q_call_data_step = meta.query_selector(q_call_data_step);
let call_data_rlc_acc_next = meta.query_advice(call_data_rlc_acc, Rotation::next());
let call_data_rlc_acc = meta.query_advice(call_data_rlc_acc, Rotation::cur());
let q_call_data_step = meta.query_selector(q_call_data_part_step);
let call_data_rlc_acc_next =
meta.query_advice(call_data_part_rlc_acc, Rotation::next());
let call_data_rlc_acc = meta.query_advice(call_data_part_rlc_acc, Rotation::cur());
let call_data_next = meta.query_advice(tx_table.value, Rotation::next());
let use_rlc = meta.query_fixed(use_rlc, Rotation::cur());
let randomness = challenges.lookup_input();
Expand All @@ -137,12 +146,12 @@ impl<F: Field> SubCircuitConfig<F> for AnchorTxCircuitConfig<F> {
cb.gate(q_call_data_step)
},
);

// RLC/decode the calldata (per part) of the anchor tx (first byte)
meta.create_gate("call_data_rlc_acc[0] = call_data[0]", |meta| {
let mut cb = BaseConstraintBuilder::new(MAX_DEGREE);

let q_call_data_start = meta.query_selector(q_call_data_start);
let call_data_rlc_acc = meta.query_advice(call_data_rlc_acc, Rotation::cur());
let q_call_data_start = meta.query_selector(q_call_data_part_start);
let call_data_rlc_acc = meta.query_advice(call_data_part_rlc_acc, Rotation::cur());
let call_data = meta.query_advice(tx_table.value, Rotation::cur());

cb.require_equal(
Expand All @@ -153,10 +162,12 @@ impl<F: Field> SubCircuitConfig<F> for AnchorTxCircuitConfig<F> {
cb.gate(q_call_data_start)
});

// After RLC/decode of an input in the calldata, verify that the value matches the expected
// value in the public input table.
meta.lookup_any("call data in pi_table", |meta| {
let q_call_data_end = meta.query_selector(q_call_data_end);
let call_data_rlc_acc = meta.query_advice(call_data_rlc_acc, Rotation::cur());
let call_data_tag = meta.query_fixed(call_data_tag, Rotation::cur());
let q_call_data_end = meta.query_selector(q_call_data_part_end);
let call_data_rlc_acc = meta.query_advice(call_data_part_rlc_acc, Rotation::cur());
let call_data_tag = meta.query_fixed(call_data_part_tag, Rotation::cur());

[call_data_tag, call_data_rlc_acc]
.into_iter()
Expand All @@ -173,18 +184,18 @@ impl<F: Field> SubCircuitConfig<F> for AnchorTxCircuitConfig<F> {
tag,
use_rlc,

q_call_data_start,
q_call_data_step,
q_call_data_end,
call_data_rlc_acc,
call_data_tag,
q_call_data_part_start,
q_call_data_part_step,
q_call_data_part_end,
call_data_part_rlc_acc,
call_data_part_tag,
sign_verify,
}
}
}

impl<F: Field> AnchorTxCircuitConfig<F> {
fn assign_anchor_tx(
fn assign_anchor_tx_values(
&self,
region: &mut Region<'_, F>,
_anchor_tx: &Transaction,
Expand Down Expand Up @@ -270,36 +281,43 @@ impl<F: Field> AnchorTxCircuitConfig<F> {
),
] {
let mut rlc_acc = Value::known(F::ZERO);
// Use RLC encoding if the input doesn't fit within the field
let (use_rlc, t) = if value.len() * 8 > F::CAPACITY as usize {
(Value::known(F::ONE), challenges.evm_word())
} else {
(Value::known(F::ZERO), Value::known(F::from(BYTE_POW_BASE)))
};
for (idx, byte) in value.iter().enumerate() {
let row_offset = offset + idx;

// RLC/Decode bytes
region.assign_fixed(|| annotation, self.use_rlc, row_offset, || use_rlc)?;
rlc_acc = rlc_acc * t + Value::known(F::from(*byte as u64));
region.assign_advice(
|| annotation,
self.call_data_rlc_acc,
self.call_data_part_rlc_acc,
row_offset,
|| rlc_acc,
)?;

// Set the tag for this input
region.assign_fixed(
|| annotation,
self.call_data_tag,
self.call_data_part_tag,
row_offset,
|| Value::known(F::from(tag as u64)),
)?;
region.assign_fixed(|| annotation, self.use_rlc, row_offset, || use_rlc)?;
// setup selector

// Always enable the `start` selector at the first byte
if idx == 0 {
self.q_call_data_start.enable(region, row_offset)?;
self.q_call_data_part_start.enable(region, row_offset)?;
}
// the last offset of field
// If we're at the last byte, enable the `end` selector.
// Otherwise enable the `step` selector.
if idx == value.len() - 1 {
self.q_call_data_end.enable(region, row_offset)?;
self.q_call_data_part_end.enable(region, row_offset)?;
} else {
self.q_call_data_step.enable(region, row_offset)?;
self.q_call_data_part_step.enable(region, row_offset)?;
}
}
offset += value.len();
Expand Down Expand Up @@ -437,7 +455,7 @@ impl<F: Field> AnchorTxCircuitConfig<F> {
|| "anchor transaction",
|ref mut region| {
self.load_tx_table(region, txs, max_txs, max_calldata, challenges)?;
self.assign_anchor_tx(region, anchor_tx, taiko, challenges)?;
self.assign_anchor_tx_values(region, anchor_tx, taiko, challenges)?;
self.assign_call_data(region, anchor_tx, call_data, challenges)?;
Ok(())
},
Expand Down
Loading

0 comments on commit 769bffb

Please sign in to comment.