diff --git a/zkevm-circuits/src/anchor_tx_circuit.rs b/zkevm-circuits/src/anchor_tx_circuit.rs index b37e94390b..fc6a5fc810 100644 --- a/zkevm-circuits/src/anchor_tx_circuit.rs +++ b/zkevm-circuits/src/anchor_tx_circuit.rs @@ -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 { @@ -59,11 +64,11 @@ pub struct AnchorTxCircuitConfig { use_rlc: Column, // 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, - call_data_tag: Column, + q_call_data_part_start: Selector, + q_call_data_part_step: Selector, + q_call_data_part_end: Selector, + call_data_part_rlc_acc: Column, + call_data_part_tag: Column, sign_verify: SignVerifyConfig, } @@ -94,14 +99,17 @@ impl SubCircuitConfig for AnchorTxCircuitConfig { 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); [ @@ -116,15 +124,16 @@ impl SubCircuitConfig for AnchorTxCircuitConfig { .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(); @@ -137,12 +146,12 @@ impl SubCircuitConfig for AnchorTxCircuitConfig { 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( @@ -153,10 +162,12 @@ impl SubCircuitConfig for AnchorTxCircuitConfig { 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() @@ -173,18 +184,18 @@ impl SubCircuitConfig for AnchorTxCircuitConfig { 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 AnchorTxCircuitConfig { - fn assign_anchor_tx( + fn assign_anchor_tx_values( &self, region: &mut Region<'_, F>, _anchor_tx: &Transaction, @@ -270,6 +281,7 @@ impl AnchorTxCircuitConfig { ), ] { 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 { @@ -277,29 +289,35 @@ impl AnchorTxCircuitConfig { }; 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(); @@ -437,7 +455,7 @@ impl AnchorTxCircuitConfig { || "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(()) }, diff --git a/zkevm-circuits/src/anchor_tx_circuit/sign_verify.rs b/zkevm-circuits/src/anchor_tx_circuit/sign_verify.rs index 73493abfb5..eec91d10a5 100644 --- a/zkevm-circuits/src/anchor_tx_circuit/sign_verify.rs +++ b/zkevm-circuits/src/anchor_tx_circuit/sign_verify.rs @@ -40,7 +40,7 @@ use crate::{ evm_circuit::util::{ constraint_builder::{BaseConstraintBuilder, ConstrainBuilderCommon}, - split_u256_limb64, + rlc, split_u256_limb64, }, table::{LookupTable, TxFieldTag, TxTable}, util::Challenges, @@ -104,31 +104,30 @@ static GX2_MUL_PRIVATEKEY: Lazy = Lazy::new(|| word!("0x4a43b192ca74cab200d6c086df90fb729abca9e52d38b8fa0beb4eafe70956de")); static GX2_MUL_PRIVATEKEY_LO_HI: Lazy<(U256, U256)> = Lazy::new(|| split_u256(&GX2_MUL_PRIVATEKEY)); -// In mul_add chip, we have a * b + c == d -// => a == GX1_MUL_PRIVATEKEY -// => b == 1 -// => c == msg_hash -// => d == N -// // # The circuit layout // - msg_hash (c) // - SigR +// +// We don't have to verify `s` and `v` of the signature, because the signature needs to be valid and +// and those values are fixed if `r` is fixed. +// `msg_hash` is calculated and verified in the tx circuit like any other transaction. #[derive(Debug, Clone)] pub(crate) struct SignVerifyConfig { tx_table: TxTable, - q_sign_start: Selector, - q_sign_step: Selector, - q_sign_end: Selector, + q_sig_start: Selector, + q_sig_step: Selector, + q_sig_end: Selector, tag: Column, - sign: Column, - sign_rlc_acc: Column, - // split u256 to low and high + sig: Column, + sig_rlc_acc: Column, + + // split u256 into 4 64bit limbs q_u64_start: Selector, q_u64_step: Selector, q_u64_end: Selector, - sign_u64_acc: Column, + sig_u64_acc: Column, q_check: Selector, mul_add: MulAddConfig, @@ -141,188 +140,188 @@ impl SignVerifyConfig { tx_table: TxTable, challenges: &Challenges>, ) -> Self { - let q_sign_start = meta.complex_selector(); - let q_sign_step = meta.complex_selector(); - let q_sign_end = meta.complex_selector(); + let q_sig_start = meta.complex_selector(); + let q_sig_step = meta.complex_selector(); + let q_sig_end = meta.complex_selector(); let tag = meta.fixed_column(); - let sign = meta.advice_column(); - let sign_rlc_acc = meta.advice_column_in(SecondPhase); + let sig = meta.advice_column(); + let sig_rlc_acc = meta.advice_column_in(SecondPhase); let q_u64_start = meta.complex_selector(); let q_u64_step = meta.complex_selector(); let q_u64_end = meta.complex_selector(); - let sign_u64_acc = meta.advice_column(); + let sig_u64_acc = meta.advice_column(); - let gx1_rlc = crate::evm_circuit::util::rlc::expr( + // RLC of GX1 bytes + let gx1_rlc = rlc::expr( GX1.to_le_bytes() .map(|v| Expression::Constant(F::from(v as u64))) .as_ref(), challenges.evm_word(), ); - - let gx2_rlc = crate::evm_circuit::util::rlc::expr( + // RLC of GX2 bytes + let gx2_rlc = rlc::expr( GX2.to_le_bytes() .map(|v| Expression::Constant(F::from(v as u64))) .as_ref(), challenges.evm_word(), ); + + // Check if R == GX2 let q_check = meta.complex_selector(); let is_equal_gx2 = IsEqualChip::configure( meta, |meta| meta.query_selector(q_check), - |meta| meta.query_advice(sign_rlc_acc, Rotation(63)), // SigR == GX2 + |meta| meta.query_advice(sig_rlc_acc, Rotation(63)), // SigR == GX2 |_| gx2_rlc.expr(), ); - + // Only enable the mul_add constraints when r == GX2 let mul_add = MulAddChip::configure(meta, |meta| { is_equal_gx2.is_equal_expression.expr() * meta.query_selector(q_check) }); - // signature rlc + // RLC the signature data (per part) (all bytes except the first one) meta.create_gate( - "sign_rlc_acc[i+1] = sign_rlc_acc[i] * randomness + sign[i+1]", + "sig_rlc_acc[i+1] = sig_rlc_acc[i] * randomness + sig[i+1]", |meta| { let mut cb = BaseConstraintBuilder::new(MAX_DEGREE); - let q_sign_step = meta.query_selector(q_sign_step); - let sign_rlc_acc_next = meta.query_advice(sign_rlc_acc, Rotation::next()); - let sign_rlc_acc = meta.query_advice(sign_rlc_acc, Rotation::cur()); - let sign = meta.query_advice(sign, Rotation::next()); + let q_sig_step = meta.query_selector(q_sig_step); + let sig_rlc_acc_next = meta.query_advice(sig_rlc_acc, Rotation::next()); + let sig_rlc_acc = meta.query_advice(sig_rlc_acc, Rotation::cur()); + let sign = meta.query_advice(sig, Rotation::next()); let randomness = challenges.evm_word(); cb.require_equal( - "sign_rlc_acc[i+1] = sign_rlc_acc[i] * randomness + sign[i+1]", - sign_rlc_acc_next, - sign_rlc_acc * randomness + sign, + "sig_rlc_acc[i+1] = sig_rlc_acc[i] * randomness + sign[i+1]", + sig_rlc_acc_next, + sig_rlc_acc * randomness + sign, ); - cb.gate(q_sign_step) + cb.gate(q_sig_step) }, ); - - meta.create_gate("sign_rlc_acc[0] = sign[0]", |meta| { + // RLC the signature data (per part) (first byte) + meta.create_gate("sig_rlc_acc[0] = sign[0]", |meta| { let mut cb = BaseConstraintBuilder::new(MAX_DEGREE); - let q_sign_start = meta.query_selector(q_sign_start); - let sign_rlc_acc = meta.query_advice(sign_rlc_acc, Rotation::cur()); - let sign = meta.query_advice(sign, Rotation::cur()); + let q_sig_start = meta.query_selector(q_sig_start); + let sig_rlc_acc = meta.query_advice(sig_rlc_acc, Rotation::cur()); + let sign = meta.query_advice(sig, Rotation::cur()); - cb.require_equal("sign_rlc_acc[0] = sign[0]", sign_rlc_acc, sign); - cb.gate(q_sign_start) + cb.require_equal("sig_rlc_acc[0] = sign[0]", sig_rlc_acc, sign); + cb.gate(q_sig_start) }); - meta.lookup_any("sign_r or msg_hash in tx_table", |meta| { - let q_sign_end = meta.query_selector(q_sign_end); + // Make sure that `sig_r` and `msg_hash` have the correct value by looking up their RLCd + // representations in the tx table. + meta.lookup_any("sig_r or msg_hash in tx_table", |meta| { + let q_sig_end = meta.query_selector(q_sig_end); let tx_id = super::ANCHOR_TX_ID.expr(); let tag = meta.query_fixed(tag, Rotation::cur()); let index = 0.expr(); - let value = meta.query_advice(sign_rlc_acc, Rotation::cur()); + let value = meta.query_advice(sig_rlc_acc, Rotation::cur()); [tx_id, tag, index, value] .into_iter() .zip(tx_table.table_exprs(meta).into_iter()) - .map(|(arg, table)| (q_sign_end.expr() * arg, table)) + .map(|(arg, table)| (q_sig_end.expr() * arg, table)) .collect::>() }); - // signature u64 + // Decode the 4 64bit limbs of msg_hash and R (all bytes except the first one) meta.create_gate( - "sign_u64_acc[i+1] = sign_u64_acc[i] * BYTE_POW_BASE + sign[i+1]", + "sig_u64_acc[i+1] = sig_u64_acc[i] * BYTE_POW_BASE + sig[i+1]", |meta| { let mut cb = BaseConstraintBuilder::new(MAX_DEGREE); let q_u64_step = meta.query_selector(q_u64_step); - let sign_u64_acc_next = meta.query_advice(sign_u64_acc, Rotation::next()); - let sign_u64_acc = meta.query_advice(sign_u64_acc, Rotation::cur()); - let sign_next = meta.query_advice(sign, Rotation::next()); + let sig_u64_acc_next = meta.query_advice(sig_u64_acc, Rotation::next()); + let sig_u64_acc = meta.query_advice(sig_u64_acc, Rotation::cur()); + let sig_next = meta.query_advice(sig, Rotation::next()); cb.require_equal( - "sign_u64_acc[i+1] = sign_u64_acc[i] * BYTE_POW_BASE + sign[i+1]", - sign_u64_acc_next, - sign_u64_acc * BYTE_POW_BASE.expr() + sign_next, + "sig_u64_acc[i+1] = sig_u64_acc[i] * BYTE_POW_BASE + sig[i+1]", + sig_u64_acc_next, + sig_u64_acc * BYTE_POW_BASE.expr() + sig_next, ); cb.gate(q_u64_step) }, ); - - meta.create_gate("sign_u64_acc[start] = sign[start]", |meta| { + // Decode the 4 64bit limbs of msg_hash and R (first byte) + meta.create_gate("sig_u64_acc[start] = sig[start]", |meta| { let mut cb = BaseConstraintBuilder::new(MAX_DEGREE); let q_u64_start = meta.query_selector(q_u64_start); - let sign_u64_acc = meta.query_advice(sign_u64_acc, Rotation::cur()); - let sign = meta.query_advice(sign, Rotation::cur()); + let sig_u64_acc = meta.query_advice(sig_u64_acc, Rotation::cur()); + let sig = meta.query_advice(sig, Rotation::cur()); - cb.require_equal("sign_u64_acc[start] = sign[start]", sign_u64_acc, sign); + cb.require_equal("sig_u64_acc[start] = sig[start]", sig_u64_acc, sig); cb.gate(q_u64_start) }); - // check SigR + // Check that R has the expected value meta.create_gate( "IF r == GX2 THEN a(msg_hash) * b(1) + c(GX1_MUL_PRIVATEKEY) == d(N)", |meta| { let mut cb = BaseConstraintBuilder::new(MAX_DEGREE); - let q_check = meta.query_selector(q_check); - - let sign_rlc_acc = meta.query_advice(sign_rlc_acc, Rotation(63)); - - cb.require_in_set("r in (GX1, GX2)", sign_rlc_acc, vec![gx1_rlc, gx2_rlc]); + // R needs to be either GX1 or Gx2 + let sig_rlc_acc = meta.query_advice(sig_rlc_acc, Rotation(63)); + cb.require_in_set("r in (GX1, GX2)", sig_rlc_acc, vec![gx1_rlc, gx2_rlc]); + // In mul_add chip, we have a * b + c == d + // => a == msg_hash + // => b == 1 + // => c == GX1_MUL_PRIVATEKEY + // => d == N + // Check that the inputs a, b, and c into mul_add are correct // a == msg_hash - let (a_limbs_cur0, a_limbs_cur1, a_limbs_cur2, a_limbs_cur3) = - mul_add.a_limbs_cur(meta); - - // c == msg_hash - let a_limb0 = meta.query_advice(sign_u64_acc, Rotation(31)); - let a_limb1 = meta.query_advice(sign_u64_acc, Rotation(23)); - let a_limb2 = meta.query_advice(sign_u64_acc, Rotation(15)); - let a_limb3 = meta.query_advice(sign_u64_acc, Rotation(7)); - cb.require_equal("a_limb0", a_limbs_cur0, a_limb0); - cb.require_equal("a_limb1", a_limbs_cur1, a_limb1); - cb.require_equal("a_limb2", a_limbs_cur2, a_limb2); - cb.require_equal("a_limb3", a_limbs_cur3, a_limb3); - + let a = mul_add.a_limbs_cur(meta); + cb.require_equal("a.0", a.0, meta.query_advice(sig_u64_acc, Rotation(31))); + cb.require_equal("a.1", a.1, meta.query_advice(sig_u64_acc, Rotation(23))); + cb.require_equal("a.2", a.2, meta.query_advice(sig_u64_acc, Rotation(15))); + cb.require_equal("a.3", a.3, meta.query_advice(sig_u64_acc, Rotation(7))); // b == 1 - let (b_limb0, b_limb1, b_limb2, b_limb3) = mul_add.b_limbs_cur(meta); - let b_limb = split_u256_limb64(&U256::one()) + let b = mul_add.b_limbs_cur(meta); + let one = split_u256_limb64(&U256::one()) .map(|v| Expression::Constant(F::from(v.as_u64()))); - cb.require_equal("b_limb0", b_limb0, b_limb[0].expr()); - cb.require_equal("b_limb1", b_limb1, b_limb[1].expr()); - cb.require_equal("b_limb2", b_limb2, b_limb[2].expr()); - cb.require_equal("b_limb3", b_limb3, b_limb[3].expr()); - + cb.require_equal("b.0", b.0, one[0].expr()); + cb.require_equal("b.1", b.1, one[1].expr()); + cb.require_equal("b.2", b.2, one[2].expr()); + cb.require_equal("b.3", b.3, one[3].expr()); // c == GX1_MUL_PRIVATEKEY - let c_lo_hi0 = + let gx1_mul_privatekey_0 = Expression::Constant(F::from_u128(GX1_MUL_PRIVATEKEY_LO_HI.0.as_u128())); - let c_lo_hi1 = + let gx1_mul_privatekey_1 = Expression::Constant(F::from_u128(GX1_MUL_PRIVATEKEY_LO_HI.1.as_u128())); - let (c_lo_cur, c_hi_cur) = mul_add.c_lo_hi_cur(meta); - cb.require_equal("c_lo_cur", c_lo_hi0, c_lo_cur); - cb.require_equal("c_hi_cur", c_lo_hi1, c_hi_cur); - - // d == N - let (d_lo_cur, d_hi_cur) = mul_add.d_lo_hi_cur(meta); - let d_lo_cur_expr = Expression::Constant(F::from_u128(N_LO_HI.0.as_u128())); - let d_hi_cur_expr = Expression::Constant(F::from_u128(N_LO_HI.1.as_u128())); - - cb.require_equal("d_lo_cur", d_lo_cur_expr, d_lo_cur); - cb.require_equal("d_hi_cur", d_hi_cur_expr, d_hi_cur); - cb.gate(q_check) + let c = mul_add.c_lo_hi_cur(meta); + cb.require_equal("c.0", c.0, gx1_mul_privatekey_0); + cb.require_equal("c.1", c.1, gx1_mul_privatekey_1); + + // Now finally check that d == N + let n_0 = Expression::Constant(F::from_u128(N_LO_HI.0.as_u128())); + let n_1 = Expression::Constant(F::from_u128(N_LO_HI.1.as_u128())); + let d = mul_add.d_lo_hi_cur(meta); + cb.require_equal("d.0", d.0, n_0); + cb.require_equal("d.1", d.1, n_1); + + cb.gate(meta.query_selector(q_check)) }, ); Self { tx_table, - q_sign_start, - q_sign_step, - q_sign_end, + q_sig_start, + q_sig_step, + q_sig_end, tag, - sign, - sign_rlc_acc, + sig, + sig_rlc_acc, q_u64_start, q_u64_step, q_u64_end, - sign_u64_acc, + sig_u64_acc, q_check, mul_add, @@ -349,12 +348,7 @@ impl SignVerifyConfig { let row_offset = *offset + idx; u64_acc = u64_acc * Value::known(F::from(BYTE_POW_BASE)) + Value::known(F::from(*byte as u64)); - region.assign_advice( - || "sign_u64_acc", - self.sign_u64_acc, - row_offset, - || u64_acc, - )?; + region.assign_advice(|| "sig_u64_acc", self.sig_u64_acc, row_offset, || u64_acc)?; // setup selector if idx == 0 { self.q_u64_start.enable(region, row_offset)?; @@ -379,8 +373,8 @@ impl SignVerifyConfig { for (idx, byte) in value.iter().enumerate() { let row_offset = *offset + idx; region.assign_advice( - || "sign", - self.sign, + || "sig", + self.sig, row_offset, || Value::known(F::from(*byte as u64)), )?; @@ -392,16 +386,16 @@ impl SignVerifyConfig { )?; rlc_acc = rlc_acc * randomness + Value::known(F::from(*byte as u64)); - region.assign_advice(|| "sign_rlc_acc", self.sign_rlc_acc, row_offset, || rlc_acc)?; + region.assign_advice(|| "sig_rlc_acc", self.sig_rlc_acc, row_offset, || rlc_acc)?; // setup selector if idx == 0 { - self.q_sign_start.enable(region, row_offset)?; + self.q_sig_start.enable(region, row_offset)?; } // the last offset of field if idx == 31 { - self.q_sign_end.enable(region, row_offset)?; + self.q_sig_end.enable(region, row_offset)?; } else { - self.q_sign_step.enable(region, row_offset)?; + self.q_sig_step.enable(region, row_offset)?; } } *offset += 32; @@ -433,21 +427,21 @@ impl SignVerifyConfig { let msg_hash = U256::from_little_endian(&anchor_tx.tx_sign_hash.to_fixed_bytes()); self.load_mul_add(region, msg_hash)?; let mut offset = 0; - for (annotation, tag, need_check, value) in [ + for (annotation, tag, do_check_equal_to_gx2, value) in [ ( "msg_hash", TxFieldTag::TxSignHash, false, msg_hash.to_be_bytes(), ), - ("sign_r", TxFieldTag::SigR, true, anchor_tx.r.to_be_bytes()), + ("sig_r", TxFieldTag::SigR, true, anchor_tx.r.to_be_bytes()), ] { let rlc_acc = self.assign_field(region, annotation, &mut offset, tag, value, challenges)?; - if need_check { - let gx2_rlc = challenges.evm_word().map(|randomness| { - crate::evm_circuit::util::rlc::value(&GX2.to_le_bytes(), randomness) - }); + if do_check_equal_to_gx2 { + let gx2_rlc = challenges + .evm_word() + .map(|randomness| rlc::value(&GX2.to_le_bytes(), randomness)); let chip = IsEqualChip::construct(self.is_equal_gx2.clone()); chip.assign(region, 0, rlc_acc, gx2_rlc)?; } diff --git a/zkevm-circuits/src/anchor_tx_circuit/test.rs b/zkevm-circuits/src/anchor_tx_circuit/test.rs index 7de03f5dd3..bb07cbbc57 100644 --- a/zkevm-circuits/src/anchor_tx_circuit/test.rs +++ b/zkevm-circuits/src/anchor_tx_circuit/test.rs @@ -50,14 +50,6 @@ use num_bigint::BigUint; use once_cell::sync::Lazy; use sha3::{Digest, Keccak256}; -#[test] -fn tx_circuit_unusable_rows() { - assert_eq!( - AnchorTxCircuit::::unusable_rows(), - unusable_rows::>(()), - ) -} - pub(crate) fn anchor_sign( anchor_tx: &Transaction, chain_id: u64, @@ -183,7 +175,7 @@ fn gen_block( block } -fn correct_sign(tx: &mut MockTransaction) { +fn sign_tx(tx: &mut MockTransaction) { let chain_id = (*MOCK_CHAIN_ID).as_u64(); let _tx: Transaction = tx.to_owned().into(); let sig_data = anchor_sign(&_tx, chain_id).unwrap(); @@ -192,17 +184,7 @@ fn correct_sign(tx: &mut MockTransaction) { tx.sig_data((2712, sig_r, sig_s)); } -#[test] -fn test() { - let taiko = Taiko { - anchor_gas_cost: 150000, - ..Default::default() - }; - let block = gen_block::<1>(2, 100, taiko, correct_sign); - assert_eq!(run::(&block, None), Ok(())); -} - -fn sign_r_is_gx2(tx: &mut MockTransaction) { +fn sign_tx_r_is_gx2(tx: &mut MockTransaction) { let msg_hash = *N - *GX1_MUL_PRIVATEKEY; let msg_hash = ct_option_ok_or( secp256k1::Fq::from_repr(msg_hash.to_le_bytes()), @@ -222,13 +204,31 @@ fn sign_r_is_gx2(tx: &mut MockTransaction) { } #[test] -fn test_when_sign_r_is_gx2() { +fn anchor_tx_circuit_unusable_rows() { + assert_eq!( + AnchorTxCircuit::::unusable_rows(), + unusable_rows::>(()), + ) +} + +#[test] +fn anchor_test() { + let taiko = Taiko { + anchor_gas_cost: 150000, + ..Default::default() + }; + let block = gen_block::<1>(2, 100, taiko, sign_tx); + assert_eq!(run::(&block, None), Ok(())); +} + +#[test] +fn anchor_test_when_sign_r_is_gx2() { let taiko = Taiko { anchor_gas_cost: 150000, ..Default::default() }; let msg_hash = *N - *GX1_MUL_PRIVATEKEY; let msg_hash = H256::from(msg_hash.to_le_bytes()); - let block = gen_block::<1>(2, 100, taiko, sign_r_is_gx2); + let block = gen_block::<1>(2, 100, taiko, sign_tx_r_is_gx2); assert_eq!(run::(&block, Some(msg_hash)), Ok(())); }