Skip to content
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9b1d145
Add test case for `SHL`.
silathdiir May 17, 2022
35f66e0
Implement opcode `SHL`.
silathdiir May 18, 2022
1939133
Fix to validate `a64s_hi[idx] < p_hi`, and add Markdown doc for `SHL`.
silathdiir May 18, 2022
897ad08
Move some code from `SHR` to make it work with `master` branch.
silathdiir May 19, 2022
af1c403
Merge remote-tracking branch 'origin/master' into feat/opcode-shl
silathdiir May 29, 2022
5f01718
Replace key `code_source` with `code_hash` in test code.
silathdiir May 29, 2022
929610d
Merge remote-tracking branch 'origin/master' into feat/opcode-shl
silathdiir Jun 4, 2022
8633f59
Fix to use `mul_add_words` for `SHL`.
silathdiir Jun 7, 2022
ad0ed96
Merge previous `SHR` into `SHL`.
silathdiir Jun 9, 2022
1469896
Merge both `SHL` and `SHR` into `mul_div_mod_shl_shr`.
silathdiir Jun 9, 2022
b45da81
Delete separate Markdown doc of `SHL` and `SHR`.
silathdiir Jun 9, 2022
3ad5b22
Fix constraints.
silathdiir Jun 9, 2022
9b95227
Update Markdown doc for `MUL`, `DIV`, `MOD`, `SHL` and `SHR`.
silathdiir Jun 10, 2022
450db8c
Merge remote-tracking branch 'origin/master' into feat/opcode-shl
silathdiir Jun 13, 2022
4598e5f
Fix the wrong argument sequence of `SHL` and `SHR`.
silathdiir Jun 13, 2022
7a7f5b9
Add function `is_op_mul`, `is_op_div`, `is_op_mod`, `is_op_shl` and
silathdiir Jun 13, 2022
76f92ab
Delete `ExecutionState::SHL_SHR` and update Markdown doc according to
silathdiir Jun 14, 2022
63b8b15
`MULMOD` opcode (#204)
davidnevadoc Jun 15, 2022
358f20e
Update spec code according to circuit, and add `Pow2` lookup for shift
silathdiir Jun 16, 2022
c57b4d0
Fix `Pow2` lookup table and update to use `shf0` for lookup.
silathdiir Jun 19, 2022
e39f590
Merge remote-tracking branch 'upstream/master' into feat/opcode-shl
silathdiir Jun 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# MUL, DIV, and MOD opcodes
# MUL, DIV, MOD, SHL and SHR opcodes

## Procedure

Expand All @@ -9,10 +9,12 @@ Pop two EVM words `a` and `b` from the stack, and push `c` to the stack, where `
- for opcode `MUL`, compute `c = (a * b) % 2^256`
- for opcode `DIV`, compute `c = a // b` when `b != 0` otherwise `c = 0`
- for opcode `MOD`, compute `c = a mod b` when `b != 0` otherwise `c = 0`
- for opcode `SHL`, `b` is a number of bits to shift to the left, compute `c = (a * 2^b) % 2^256` when `b < 256` otherwise `c = 0`
- for opcode `SHR`, `b` is a number of bits to shift to the right, compute `c = a // 2^b` when `b < 256` otherwise `c = 0`

### Circuit behavior

To prove the `MUL/DIV/MOD` opcode, we first construct a `MulAddWordsGadget` that proves `a * b + c = d (mod 2^256)` where `a, b, c, d` are all 256-bit words.
To prove the `MUL/DIV/MOD/SHL/SHR` opcode, we first construct a `MulAddWordsGadget` that proves `quotient * divisor + remainder = dividend (mod 2^256)` where `quotient, divisor, remainder, dividend` are all 256-bit words. Consider `quotient, divisor, remander, dividend` as `a, b, c, d` in `MulAddWordsGaget`.
As usual, we use 32 cells to represent each word shown as the table below, where
each cell holds a 8-bit value.

Expand Down Expand Up @@ -60,42 +62,47 @@ $$
overflow = carry_{hi} + A_1B_3 + A_2B_2 + A_3B_1 + A_2B_3 + A_3B_2 + A_3B_3
$$

Now back to the opcode circuit for `MUL`, `DIV`, and `MOD`, we first construct
the `MulAddWordsGadget` with four EVM words `a, b, c, d`.
Now back to the opcode circuit for `MUL`, `DIV`, `MOD`, `SHL` and `SHR`, we first construct the `MulAddWordsGadget` with four EVM words `quotient, divisor, remainder, dividend`.
Based on different opcode cases, we constrain the stack pops and pushes as follows

- for `MUL`, two stack pops are `a` and `b`, and the stack push is `d`
- for `DIV`, two stack pops are `d` and `b`, and the stack push is `a` if `b != 0`; otherwise 0.
- for `MOD`, two stack pops are `d` and `b`, and the stack push is `c` if `b != 0`; otherwise 0.
- for `MUL`, two stack pops are `quotient` and `divisor`, and the stack push is `dividend`.
- for `DIV`, two stack pops are `dividend` and `divisor`, and the stack push is `quotient` if `divisor != 0` and 0 otherwise.
- for `MOD`, two stack pops are `dividend` and `divisor`, and the stack push is `remainder` if `divisor != 0` and 0 otherwise.
- for `SHL`, two stack pops are `quotient` and `shift` when `divisor = 2^shift` if `shift < 256` and 0 otherwise. The stack push is `dividend` if `shift < 256` and 0 otherwise.
- for `SHR`, two stack pops are `dividend` and `shift` when `divisor = 2^shift` if `shift < 256` and 0 otherwise. The stack push is `quotient` if `shift < 256` and 0 otherwise.

The opcode circuit also adds extra constraints for different opcodes:

- if the opcode is `MUL`, constrain `c == 0`.
- if the opcode is not `MUL`,
- use a `LtWordGadget` to constrain `c < b` when `b != 0`
- constrain `overflow == 0`
- use a `LtWordGadget` to constrain `remainder < divisor` when `divisor != 0`.
- if the opcode is `MUL` or `SHL`, constrain `remainder == 0`.
- if the opcode is `DIV`, `MOD` or `SHR`, constrain `overflow == 0`.

## Constraints

1. opcodeId checks
1. opId === OpcodeId(0x02) for `MUL`
2. opId === OpcodeId(0x04) for `DIV`
3. opId === OpcodeId(0x06) for `MOD`
3. opId === OpcodeId(0x1b) for `SHL`
3. opId === OpcodeId(0x1c) for `SHR`
2. state transition:
- gc + 3
- stack_pointer + 1
- pc + 1
- gas + 5
- gas
- when opcode is `MUL`, `DIV` or `MOD`, gas + 5.
- when opcode is `SHL` or `SHR`, gas + 3.
3. Lookups: 3 busmapping lookups
- top of the stack :
- when it's `MUL`, `a` is at the top of the stack
- when it's `DIV`, `d` is at the top of the stack.
- when it's `MOD`, `d` is at the top of the stack.
- `b` is at the second position of the stack
- top of the stack
- when opcode is `MUL` or `SHL`, `quotient` is at the top of the stack.
- when opcode is `DIV`, `MOD` or `SHR`, `dividend` is at the top of the stack.
- second position of the stack
- when opcode is `MUL`, `DIV` or `MOD`, `divisor` is at the second position of the stack.
- when opcode is `SHL` or `SHR`, `shift` is at the second position of the stack when `divisor = 2^shift`.
- new top of the stack
- when it's `MUL`, `d` is at the new top of the stack
- when it's `DIV`, `a` is at the new top of the stack when `b != 0`, otherwise 0
- when it's `MOD`, `c` is at the new top of the stack when `b != 0`, otherwise 0
- when opcode is `MUL` or `SHL`, `dividend` is at the new top of the stack.
- when opcode is `DIV` or `SHR`, `quotient` is at the new top of the stack if `divisor != 0` otherwise 0.
- when opcode is `MOD`, `remainder` is at the new top of the stack if `divisor != 0`, otherwise 0.

## Exceptions

Expand All @@ -104,4 +111,4 @@ The opcode circuit also adds extra constraints for different opcodes:

## Code

See `src/zkevm_specs/evm/execution/mul_div_mod.py`
See `src/zkevm_specs/evm/execution/mul_div_mod_shl_shr.py`
134 changes: 0 additions & 134 deletions specs/opcode/1cSHR.md

This file was deleted.

6 changes: 2 additions & 4 deletions src/zkevm_specs/evm/execution/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
from .iszero import *
from .jump import *
from .jumpi import *
from .mul_div_mod import *
from .origin import *
from .push import *
from .slt_sgt import *
Expand All @@ -35,7 +34,7 @@
from .selfbalance import *
from .extcodehash import *
from .log import *
from .shr import *
from .mul_div_mod_shl_shr import mul_div_mod_shl_shr


EXECUTION_STATE_IMPL: Dict[ExecutionState, Callable] = {
Expand All @@ -46,7 +45,6 @@
ExecutionState.CopyToMemory: copy_to_memory,
ExecutionState.ADD: add_sub,
ExecutionState.ADDMOD: addmod,
ExecutionState.MUL: mul_div_mod,
ExecutionState.ORIGIN: origin,
ExecutionState.CALLER: caller,
ExecutionState.CALLVALUE: callvalue,
Expand All @@ -70,5 +68,5 @@
ExecutionState.LOG: log,
ExecutionState.CALL: call,
ExecutionState.ISZERO: iszero,
ExecutionState.SHR: shr,
ExecutionState.MUL_DIV_MOD_SHL_SHR: mul_div_mod_shl_shr,
}
71 changes: 0 additions & 71 deletions src/zkevm_specs/evm/execution/mul_div_mod.py

This file was deleted.

Loading