-
Notifications
You must be signed in to change notification settings - Fork 840
Circuit for EXTCODEHASH opcode #353
Circuit for EXTCODEHASH opcode #353
Conversation
f3e186b
to
14ec0d9
Compare
@ed255, can you take a look at this when you get the chance? |
external_address: RandomLinearCombination<F, N_BYTES_ACCOUNT_ADDRESS>, | ||
tx_id: Cell<F>, | ||
previously_accessed: Cell<F>, | ||
external_code_hash: Cell<F>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be Word<F>
, right? As the code hash can be more than 254 bits
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code hash is 256 bits, but the constraints are all expressed in terms of its RLC encoding. The code hash is RLC encoded for the RW table here: https://github.com/scroll-tech/zkevm-circuits/blob/e2a746f632f67e905fde5390e604c491cbc367fc/zkevm-circuits/src/evm_circuit/witness.rs#L647 and self.external_code_hash
is RLC encoded in the assign_exec_step
step in this gadget as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct!
#[test] | ||
fn extcodehash_gadget_cold_account() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should also have a test case that asserts failure, when gas available is only sufficient for a warm account, whereas gas_cost
for EXTCODEHASH
should be more than that (for a cold account). In this scenario the prover should fail with insufficient gas available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote this test:
#[test]
fn extcodehash_gadget_insufficient_gas() {
let address = address!("0xaabbccddee000000000000000000000000000011");
let code = bytecode! {
PUSH20(address.to_word())
#[start]
EXTCODEHASH
STOP
};
assert_eq!(test_circuits_using_bytecode(code, BytecodeTestConfig {
gas_limit: 100,
..Default::default()
}), Ok(()));
}
but it fails with
---- evm_circuit::execution::extcodehash::test::extcodehash_gadget_insufficient_gas stdout ----
thread 'evm_circuit::execution::extcodehash::test::extcodehash_gadget_insufficient_gas' panicked at 'called `Result::unwrap()` on an `Err` value: TracingError("Failed to trace tx, err: intrinsic gas too low: have 100, want 21000")', zkevm-circuits/src/test_util.rs:58:78
which is during the witness generation. I don't think it's possible (right now) to even try to generate a proof for a transaction that reverts because of insufficient gas.
The two existing warm/cold tests already ensure that the gas cost constraint in the state transition is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're working on enabling better test-case generation. See: #349
Other Opcodes like GASPRICE
also do have issues to be implemented until we close it.
We can leave an issue open as tech-debt or something similar.
For now, we don't really have a way as when Geth gets an out-of-gas exception it doesn't return the trace.
We also need to update this behaviour. And we should file an issue for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forget about what I said above.
I was wrong. In fact, a tx like the one you purpose here is not valid. And would not be included in a block as basically, there's no way to execute it.
The minimum gas needed to start a tx is 21000. Hence, if you use 21001 as gas argument this would end up in an out-of-gas and you'd get a trace back. But without enough funds to even kickstart the tx,
My suggestion is to increase the gas you provide to the tx.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Brilliant job!!
external_address: RandomLinearCombination<F, N_BYTES_ACCOUNT_ADDRESS>, | ||
tx_id: Cell<F>, | ||
previously_accessed: Cell<F>, | ||
external_code_hash: Cell<F>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct!
#[test] | ||
fn extcodehash_gadget_cold_account() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're working on enabling better test-case generation. See: #349
Other Opcodes like GASPRICE
also do have issues to be implemented until we close it.
We can leave an issue open as tech-debt or something similar.
For now, we don't really have a way as when Geth gets an out-of-gas exception it doesn't return the trace.
We also need to update this behaviour. And we should file an issue for that.
@z2trillion The current approach followed to implement the |
0637e1a
to
8d4ce09
Compare
@ed255 i've made a PR for the specs here: privacy-scaling-explorations/zkevm-specs#139. This PR is ready for another look as well. |
595c329
to
3df8130
Compare
@ed255 this is ready for review again |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good! I've just added a few comments about details on the bus-mapping implementation, and a typo I spotted in the circuit tests.
from_bytes::expr(&external_address.cells), | ||
1.expr(), | ||
is_warm.expr(), | ||
None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reviewed the implementation of SSTORE and I realized I missed this before. For an op that can revert, this shouldn't be None
. Take a look here:
https://github.com/appliedzkp/zkevm-circuits/blob/c5dda20e901951e61f751b89dd50607f83b98a95/zkevm-circuits/src/evm_circuit/execution/sstore.rs#L75-L81
This will require adding two read operations for CallContextFieldTag::RwCounterEndOfReversion
, CallContextFieldTag::IsPersistent
as seen here:
https://github.com/appliedzkp/zkevm-circuits/blob/c5dda20e901951e61f751b89dd50607f83b98a95/zkevm-circuits/src/evm_circuit/execution/sstore.rs#L50-L56
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made these changes to the circuit and the changes needed to the bus mapping, but now the circuit tests fail.
Do you know if the witness generation supports RwCounterEndOfReversion
and IsPersistent
? I noticed that the sload bus mapping doesn't correspond to the circuit and that the sload and sstore circuits both manually construct the rw tables for their tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made these changes to the circuit and the changes needed to the bus mapping, but now the circuit tests fail.
Do you know if the witness generation supports
RwCounterEndOfReversion
andIsPersistent
? I noticed that the sload bus mapping doesn't correspond to the circuit and that the sload and sstore circuits both manually construct the rw tables for their tests.
I will investigate this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found the bug! After you added generating the operations for CallContextFieldTag::RwCounterEndOfReversion and CallContextFieldTag::RwCounterEndOfReversion you altered the positions of the other operations for that step in rw_indices. So when you query the values in the assign advice method, you need to update the indexes of rw_index to obtain the values for nonce, balance and code_hash. See #353 (comment)
Co-authored-by: Eduard S. <eduardsanou@posteo.net>
9c760d0
to
33cf4f7
Compare
Co-authored-by: Eduard S. <eduardsanou@posteo.net>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks for working on this :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. just one nitpick
* (1.expr() - nonce.expr() * nonempty_witness.expr()) | ||
* (1.expr() - balance.expr() * nonempty_witness.expr()) | ||
* (1.expr() - (code_hash.expr() - empty_code_hash_rlc) * nonempty_witness.expr()), | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is smart. it took me a while to realize the constraint is right. 😄
Co-authored-by: Haichen Shen <shenhaichen@gmail.com>
* add test case for tx.to is zero * fix: handle the rlp of tx whose to = zero * add gates for is_create * clippy
Spec PR: privacy-scaling-explorations/zkevm-specs#139