privacy-scaling-explorations / zkevm-circuits

Home Page:https://privacy-scaling-explorations.github.io/zkevm-circuits/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

soundness: begin_tx tx_id should be read?

lispc opened this issue · comments

What command(s) is the bug in?

No response

Describe the bug

here

cb.call_context_lookup_write(
the tx_id is written into CallContext, but this cell is not constrained. I know in EndTxGadget, tx_id is increased by one. I think in begin_tx, an evil attacker can still assign an invalid value to BeginTxHelperGadget.tx_id? The call_context_lookup_write of TxId inside EndTx, and the call_context_lookup_write of TxId inside BeginTx, are 2 different rws, so the former cannot constrain the latter? Unless we modify codes and deliberately make them share same rwc so they can be same identical rw?

Concrete steps to reproduce the bug. If it's able reproduce via testool, please share test_id from jenkins report

No response

We had an open issue about missing constraints in BeginTx #1475 (it could be unrelated though, but a main point of that issue is to sync the specs and implementation of BeginTx)

commented

Hi, Just have a quick look, In end_tx.rs

cb.call_context_lookup_write(
Some(cb.next.state.rw_counter.expr()),
CallContextFieldTag::TxId,
Word::from_lo_unchecked(tx_id.expr() + 1.expr()),
);

it constrain next TxId should be current TxId + 1 with under next state (cb.next.state) rw_counter cb.next.state.rw_counter. So end_tx and next begin_tx already share the same rwc ?

Besides, rw_counter should be unique under same tag

meta.create_gate("limb_difference is not zero", |meta| {
let selector = meta.query_fixed(selector, Rotation::cur());
let limb_difference = meta.query_advice(limb_difference, Rotation::cur());
let limb_difference_inverse =
meta.query_advice(limb_difference_inverse, Rotation::cur());
vec![selector * (1.expr() - limb_difference * limb_difference_inverse)]
});

It seems to me there is no soundness issue, cmiiw :)

Hi, Just have a quick look, In end_tx.rs

cb.call_context_lookup_write(
Some(cb.next.state.rw_counter.expr()),
CallContextFieldTag::TxId,
Word::from_lo_unchecked(tx_id.expr() + 1.expr()),
);

it constrain next TxId should be current TxId + 1 with under next state (cb.next.state) rw_counter cb.next.state.rw_counter. So end_tx and next begin_tx already share the same rwc ?

Besides, rw_counter should be unique under same tag

meta.create_gate("limb_difference is not zero", |meta| {
let selector = meta.query_fixed(selector, Rotation::cur());
let limb_difference = meta.query_advice(limb_difference, Rotation::cur());
let limb_difference_inverse =
meta.query_advice(limb_difference_inverse, Rotation::cur());
vec![selector * (1.expr() - limb_difference * limb_difference_inverse)]
});

It seems to me there is no soundness issue, cmiiw :)

I think line128, the rwc is used as call_id. Rwc is automatically maintained inside constrain builder. So ithink they don't share same rwc

commented

cb.call_context_lookup_write(
Some(cb.next.state.rw_counter.expr()),
CallContextFieldTag::TxId,
Word::from_lo_unchecked(tx_id.expr() + 1.expr()),
);

I think line128, the rwc is used as call_id. Rwc is automatically maintained inside constrain builder. So ithink they don't share same rwc

Yeah you're right, just notice it was used as call_id. So yes there is soundness due to mismatch rwc. One quick fix I can imagine is we need to use rw_lookup_with_counter

fn rw_lookup_with_counter(
&mut self,
name: &str,
counter: Expression<F>,
is_write: Expression<F>,
tag: Target,
values: RwValues<F>,

And pass exactly same (rwc, call_id) to assure consistent rwc and only one entry is there

commented

Hi @lispc This issue was fixed in PR #1719 and merged, please kindly check, thanks!

seems good!