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.
This should be Word<F>, right? As the code hash can be more than 254 bits
There was a problem hiding this comment.
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.
| #[test] | ||
| fn extcodehash_gadget_cold_account() { |
There was a problem hiding this comment.
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.
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.
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.
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.
| external_address: RandomLinearCombination<F, N_BYTES_ACCOUNT_ADDRESS>, | ||
| tx_id: Cell<F>, | ||
| previously_accessed: Cell<F>, | ||
| external_code_hash: Cell<F>, |
| #[test] | ||
| fn extcodehash_gadget_cold_account() { |
There was a problem hiding this comment.
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-ethereum/zkevm-specs#139. This PR is ready for another look as well. |
595c329 to
3df8130
Compare
|
@ed255 this is ready for review again |
ed255
left a comment
There was a problem hiding this comment.
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.
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.
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.
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
RwCounterEndOfReversionandIsPersistent? 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.
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>
ed255
left a comment
There was a problem hiding this comment.
LGTM! Thanks for working on this :)
icemelon
left a comment
There was a problem hiding this comment.
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.
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-ethereum/zkevm-specs#139