changed 3 years ago
Linked with GitHub

ZKEVM - Bytes Copy

In EVM, there are many opcodes able to copy some chunk of bytes from different source to stack or memory:

  • CALLDATALOAD - push 32 bytes from calldata as a word to stack
  • CALLDATACOPY - copy * bytes from calldata to memory
  • CODECOPY - copy * bytes from current bytecode to memory
  • EXTCODECOPY - copy * bytes from external bytecode to memory
  • RETURNDATACOPY - copy * bytes from returndata to memory
  • JUMP, JUMPI - read the destination byte
  • PUSH* - push * bytes from current bytecode as a word to stack
  • Implicit STOP - EVM returns a implicit STOP in the end if program counter is increased out of range.

If the requested range is out of source bound, only RETURNDATACOPY triggers error, others right pad the result with all zeros.

CALLDATALOAD, CALLDATACOPY

Calldata source could be:

  • tx_table - when root
  • rw_table - when internal

Since the calldata of tx_table could be up to ≈223 (7486750) (all zeros calldata with 30 million gas limit (30000000-53000) / 4), in the worst case we need 3 bytes range lookup to compare if the bytes copy is out of range.

CODECOPY

Bytecode source could be:

  • tx_table - when root creation
  • bytecode_table - when call and internal creation

Again one of the source is tx_table, in the worst case we still need 3 bytes range lookup.

EXTCODECOPY

External bytecode source could only be bytecode_table since it's already deployed, so the range becomes 3 * 213 (0x6000) which can be done by 2 bytes range lookup.

But considering EXTCODECOPY is really similar to CODECOPY, we probably handled them together.

RETURNDATACOPY

Since the source is always from memory of rw_table, we can verify the range by 5 bytes range lookup.

JUMP, JUMPI

For the success case we don't need to worry about the range, the lookup already did for us.

However, for the out-of-range jump case, we need to verify it's indeed out of range, and the source is same as CODECOPY.

PUSH*

We can handle this in the same way as CODECOPY since they have the same source.

We can also try to hack on the source described in the next section.

Implicit STOP in the end

If we can ask Bytecode circuit to pad 33 0 in the end of each bytecode, and ask Tx circuit to also do so in the end of calldata of each transaction, then we don't need to worry about the implicit STOP and PUSH* out of range.

Select a repo