diff --git a/yellow-paper/docs/public-vm/InstructionSet.mdx b/yellow-paper/docs/public-vm/InstructionSet.mdx new file mode 100644 index 00000000000..141e435dd25 --- /dev/null +++ b/yellow-paper/docs/public-vm/InstructionSet.mdx @@ -0,0 +1,5 @@ +# Instruction Set + +import GeneratedInstructionSet from './gen/_InstructionSet.mdx'; + + \ No newline at end of file diff --git a/yellow-paper/docs/public-vm/Types.mdx b/yellow-paper/docs/public-vm/Types.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/yellow-paper/docs/public-vm/_category_.json b/yellow-paper/docs/public-vm/_category_.json new file mode 100644 index 00000000000..b71bfdd8d04 --- /dev/null +++ b/yellow-paper/docs/public-vm/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "AVM: Aztec's Public VM", + "position": 5, + "link": { + "type": "generated-index", + "description": "Aztec's Public VM..." + } +} diff --git a/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx b/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx new file mode 100644 index 00000000000..60bd17532b4 --- /dev/null +++ b/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx @@ -0,0 +1,1330 @@ +[comment]: # (THIS IS A GENERATED FILE! DO NOT EDIT!) +[comment]: # (Generated via `yarn preprocess`) + +[comment]: # (Generated by InstructionSetMarkdownGen.tsx and InstructionSet.js) + +import Markdown from 'react-markdown' +import CodeBlock from '@theme/CodeBlock' + + +## Instructions Table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OpcodeNameSummaryBit-sizeExpression
0x00 [`ADD`](#isa-section-add)Addition (a + b)96{ + `M[dstOffset] = M[aOffset] + M[bOffset] mod 2^k` + }
0x01 [`SUB`](#isa-section-sub)Subtraction (a - b)96{ + `M[dstOffset] = M[aOffset] - M[bOffset] mod 2^k` + }
0x02 [`DIV`](#isa-section-div)Unsigned division (a / b)96{ + `M[dstOffset] = M[aOffset] / M[bOffset]` + }
0x03 [`EQ`](#isa-section-eq)Equality check (a == b)96{ + `M[dstOffset] = M[aOffset] == M[bOffset] ? 1 : 0` + }
0x04 [`LT`](#isa-section-lt)Less-than check (a < b)96{ + `M[dstOffset] = M[aOffset] < M[bOffset] ? 1 : 0` + }
0x05 [`LTE`](#isa-section-lte)Less-than-or-equals check (a <= b)96{ + `M[dstOffset] = M[aOffset] <= M[bOffset] ? 1 : 0` + }
0x06 [`AND`](#isa-section-and)Bitwise AND (a & b)96{ + `M[dstOffset] = M[aOffset] AND M[bOffset]` + }
0x07 [`OR`](#isa-section-or)Bitwise OR (a | b)96{ + `M[dstOffset] = M[aOffset] OR M[bOffset]` + }
0x08 [`XOR`](#isa-section-xor)Bitwise XOR (a ^ b)96{ + `M[dstOffset] = M[aOffset] XOR M[bOffset]` + }
0x09 [`NOT`](#isa-section-not)Bitwise NOT (inversion)72{ + `M[dstOffset] = NOT M[aOffset]` + }
0x0a [`SHL`](#isa-section-shl)Bitwise leftward shift (a << b)96{ + `M[dstOffset] = M[aOffset] << M[bOffset]` + }
0x0b [`SHR`](#isa-section-shr)Bitwise rightward shift (a >> b)96{ + `M[dstOffset] = M[aOffset] >> M[bOffset]` + }
0x0c [`SET`](#isa-section-set)Set a memory word from a constant in the bytecode.48+N{ + `M[dstOffset] = const` + }
0x0d [`MOV`](#isa-section-mov)Move a word from source memory location to destination`.64{ + `M[dstOffset] = M[srcOffset]` + }
0x0e [`CMOV`](#isa-section-cmov)Move a word (conditionally chosen) from one memory location to another (`d = cond > 0 ? a : b`).112{ + `M[dstOffset] = M[condOffset] > 0 ? M[aOffset] : M[bOffset]` + }
0x0f [`CAST`](#isa-section-cast)Type cast72{ + `M[dstOffset] = cast(M[aOffset])` + }
0x10 [`CALLDATACOPY`](#isa-section-calldatacopy)Copy calldata into memory.88{ + `M[dstOffset:dstOffset+size] = calldata[cdOffset:cdOffset+size]` + }
0x11 [`SLOAD`](#isa-section-sload)Load a word from storage.64{ + `M[dstOffset] = storage[M[slotOffset]]` + }
0x12 [`SSTORE`](#isa-section-sstore)Write a word to storage.64{ + `storage[M[slotOffset]] = M[srcOffset]` + }
0x13 [`L1L2MSGLOAD`](#isa-section-l1l2msgload)Retrieve an L1-to-L2 message by key136 +{`{ + M[dstMsgOffset], + M[dstSibPathOffset], + M[dstLeafIndexOffset], + M[dstRootOffset] +} = getL1ToL2Message(M[keyOffset])`} +
0x14 [`SENDL1TOL2MSG`](#isa-section-sendl2tol1msg)Retrieve an L1-to-L2 message by key136 +{`{ + M[dstMsgOffset], + M[dstSibPathOffset], + M[dstLeafIndexOffset], + M[dstRootOffset] +} = getL1ToL2Message(M[keyOffset])`} +
0x15 [`JUMP`](#isa-section-jump)Jump to a location in the bytecode.40{ + `PC = loc` + }
0x16 [`JUMPI`](#isa-section-jumpi)Conditionally jump to a location in the bytecode.64{ + `PC = M[condOffset] > 0 ? loc : PC` + }
0x17 [`RETURN`](#isa-section-return)Halt execution with `success`, optionally returning some data.64{ + `return(M[offset:offset+size])` + }
0x18 [`REVERT`](#isa-section-revert)Halt execution with `failure`, optionally returning some data.64{ + `revert(M[offset:offset+size])` + }
0x19 [`CALL`](#isa-section-call)Call into another contract.208 +{`M[successOffset] = call( + M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[argsOffset], M[argsSize], + M[retOffset], M[retSize])`} +
0x1a [`STATICCALL`](#isa-section-staticcall)Call into another contract, disallowing persistent state modifications.208 +{`M[successOffset] = staticcall( + M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[argsOffset], M[argsSize], + M[retOffset], M[retSize])`} +
0x1b [`ULOG`](#isa-section-ulog)Emit an unencrypted log with data from the `field` memory page64{ + `ulog(M[offset:offset+size])` + }
0x1c [`CHAINID`](#isa-section-chainid)Get this rollup's L1 chain ID40{ + `M[dstOffset] = Globals.chainId` + }
0x1d [`VERSION`](#isa-section-version)Get this rollup's L2 version ID40{ + `M[dstOffset] = Globals.version` + }
0x1e [`BLOCKNUMBER`](#isa-section-blocknumber)Get this block's number40{ + `M[dstOffset] = Globals.blocknumber` + }
0x1f [`TIMESTAMP`](#isa-section-timestamp)Get this L2 block's timestamp40{ + `M[dstOffset] = Globals.timestamp` + }
0x20 [`COINBASE`](#isa-section-coinbase)Get the block's beneficiary address40{ + `M[dstOffset] = Globals.coinbase` + }
0x21 [`BLOCKL1GASLIMIT`](#isa-section-blockl1gaslimit)Total amount of "L1 gas" that a block can consume40{ + `M[dstOffset] = Globals.l1GasLimit` + }
0x22 [`BLOCKL2GASLIMIT`](#isa-section-blockl2gaslimit)Total amount of "L2 gas" that a block can consume40{ + `M[dstOffset] = Globals.l2GasLimit` + }
0x23 [`NOTESROOT`](#isa-section-notesroot)Get the historical note-hash tree root as of the specified block number.64{ + `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].note_hash_tree_root` + }
0x24 [`NULLIFIERSROOT`](#isa-section-nullroot)Get the historical nullifier tree root as of the specified block number.64{ + `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].nullifier_tree_root` + }
0x25 [`CONTRACTSROOT`](#isa-section-contractsroot)Get the historical contracts tree root as of the specified block number.64{ + `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].contracts_tree_root` + }
0x26 [`MSGSROOT`](#isa-section-msgsroot)Get the historical l1-to-l2 messages tree root as of the specified block number.64{ + `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].l1_to_l2_messages_tree_root` + }
0x27 [`BLOCKSROOT`](#isa-section-blocksroot)Get the historical blocks tree root as of the specified block number.64{ + `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].blocks_tree_root` + }
0x28 [`PUBLICDATAROOT`](#isa-section-publicdataroot)Get the historical public data tree root as of the specified block number.64{ + `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].public_data_tree_root` + }
0x29 [`GLOBALSHASH`](#isa-section-globalshash)Get the historical global variables hash as of the specified block number.64{ + `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].global_variables_hash` + }
0x2a [`ORIGIN`](#isa-section-origin)Get the transaction's origination address40{ + `M[dstOffset] = TxContext.origin` + }
0x2b [`REFUNDEE`](#isa-section-refundee)The recipient of fee refunds for this transaction40{ + `M[dstOffset] = TxContext.refundee` + }
0x2c [`FEEPERL1GAS`](#isa-section-feeperl1gas)The fee to be paid per "L1 gas" - set by the transaction's original caller40{ + `M[dstOffset] = TxContext.feePerL1Gas` + }
0x2d [`FEEPERL2GAS`](#isa-section-feeperl2gas)The fee to be paid per "L2 gas" - set by the transaction's original caller40{ + `M[dstOffset] = TxContext.feePerL2Gas` + }
0x2e [`CALLER`](#isa-section-caller)Get the address of the sender (the caller's context)40{ + `M[dstOffset] = CallContext.sender` + }
0x2f [`ADDRESS`](#isa-section-address)Get the address of the currently executing l2 contract40{ + `M[dstOffset] = CallContext.storageContractAddress` + }
0x30 [`PORTAL`](#isa-section-portal)Get the address of the l1 portal contract40{ + `M[dstOffset] = CallContext.portalAddress` + }
0x31 [`CALLDEPTH`](#isa-section-calldepth)Get how many calls deep the current call context is40{ + `M[dstOffset] = CallContext.calldepth` + }
0x32 [`L1GAS`](#isa-section-l1gas)Remaining "L1 gas" for this call (after this instruction).40{ + `M[dstOffset] = LatestContext.l1Gas` + }
0x33 [`L2GAS`](#isa-section-l2gas)Remaining "L2 gas" for this call (after this instruction).40{ + `M[dstOffset] = LatestContext.l2Gas` + }
+ + +## Instructions + +### `ADD` (0x00) +Addition (a + b) + +[See in table.](#isa-table-add) + +- **Category**: arithmetic +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] + M[bOffset] mod 2^k` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/ADD.png) + +### `SUB` (0x01) +Subtraction (a - b) + +[See in table.](#isa-table-sub) + +- **Category**: arithmetic +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] - M[bOffset] mod 2^k` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/SUB.png) + +### `DIV` (0x02) +Unsigned division (a / b) + +[See in table.](#isa-table-div) + +- **Category**: arithmetic +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] / M[bOffset]` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/DIV.png) + +### `EQ` (0x03) +Equality check (a == b) + +[See in table.](#isa-table-eq) + +- **Category**: conditional +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] == M[bOffset] ? 1 : 0` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/EQ.png) + +### `LT` (0x04) +Less-than check (a < b) + +[See in table.](#isa-table-lt) + +- **Category**: conditional +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] < M[bOffset] ? 1 : 0` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/LT.png) + +### `LTE` (0x05) +Less-than-or-equals check (a <= b) + +[See in table.](#isa-table-lte) + +- **Category**: conditional +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] <= M[bOffset] ? 1 : 0` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/LTE.png) + +### `AND` (0x06) +Bitwise AND (a & b) + +[See in table.](#isa-table-and) + +- **Category**: bitwise +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] AND M[bOffset]` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/AND.png) + +### `OR` (0x07) +Bitwise OR (a | b) + +[See in table.](#isa-table-or) + +- **Category**: bitwise +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] OR M[bOffset]` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/OR.png) + +### `XOR` (0x08) +Bitwise XOR (a ^ b) + +[See in table.](#isa-table-xor) + +- **Category**: bitwise +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] XOR M[bOffset]` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/XOR.png) + +### `NOT` (0x09) +Bitwise NOT (inversion) + +[See in table.](#isa-table-not) + +- **Category**: bitwise +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = NOT M[aOffset]` +- **Tag checks**: `T[aOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 72 + +![](./images/bit-formats/NOT.png) + +### `SHL` (0x0a) +Bitwise leftward shift (a << b) + +[See in table.](#isa-table-shl) + +- **Category**: bitwise +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] << M[bOffset]` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/SHL.png) + +### `SHR` (0x0b) +Bitwise rightward shift (a >> b) + +[See in table.](#isa-table-shr) + +- **Category**: bitwise +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. +- **Args**: + - **aOffset**: memory offset of the operation's left input + - **bOffset**: memory offset of the operation's right input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[aOffset] >> M[bOffset]` +- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 96 + +![](./images/bit-formats/SHR.png) + +### `SET` (0x0c) +Set a memory word from a constant in the bytecode. + +[See in table.](#isa-table-set) + +- **Category**: memory +- **Flags**: + - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. `field` type is NOT supported for SET. +- **Args**: + - **const**: a constant value from the bytecode to store in memory (any type except `field`) + - **dstOffset**: memory offset specifying where to store the constant +- **Expression**: `M[dstOffset] = const` +- **Details**: Set memory word at `dstOffset` to `const`'s immediate value. `const` _cannot be `field` type_! +- **Tag updates**: `T[dstOffset] = op-type` +- **Bit-size**: 48+N + +![](./images/bit-formats/SET.png) + +### `MOV` (0x0d) +Move a word from source memory location to destination`. + +[See in table.](#isa-table-mov) + +- **Category**: memory +- **Args**: + - **srcOffset**: memory offset of word to move + - **dstOffset**: memory offset specifying where to store that word +- **Expression**: `M[dstOffset] = M[srcOffset]` +- **Tag updates**: `T[dstOffset] = T[srcOffset]` +- **Bit-size**: 64 + +![](./images/bit-formats/MOV.png) + +### `CMOV` (0x0e) +Move a word (conditionally chosen) from one memory location to another (`d = cond > 0 ? a : b`). + +[See in table.](#isa-table-cmov) + +- **Category**: memory +- **Args**: + - **aOffset**: memory offset of word 'a' to conditionally move + - **bOffset**: memory offset of word 'b' to conditionally move + - **condOffset**: memory offset of the operations 'conditional' input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = M[condOffset] > 0 ? M[aOffset] : M[bOffset]` +- **Details**: One of two source memory locations is chosen based on the condition. `T[condOffset]` is not checked because the greater-than-zero suboperation is the same regardless of type. +- **Tag updates**: `T[dstOffset] = M[condOffset] > 0 ? T[aOffset] : T[bOffset]` +- **Bit-size**: 112 + +![](./images/bit-formats/CMOV.png) + +### `CAST` (0x0f) +Type cast + +[See in table.](#isa-table-cast) + +- **Category**: types +- **Flags**: + - **dest-type**: The [type/size](./Types) to tag the output with when different from `op-type`. +- **Args**: + - **aOffset**: memory offset of word to cast + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = cast(M[aOffset])` +- **Details**: Cast a word in memory based on the `dest-type` specified in the bytecode. Truncates when casting to a smaller type, left-zero-pads when casting to a larger type. +- **Tag updates**: `T[dstOffset] = dest-type` +- **Bit-size**: 72 + +![](./images/bit-formats/CAST.png) + +### `CALLDATACOPY` (0x10) +Copy calldata into memory. + +[See in table.](#isa-table-calldatacopy) + +- **Category**: contract calls +- **Args**: + - **cdOffset**: offset into calldata to copy from + - **size**: number of words to copy + - **dstOffset**: memory offset specifying where to copy the first word to +- **Expression**: `M[dstOffset:dstOffset+size] = calldata[cdOffset:cdOffset+size]` +- **Details**: Calldata is read-only and cannot be directly operated on by other instructions. This instruction moves words from calldata into memory so they can be operated on normally. +- **Tag updates**: `T[dstOffset:dstOffset+size] = field` +- **Bit-size**: 88 + +![](./images/bit-formats/CALLDATACOPY.png) + +### `SLOAD` (0x11) +Load a word from storage. + +[See in table.](#isa-table-sload) + +- **Category**: storage & messaging +- **Args**: + - **slotOffset**: memory offset of the storage slot to load from + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = storage[M[slotOffset]]` +- **Details**: Load a word from this contract's persistent public storage into memory. +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 64 + +![](./images/bit-formats/SLOAD.png) + +### `SSTORE` (0x12) +Write a word to storage. + +[See in table.](#isa-table-sstore) + +- **Category**: storage & messaging +- **Args**: + - **srcOffset**: memory offset of the word to store + - **slotOffset**: memory offset containing the storage slot to store to +- **Expression**: `storage[M[slotOffset]] = M[srcOffset]` +- **Details**: Store a word from memory into this contract's persistent public storage. +- **Bit-size**: 64 + +![](./images/bit-formats/SSTORE.png) + +### `L1L2MSGLOAD` (0x13) +Retrieve an L1-to-L2 message by key + +[See in table.](#isa-table-l1l2msgload) + +- **Category**: storage & messaging +- **Args**: + - **keyOffset**: memory offset of the message key + - **dstMsgOffset**: memory offset specifying where to store the `L1_TO_L2_MESSAGE_LENGTH` words of the retrieved message + - **dstSibPathOffset**: memory offset specifying where to store the `L1_TO_L2_MSG_TREE_HEIGHT` words of the retrieved message's sibling path + - **dstLeafIndexOffset**: memory offset specifying where to store the retrieved message's leaf index + - **dstRootOffset**: memory offset specifying where to store the retrieved message tree root +- **Expression**: + +{`{ + M[dstMsgOffset], + M[dstSibPathOffset], + M[dstLeafIndexOffset], + M[dstRootOffset] +} = getL1ToL2Message(M[keyOffset])`} + +- **Tag updates**: `T[dst*Offset] = field` +- **Bit-size**: 136 + +![](./images/bit-formats/L1L2MSGLOAD.png) + +### `SENDL1TOL2MSG` (0x14) +Retrieve an L1-to-L2 message by key + +[See in table.](#isa-table-sendl2tol1msg) + +- **Category**: storage & messaging +- **Args**: + - **keyOffset**: memory offset of the message key + - **dstMsgOffset**: memory offset specifying where to store the `L1_TO_L2_MESSAGE_LENGTH` words of the retrieved message + - **dstSibPathOffset**: memory offset specifying where to store the `L1_TO_L2_MSG_TREE_HEIGHT` words of the retrieved message's sibling path + - **dstLeafIndexOffset**: memory offset specifying where to store the retrieved message's leaf index + - **dstRootOffset**: memory offset specifying where to store the retrieved message tree root +- **Expression**: + +{`{ + M[dstMsgOffset], + M[dstSibPathOffset], + M[dstLeafIndexOffset], + M[dstRootOffset] +} = getL1ToL2Message(M[keyOffset])`} + +- **Tag updates**: `T[dst*Offset] = field` +- **Bit-size**: 136 + +![](./images/bit-formats/SENDL1TOL2MSG.png) + +### `JUMP` (0x15) +Jump to a location in the bytecode. + +[See in table.](#isa-table-jump) + +- **Category**: control +- **Args**: + - **loc**: target location to jump to +- **Expression**: `PC = loc` +- **Details**: Target location is an immediate value (a constant in the bytecode). +- **Bit-size**: 40 + +![](./images/bit-formats/JUMP.png) + +### `JUMPI` (0x16) +Conditionally jump to a location in the bytecode. + +[See in table.](#isa-table-jumpi) + +- **Category**: control +- **Args**: + - **loc**: target location conditionally jump to + - **condOffset**: memory offset of the operations 'conditional' input +- **Expression**: `PC = M[condOffset] > 0 ? loc : PC` +- **Details**: Target location is an immediate value (a constant in the bytecode). `T[condOffset]` is not checked because the greater-than-zero suboperation is the same regardless of type. +- **Bit-size**: 64 + +![](./images/bit-formats/JUMPI.png) + +### `RETURN` (0x17) +Halt execution with `success`, optionally returning some data. + +[See in table.](#isa-table-return) + +- **Category**: contract calls +- **Args**: + - **offset**: memory offset of first word to return + - **size**: number of words to return +- **Expression**: `return(M[offset:offset+size])` +- **Details**: Return control flow to the calling context/contract. +- **Bit-size**: 64 + +![](./images/bit-formats/RETURN.png) + +### `REVERT` (0x18) +Halt execution with `failure`, optionally returning some data. + +[See in table.](#isa-table-revert) + +- **Category**: contract calls +- **Args**: + - **offset**: memory offset of first word to return + - **size**: number of words to return +- **Expression**: `revert(M[offset:offset+size])` +- **Details**: Return control flow to the calling context/contract. +- **Bit-size**: 64 + +![](./images/bit-formats/REVERT.png) + +### `CALL` (0x19) +Call into another contract. + +[See in table.](#isa-table-call) + +- **Category**: contract calls +- **Args**: + - **l1GasOffset**: amount of L1 gas to provide to the callee + - **l2GasOffset**: amount of L2 gas to provide to the callee + - **addrOffset**: address of the contract to call + - **argsOffset**: memory offset to args (will become the callee's calldata) + - **argsSize**: number of words to pass via callee's calldata + - **retOffset**: destination memory offset specifying where to store the data returned from the callee + - **retSize**: number of words to copy from data returned by callee + - **successOffset**: destination memory offset specifying where to store the call's success (0: failure, 1: success) +- **Expression**: + +{`M[successOffset] = call( + M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[argsOffset], M[argsSize], + M[retOffset], M[retSize])`} + +- **Details**: Creates a new CallContext, triggers execution of the corresponding contract code, + and then resumes execution in the current CallContext. A non-existent contract or one + with no code will return success. Nested call has an incremented `CallContext.calldepth`. +- **Tag checks**: `T[l1GasOffset] == T[l2GasOffset] == u32` +- **Tag updates**: + +{`T[successOffset] = u8 +T[retOffset:retOffset+retSize] = field`} + +- **Bit-size**: 208 + +![](./images/bit-formats/CALL.png) + +### `STATICCALL` (0x1a) +Call into another contract, disallowing persistent state modifications. + +[See in table.](#isa-table-staticcall) + +- **Category**: contract calls +- **Args**: + - **l1GasOffset**: amount of L1 gas to provide to the callee + - **l2GasOffset**: amount of L2 gas to provide to the callee + - **addrOffset**: address of the contract to call + - **argsOffset**: memory offset to args (will become the callee's calldata) + - **argsSize**: number of words to pass via callee's calldata + - **retOffset**: destination memory offset specifying where to store the data returned from the callee + - **retSize**: number of words to copy from data returned by callee + - **successOffset**: destination memory offset specifying where to store the call's success (0: failure, 1: success) +- **Expression**: + +{`M[successOffset] = staticcall( + M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[argsOffset], M[argsSize], + M[retOffset], M[retSize])`} + +- **Details**: Same as `CALL`, but the callee is cannot modify persistent state. Disallowed instructions are `SSTORE`, `ULOG`, `CALL`. +- **Tag checks**: `T[l1GasOffset] == T[l2GasOffset] == u32` +- **Tag updates**: + +{`T[successOffset] = u8 +T[retOffset:retOffset+retSize] = field`} + +- **Bit-size**: 208 + +![](./images/bit-formats/STATICCALL.png) + +### `ULOG` (0x1b) +Emit an unencrypted log with data from the `field` memory page + +[See in table.](#isa-table-ulog) + +- **Category**: logging +- **Args**: + - **offset**: memory offset of the data to log + - **size**: number of words to log +- **Expression**: `ulog(M[offset:offset+size])` +- **Bit-size**: 64 + +![](./images/bit-formats/ULOG.png) + +### `CHAINID` (0x1c) +Get this rollup's L1 chain ID + +[See in table.](#isa-table-chainid) + +- **Category**: block info +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = Globals.chainId` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/CHAINID.png) + +### `VERSION` (0x1d) +Get this rollup's L2 version ID + +[See in table.](#isa-table-version) + +- **Category**: block info +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = Globals.version` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/VERSION.png) + +### `BLOCKNUMBER` (0x1e) +Get this block's number + +[See in table.](#isa-table-blocknumber) + +- **Category**: block info +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = Globals.blocknumber` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/BLOCKNUMBER.png) + +### `TIMESTAMP` (0x1f) +Get this L2 block's timestamp + +[See in table.](#isa-table-timestamp) + +- **Category**: block info +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = Globals.timestamp` +- **Tag updates**: `T[dstOffset] = u64` +- **Bit-size**: 40 + +![](./images/bit-formats/TIMESTAMP.png) + +### `COINBASE` (0x20) +Get the block's beneficiary address + +[See in table.](#isa-table-coinbase) + +- **Category**: block info +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = Globals.coinbase` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/COINBASE.png) + +### `BLOCKL1GASLIMIT` (0x21) +Total amount of "L1 gas" that a block can consume + +[See in table.](#isa-table-blockl1gaslimit) + +- **Category**: block info +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = Globals.l1GasLimit` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/BLOCKL1GASLIMIT.png) + +### `BLOCKL2GASLIMIT` (0x22) +Total amount of "L2 gas" that a block can consume + +[See in table.](#isa-table-blockl2gaslimit) + +- **Category**: block info +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = Globals.l2GasLimit` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/BLOCKL2GASLIMIT.png) + +### `NOTESROOT` (0x23) +Get the historical note-hash tree root as of the specified block number. + +[See in table.](#isa-table-notesroot) + +- **Category**: historical access +- **Args**: + - **blockNumOffset**: memory offset of the block number input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].note_hash_tree_root` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 64 + +![](./images/bit-formats/NOTESROOT.png) + +### `NULLIFIERSROOT` (0x24) +Get the historical nullifier tree root as of the specified block number. + +[See in table.](#isa-table-nullroot) + +- **Category**: historical access +- **Args**: + - **blockNumOffset**: memory offset of the block number input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].nullifier_tree_root` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 64 + +![](./images/bit-formats/NULLIFIERSROOT.png) + +### `CONTRACTSROOT` (0x25) +Get the historical contracts tree root as of the specified block number. + +[See in table.](#isa-table-contractsroot) + +- **Category**: historical access +- **Args**: + - **blockNumOffset**: memory offset of the block number input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].contracts_tree_root` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 64 + +![](./images/bit-formats/CONTRACTSROOT.png) + +### `MSGSROOT` (0x26) +Get the historical l1-to-l2 messages tree root as of the specified block number. + +[See in table.](#isa-table-msgsroot) + +- **Category**: historical access +- **Args**: + - **blockNumOffset**: memory offset of the block number input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].l1_to_l2_messages_tree_root` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 64 + +![](./images/bit-formats/MSGSROOT.png) + +### `BLOCKSROOT` (0x27) +Get the historical blocks tree root as of the specified block number. + +[See in table.](#isa-table-blocksroot) + +- **Category**: historical access +- **Args**: + - **blockNumOffset**: memory offset of the block number input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].blocks_tree_root` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 64 + +![](./images/bit-formats/BLOCKSROOT.png) + +### `PUBLICDATAROOT` (0x28) +Get the historical public data tree root as of the specified block number. + +[See in table.](#isa-table-publicdataroot) + +- **Category**: historical access +- **Args**: + - **blockNumOffset**: memory offset of the block number input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].public_data_tree_root` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 64 + +![](./images/bit-formats/PUBLICDATAROOT.png) + +### `GLOBALSHASH` (0x29) +Get the historical global variables hash as of the specified block number. + +[See in table.](#isa-table-globalshash) + +- **Category**: historical access +- **Args**: + - **blockNumOffset**: memory offset of the block number input + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].global_variables_hash` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 64 + +![](./images/bit-formats/GLOBALSHASH.png) + +### `ORIGIN` (0x2a) +Get the transaction's origination address + +[See in table.](#isa-table-origin) + +- **Category**: tx context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = TxContext.origin` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/ORIGIN.png) + +### `REFUNDEE` (0x2b) +The recipient of fee refunds for this transaction + +[See in table.](#isa-table-refundee) + +- **Category**: tx context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = TxContext.refundee` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/REFUNDEE.png) + +### `FEEPERL1GAS` (0x2c) +The fee to be paid per "L1 gas" - set by the transaction's original caller + +[See in table.](#isa-table-feeperl1gas) + +- **Category**: tx context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = TxContext.feePerL1Gas` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/FEEPERL1GAS.png) + +### `FEEPERL2GAS` (0x2d) +The fee to be paid per "L2 gas" - set by the transaction's original caller + +[See in table.](#isa-table-feeperl2gas) + +- **Category**: tx context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = TxContext.feePerL2Gas` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/FEEPERL2GAS.png) + +### `CALLER` (0x2e) +Get the address of the sender (the caller's context) + +[See in table.](#isa-table-caller) + +- **Category**: call context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = CallContext.sender` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/CALLER.png) + +### `ADDRESS` (0x2f) +Get the address of the currently executing l2 contract + +[See in table.](#isa-table-address) + +- **Category**: call context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = CallContext.storageContractAddress` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/ADDRESS.png) + +### `PORTAL` (0x30) +Get the address of the l1 portal contract + +[See in table.](#isa-table-portal) + +- **Category**: call context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = CallContext.portalAddress` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/PORTAL.png) + +### `CALLDEPTH` (0x31) +Get how many calls deep the current call context is + +[See in table.](#isa-table-calldepth) + +- **Category**: call context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = CallContext.calldepth` +- **Details**: Note: security issues with EVM's tx.origin can be resolved by asserting the `calldepth == 0`. +- **Tag updates**: `T[dstOffset] = u8` +- **Bit-size**: 40 + +![](./images/bit-formats/CALLDEPTH.png) + +### `L1GAS` (0x32) +Remaining "L1 gas" for this call (after this instruction). + +[See in table.](#isa-table-l1gas) + +- **Category**: latest context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = LatestContext.l1Gas` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/L1GAS.png) + +### `L2GAS` (0x33) +Remaining "L2 gas" for this call (after this instruction). + +[See in table.](#isa-table-l2gas) + +- **Category**: latest context +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = LatestContext.l2Gas` +- **Tag updates**: `T[dstOffset] = u32` +- **Bit-size**: 40 + +![](./images/bit-formats/L2GAS.png) diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/ADD.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/ADD.png new file mode 100644 index 00000000000..c358398a8d0 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/ADD.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/ADDRESS.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/ADDRESS.png new file mode 100644 index 00000000000..14fe371aec9 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/ADDRESS.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/AND.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/AND.png new file mode 100644 index 00000000000..c15ee272e57 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/AND.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL1GASLIMIT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL1GASLIMIT.png new file mode 100644 index 00000000000..74517313b12 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL1GASLIMIT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL2GASLIMIT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL2GASLIMIT.png new file mode 100644 index 00000000000..816a84cb99d Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL2GASLIMIT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKNUMBER.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKNUMBER.png new file mode 100644 index 00000000000..267651b6800 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKNUMBER.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKSROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKSROOT.png new file mode 100644 index 00000000000..aea3d00f76b Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKSROOT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CALL.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALL.png new file mode 100644 index 00000000000..9bc0b671d99 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALL.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLDATACOPY.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLDATACOPY.png new file mode 100644 index 00000000000..0f5c08b1e9a Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLDATACOPY.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLDEPTH.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLDEPTH.png new file mode 100644 index 00000000000..1981867b5cb Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLDEPTH.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLER.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLER.png new file mode 100644 index 00000000000..323e2869b8e Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLER.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CAST.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CAST.png new file mode 100644 index 00000000000..8767543b69f Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/CAST.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CHAINID.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CHAINID.png new file mode 100644 index 00000000000..205a27674f1 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/CHAINID.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CMOV.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CMOV.png new file mode 100644 index 00000000000..51dfd7940b1 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/CMOV.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/COINBASE.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/COINBASE.png new file mode 100644 index 00000000000..2589a8a960e Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/COINBASE.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CONTRACTSROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CONTRACTSROOT.png new file mode 100644 index 00000000000..825ee2a8ff8 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/CONTRACTSROOT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/DIV.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/DIV.png new file mode 100644 index 00000000000..423a4a91fc2 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/DIV.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/EQ.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/EQ.png new file mode 100644 index 00000000000..74d09db42e4 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/EQ.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/FEEPERL1GAS.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/FEEPERL1GAS.png new file mode 100644 index 00000000000..e260a83ce7a Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/FEEPERL1GAS.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/FEEPERL2GAS.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/FEEPERL2GAS.png new file mode 100644 index 00000000000..6dff4ec7c46 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/FEEPERL2GAS.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/GLOBALSHASH.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/GLOBALSHASH.png new file mode 100644 index 00000000000..5737a56dba1 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/GLOBALSHASH.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMP.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMP.png new file mode 100644 index 00000000000..0d0f8134210 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMP.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMPI.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMPI.png new file mode 100644 index 00000000000..2adb94316c1 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMPI.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/L1GAS.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/L1GAS.png new file mode 100644 index 00000000000..e3236ec81c5 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/L1GAS.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/L1L2MSGLOAD.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/L1L2MSGLOAD.png new file mode 100644 index 00000000000..cd1607fbc82 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/L1L2MSGLOAD.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/L2GAS.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/L2GAS.png new file mode 100644 index 00000000000..c102ee0b00c Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/L2GAS.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/LT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/LT.png new file mode 100644 index 00000000000..296fee5bffd Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/LT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/LTE.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/LTE.png new file mode 100644 index 00000000000..e5d827599fc Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/LTE.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/MOV.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/MOV.png new file mode 100644 index 00000000000..cbdb367bd31 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/MOV.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/MSGSROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/MSGSROOT.png new file mode 100644 index 00000000000..105f39b35a1 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/MSGSROOT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/NOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/NOT.png new file mode 100644 index 00000000000..04b09f59fe8 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/NOT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/NOTESROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/NOTESROOT.png new file mode 100644 index 00000000000..b6617e00135 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/NOTESROOT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/NULLIFIERSROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/NULLIFIERSROOT.png new file mode 100644 index 00000000000..6838aab5871 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/NULLIFIERSROOT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/OR.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/OR.png new file mode 100644 index 00000000000..e5e7f27c121 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/OR.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/ORIGIN.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/ORIGIN.png new file mode 100644 index 00000000000..2bb544c40ad Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/ORIGIN.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/PORTAL.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/PORTAL.png new file mode 100644 index 00000000000..ec89242e8aa Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/PORTAL.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/PUBLICDATAROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/PUBLICDATAROOT.png new file mode 100644 index 00000000000..18a258a7ed5 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/PUBLICDATAROOT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/REFUNDEE.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/REFUNDEE.png new file mode 100644 index 00000000000..5d64c008157 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/REFUNDEE.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/RETURN.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/RETURN.png new file mode 100644 index 00000000000..b99c0eb1e5f Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/RETURN.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/REVERT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/REVERT.png new file mode 100644 index 00000000000..0ae2c7b02fd Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/REVERT.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SENDL1TOL2MSG.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SENDL1TOL2MSG.png new file mode 100644 index 00000000000..f3a2d7a1aa8 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/SENDL1TOL2MSG.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SET.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SET.png new file mode 100644 index 00000000000..1618117fa07 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/SET.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SHL.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SHL.png new file mode 100644 index 00000000000..19879901d91 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/SHL.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SHR.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SHR.png new file mode 100644 index 00000000000..386b94cffcf Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/SHR.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SLOAD.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SLOAD.png new file mode 100644 index 00000000000..c50843c3d98 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/SLOAD.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SSTORE.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SSTORE.png new file mode 100644 index 00000000000..fa07fbf2d95 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/SSTORE.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/STATICCALL.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/STATICCALL.png new file mode 100644 index 00000000000..3ca1b7c35c1 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/STATICCALL.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SUB.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SUB.png new file mode 100644 index 00000000000..c92598d9243 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/SUB.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/TIMESTAMP.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/TIMESTAMP.png new file mode 100644 index 00000000000..37009075b51 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/TIMESTAMP.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/ULOG.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/ULOG.png new file mode 100644 index 00000000000..5a872ebc893 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/ULOG.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/VERSION.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/VERSION.png new file mode 100644 index 00000000000..b96b8ee5a83 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/VERSION.png differ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/XOR.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/XOR.png new file mode 100644 index 00000000000..d6d4e80c525 Binary files /dev/null and b/yellow-paper/docs/public-vm/gen/images/bit-formats/XOR.png differ diff --git a/yellow-paper/package.json b/yellow-paper/package.json index ad92226d9ad..4e2bf4503ee 100644 --- a/yellow-paper/package.json +++ b/yellow-paper/package.json @@ -4,13 +4,14 @@ "private": true, "scripts": { "docusaurus": "docusaurus", - "start": "docusaurus start", - "start:dev": "docusaurus start --host 0.0.0.0", + "start": "yarn preprocess && docusaurus start", + "start:dev": "yarn preprocess && docusaurus start --host 0.0.0.0", "build": "docusaurus build", "swizzle": "docusaurus swizzle", "deploy": "docusaurus deploy", "clear": "docusaurus clear", "serve": "docusaurus serve", + "preprocess": "yarn node ./src/preprocess/index.js", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", "typecheck": "tsc" @@ -23,6 +24,7 @@ "prism-react-renderer": "^1.3.5", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-markdown": "6.0.0", "rehype-katex": "5", "remark-math": "3" }, diff --git a/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js b/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js new file mode 100644 index 00000000000..176c852e677 --- /dev/null +++ b/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js @@ -0,0 +1,979 @@ +const {instructionSize} = require('./InstructionSize'); + +const TOPICS_IN_TABLE = [ + "Name", "Summary", "Bit-size", "Expression", +]; +const TOPICS_IN_SECTIONS = [ + "Name", "Summary", "Category", "Flags", "Args", "Expression", "Details", "Tag checks", "Tag updates", "Bit-size", +]; + +const OP_TYPE_DESCRIPTION = "The [type/size](./Types) to check inputs against and tag the output with."; +const DEST_TYPE_DESCRIPTION = "The [type/size](./Types) to tag the output with when different from `op-type`."; + +const INSTRUCTION_SET_RAW = [ + { + "id": "add", + "Name": "`ADD`", + "Category": "arithmetic", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] + M[bOffset] mod 2^k`", + "Summary": "Addition (a + b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "sub", + "Name": "`SUB`", + "Category": "arithmetic", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] - M[bOffset] mod 2^k`", + "Summary": "Subtraction (a - b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "div", + "Name": "`DIV`", + "Category": "arithmetic", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] / M[bOffset]`", + "Summary": "Unsigned division (a / b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "eq", + "Name": "`EQ`", + "Category": "conditional", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result", "type": "u8"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] == M[bOffset] ? 1 : 0`", + "Summary": "Equality check (a == b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "lt", + "Name": "`LT`", + "Category": "conditional", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result", "type": "u8"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] < M[bOffset] ? 1 : 0`", + "Summary": "Less-than check (a < b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "lte", + "Name": "`LTE`", + "Category": "conditional", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result", "type": "u8"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] <= M[bOffset] ? 1 : 0`", + "Summary": "Less-than-or-equals check (a <= b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "and", + "Name": "`AND`", + "Category": "bitwise", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] AND M[bOffset]`", + "Summary": "Bitwise AND (a & b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "or", + "Name": "`OR`", + "Category": "bitwise", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] OR M[bOffset]`", + "Summary": "Bitwise OR (a | b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "xor", + "Name": "`XOR`", + "Category": "bitwise", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] XOR M[bOffset]`", + "Summary": "Bitwise XOR (a ^ b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "not", + "Name": "`NOT`", + "Category": "bitwise", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = NOT M[aOffset]`", + "Summary": "Bitwise NOT (inversion)", + "Details": "", + "Tag checks": "`T[aOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "shl", + "Name": "`SHL`", + "Category": "bitwise", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] << M[bOffset]`", + "Summary": "Bitwise leftward shift (a << b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "shr", + "Name": "`SHR`", + "Category": "bitwise", + "Flags": [ + {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + ], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of the operation's left input"}, + {"name": "bOffset", "description": "memory offset of the operation's right input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[aOffset] >> M[bOffset]`", + "Summary": "Bitwise rightward shift (a >> b)", + "Details": "", + "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "set", + "Name": "`SET`", + "Category": "memory", + "Flags": [ + {"name": "op-type", "description": "The [type/size](./Types) to check inputs against and tag the output with. `field` type is NOT supported for SET."}, + ], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "const", "description": "a constant value from the bytecode to store in memory (any type except `field`)", "mode": "immediate"}, + {"name": "dstOffset", "description": "memory offset specifying where to store the constant"}, + ], + "Expression": "`M[dstOffset] = const`", + "Summary": "Set a memory word from a constant in the bytecode.", + "Details": "Set memory word at `dstOffset` to `const`'s immediate value. `const` _cannot be `field` type_!", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = op-type`", + }, + { + "id": "mov", + "Name": "`MOV`", + "Category": "memory", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "srcOffset", "description": "memory offset of word to move"}, + {"name": "dstOffset", "description": "memory offset specifying where to store that word"}, + ], + "Expression": "`M[dstOffset] = M[srcOffset]`", + "Summary": "Move a word from source memory location to destination`.", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = T[srcOffset]`", + }, + { + "id": "cmov", + "Name": "`CMOV`", + "Category": "memory", + "Flags": [], + "#memreads": "3", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of word 'a' to conditionally move"}, + {"name": "bOffset", "description": "memory offset of word 'b' to conditionally move"}, + {"name": "condOffset", "description": "memory offset of the operations 'conditional' input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = M[condOffset] > 0 ? M[aOffset] : M[bOffset]`", + "Summary": "Move a word (conditionally chosen) from one memory location to another (`d = cond > 0 ? a : b`).", + "Details": "One of two source memory locations is chosen based on the condition. `T[condOffset]` is not checked because the greater-than-zero suboperation is the same regardless of type.", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = M[condOffset] > 0 ? T[aOffset] : T[bOffset]`", + }, + { + "id": "cast", + "Name": "`CAST`", + "Category": "types", + "Flags": [ + {"name": "dest-type", "description": DEST_TYPE_DESCRIPTION}, + ], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "aOffset", "description": "memory offset of word to cast"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = cast(M[aOffset])`", + "Summary": "Type cast", + "Details": "Cast a word in memory based on the `dest-type` specified in the bytecode. Truncates when casting to a smaller type, left-zero-pads when casting to a larger type.", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = dest-type`", + }, + { + "id": "calldatacopy", + "Name": "`CALLDATACOPY`", + "Category": "contract calls", + "Flags": [], + "#memreads": "`s1`", + "#memwrites": "`s1`", + "Args": [ + {"name": "cdOffset", "description": "offset into calldata to copy from"}, + {"name": "size", "description": "number of words to copy", "mode": "immediate", "type": "u24"}, + {"name": "dstOffset", "description": "memory offset specifying where to copy the first word to"}, + ], + "Expression": "`M[dstOffset:dstOffset+size] = calldata[cdOffset:cdOffset+size]`", + "Summary": "Copy calldata into memory.", + "Details": "Calldata is read-only and cannot be directly operated on by other instructions. This instruction moves words from calldata into memory so they can be operated on normally.", + "Tag checks": "", + "Tag updates": "`T[dstOffset:dstOffset+size] = field`", + }, + { + "id": "sload", + "Name": "`SLOAD`", + "Category": "storage & messaging", + "Flags": [], + "#memreads": "2", + "#memwrites": "1", + "Args": [ + {"name": "slotOffset", "description": "memory offset of the storage slot to load from"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = storage[M[slotOffset]]`", + "Summary": "Load a word from storage.", + "Details": "Load a word from this contract's persistent public storage into memory.", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + "id": "sstore", + "Name": "`SSTORE`", + "Category": "storage & messaging", + "Flags": [], + "#memreads": "2", + "#memwrites": "0", + "Args": [ + {"name": "srcOffset", "description": "memory offset of the word to store"}, + {"name": "slotOffset", "description": "memory offset containing the storage slot to store to"}, + ], + "Expression": "`storage[M[slotOffset]] = M[srcOffset]`", + "Summary": "Write a word to storage.", + "Details": "Store a word from memory into this contract's persistent public storage.", + "Tag checks": "", + "Tag updates": "", + }, + { + "id": "l1l2msgload", + "Name": "`L1L2MSGLOAD`", + "Category": "storage & messaging", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "keyOffset", "description": "memory offset of the message key"}, + {"name": "dstMsgOffset", "description": "memory offset specifying where to store the `L1_TO_L2_MESSAGE_LENGTH` words of the retrieved message"}, + {"name": "dstSibPathOffset", "description": "memory offset specifying where to store the `L1_TO_L2_MSG_TREE_HEIGHT` words of the retrieved message's sibling path"}, + {"name": "dstLeafIndexOffset", "description": "memory offset specifying where to store the retrieved message's leaf index"}, + {"name": "dstRootOffset", "description": "memory offset specifying where to store the retrieved message tree root"}, + ], + "Expression": ` +{ + M[dstMsgOffset], + M[dstSibPathOffset], + M[dstLeafIndexOffset], + M[dstRootOffset] +} = getL1ToL2Message(M[keyOffset]) +`, + "Summary": "Retrieve an L1-to-L2 message by key", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dst*Offset] = field`", + }, + { + "id": "sendl2tol1msg", + "Name": "`SENDL1TOL2MSG`", + "Category": "storage & messaging", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "keyOffset", "description": "memory offset of the message key"}, + {"name": "dstMsgOffset", "description": "memory offset specifying where to store the `L1_TO_L2_MESSAGE_LENGTH` words of the retrieved message"}, + {"name": "dstSibPathOffset", "description": "memory offset specifying where to store the `L1_TO_L2_MSG_TREE_HEIGHT` words of the retrieved message's sibling path"}, + {"name": "dstLeafIndexOffset", "description": "memory offset specifying where to store the retrieved message's leaf index"}, + {"name": "dstRootOffset", "description": "memory offset specifying where to store the retrieved message tree root"}, + ], + "Expression": ` +{ + M[dstMsgOffset], + M[dstSibPathOffset], + M[dstLeafIndexOffset], + M[dstRootOffset] +} = getL1ToL2Message(M[keyOffset]) +`, + "Summary": "Retrieve an L1-to-L2 message by key", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dst*Offset] = field`", + }, + { + "id": "jump", + "Name": "`JUMP`", + "Category": "control", + "Flags": [], + "#memreads": "0", + "#memwrites": "0", + "Args": [ + {"name": "loc", "description": "target location to jump to", "mode": "immediate", "type": "u24"}, + ], + "Expression": "`PC = loc`", + "Summary": "Jump to a location in the bytecode.", + "Details": "Target location is an immediate value (a constant in the bytecode).", + "Tag checks": "", + "Tag updates": "", + }, + { + "id": "jumpi", + "Name": "`JUMPI`", + "Category": "control", + "Flags": [], + "#memreads": "3", + "#memwrites": "0", + "Args": [ + {"name": "loc", "description": "target location conditionally jump to", "mode": "immediate", "type": "u24"}, + {"name": "condOffset", "description": "memory offset of the operations 'conditional' input"}, + ], + "Expression": "`PC = M[condOffset] > 0 ? loc : PC`", + "Summary": "Conditionally jump to a location in the bytecode.", + "Details": "Target location is an immediate value (a constant in the bytecode). `T[condOffset]` is not checked because the greater-than-zero suboperation is the same regardless of type.", + "Tag checks": "", + "Tag updates": "", + }, + { + "id": "return", + "Name": "`RETURN`", + "Category": "contract calls", + "Flags": [], + "#memreads": "`s1`", + "#memwrites": "0", + "Args": [ + {"name": "offset", "description": "memory offset of first word to return"}, + {"name": "size", "description": "number of words to return", "mode": "immediate", "type": "u24"}, + ], + "Expression": "`return(M[offset:offset+size])`", + "Summary": "Halt execution with `success`, optionally returning some data.", + "Details": "Return control flow to the calling context/contract.", + "Tag checks": "", + "Tag updates": "", + }, + { + "id": "revert", + "Name": "`REVERT`", + "Category": "contract calls", + "Flags": [], + "#memreads": "`s1`", + "#memwrites": "0", + "Args": [ + {"name": "offset", "description": "memory offset of first word to return"}, + {"name": "size", "description": "number of words to return", "mode": "immediate", "type": "u24"}, + ], + "Expression": "`revert(M[offset:offset+size])`", + "Summary": "Halt execution with `failure`, optionally returning some data.", + "Details": "Return control flow to the calling context/contract.", + "Tag checks": "", + "Tag updates": "", + }, + { + "id": "call", + "Name": "`CALL`", + "Category": "contract calls", + "Flags": [], + "#memreads": "5", + "#memwrites": "`1+retSize`", + "Args": [ + {"name": "l1GasOffset", "description": "amount of L1 gas to provide to the callee"}, + {"name": "l2GasOffset", "description": "amount of L2 gas to provide to the callee"}, + {"name": "addrOffset", "description": "address of the contract to call"}, + {"name": "argsOffset", "description": "memory offset to args (will become the callee's calldata)"}, + {"name": "argsSize", "description": "number of words to pass via callee's calldata", "mode": "immediate", "type": "u24"}, + {"name": "retOffset", "description": "destination memory offset specifying where to store the data returned from the callee"}, + {"name": "retSize", "description": "number of words to copy from data returned by callee", "mode": "immediate", "type": "u24"}, + {"name": "successOffset", "description": "destination memory offset specifying where to store the call's success (0: failure, 1: success)", "type": "u8"}, + ], + "Expression":` +M[successOffset] = call( + M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[argsOffset], M[argsSize], + M[retOffset], M[retSize]) +`, + "Summary": "Call into another contract.", + "Details": `Creates a new CallContext, triggers execution of the corresponding contract code, + and then resumes execution in the current CallContext. A non-existent contract or one + with no code will return success. Nested call has an incremented \`CallContext.calldepth\`.`, + "Tag checks": "`T[l1GasOffset] == T[l2GasOffset] == u32`", + "Tag updates": ` +T[successOffset] = u8 +T[retOffset:retOffset+retSize] = field +`, + }, + { + "id": "staticcall", + "Name": "`STATICCALL`", + "Category": "contract calls", + "Flags": [], + "#memreads": "5", + "#memwrites": "`1+retSize`", + "Args": [ + {"name": "l1GasOffset", "description": "amount of L1 gas to provide to the callee"}, + {"name": "l2GasOffset", "description": "amount of L2 gas to provide to the callee"}, + {"name": "addrOffset", "description": "address of the contract to call"}, + {"name": "argsOffset", "description": "memory offset to args (will become the callee's calldata)"}, + {"name": "argsSize", "description": "number of words to pass via callee's calldata", "mode": "immediate", "type": "u24"}, + {"name": "retOffset", "description": "destination memory offset specifying where to store the data returned from the callee"}, + {"name": "retSize", "description": "number of words to copy from data returned by callee", "mode": "immediate", "type": "u24"}, + {"name": "successOffset", "description": "destination memory offset specifying where to store the call's success (0: failure, 1: success)", "type": "u8"}, + ], + "Expression": ` +M[successOffset] = staticcall( + M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[argsOffset], M[argsSize], + M[retOffset], M[retSize]) +`, + "Summary": "Call into another contract, disallowing persistent state modifications.", + "Details": "Same as `CALL`, but the callee is cannot modify persistent state. Disallowed instructions are `SSTORE`, `ULOG`, `CALL`.", + "Tag checks": "`T[l1GasOffset] == T[l2GasOffset] == u32`", + "Tag updates": ` +T[successOffset] = u8 +T[retOffset:retOffset+retSize] = field +`, + }, + { + "id": "ulog", + "Name": "`ULOG`", + "Category": "logging", + "Flags": [], + "#memreads": "`s1`", + "#memwrites": "0", + "Args": [ + {"name": "offset", "description": "memory offset of the data to log"}, + {"name": "size", "description": "number of words to log", "mode": "immediate", "type": "u24"}, + ], + "Expression": "`ulog(M[offset:offset+size])`", + "Summary": "Emit an unencrypted log with data from the `field` memory page", + "Details": "", + "Tag checks": "", + "Tag updates": "", + }, + { + "id": "chainid", + "Name": "`CHAINID`", + "Category": "block info", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = Globals.chainId`", + "Summary": "Get this rollup's L1 chain ID", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "version", + "Name": "`VERSION`", + "Category": "block info", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = Globals.version`", + "Summary": "Get this rollup's L2 version ID", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "blocknumber", + "Name": "`BLOCKNUMBER`", + "Category": "block info", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = Globals.blocknumber`", + "Summary": "Get this block's number", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "timestamp", + "Name": "`TIMESTAMP`", + "Category": "block info", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = Globals.timestamp`", + "Summary": "Get this L2 block's timestamp", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u64`", + }, + { + "id": "coinbase", + "Name": "`COINBASE`", + "Category": "block info", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = Globals.coinbase`", + "Summary": "Get the block's beneficiary address", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "blockl1gaslimit", + "Name": "`BLOCKL1GASLIMIT`", + "Category": "block info", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = Globals.l1GasLimit`", + "Summary": "Total amount of \"L1 gas\" that a block can consume", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "blockl2gaslimit", + "Name": "`BLOCKL2GASLIMIT`", + "Category": "block info", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = Globals.l2GasLimit`", + "Summary": "Total amount of \"L2 gas\" that a block can consume", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "notesroot", + "Name": "`NOTESROOT`", + "Category": "historical access", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "blockNumOffset", "description": "memory offset of the block number input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].note_hash_tree_root`", + "Summary": "Get the historical note-hash tree root as of the specified block number.", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + "id": "nullroot", + "Name": "`NULLIFIERSROOT`", + "Category": "historical access", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "blockNumOffset", "description": "memory offset of the block number input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].nullifier_tree_root`", + "Summary": "Get the historical nullifier tree root as of the specified block number.", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + "id": "contractsroot", + "Name": "`CONTRACTSROOT`", + "Category": "historical access", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "blockNumOffset", "description": "memory offset of the block number input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].contracts_tree_root`", + "Summary": "Get the historical contracts tree root as of the specified block number.", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + "id": "msgsroot", + "Name": "`MSGSROOT`", + "Category": "historical access", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "blockNumOffset", "description": "memory offset of the block number input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].l1_to_l2_messages_tree_root`", + "Summary": "Get the historical l1-to-l2 messages tree root as of the specified block number.", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + "id": "blocksroot", + "Name": "`BLOCKSROOT`", + "Category": "historical access", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "blockNumOffset", "description": "memory offset of the block number input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].blocks_tree_root`", + "Summary": "Get the historical blocks tree root as of the specified block number.", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + "id": "publicdataroot", + "Name": "`PUBLICDATAROOT`", + "Category": "historical access", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "blockNumOffset", "description": "memory offset of the block number input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].public_data_tree_root`", + "Summary": "Get the historical public data tree root as of the specified block number.", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + "id": "globalshash", + "Name": "`GLOBALSHASH`", + "Category": "historical access", + "Flags": [], + "#memreads": "1", + "#memwrites": "1", + "Args": [ + {"name": "blockNumOffset", "description": "memory offset of the block number input"}, + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].global_variables_hash`", + "Summary": "Get the historical global variables hash as of the specified block number.", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + "id": "origin", + "Name": "`ORIGIN`", + "Category": "tx context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = TxContext.origin`", + "Summary": "Get the transaction's origination address", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "refundee", + "Name": "`REFUNDEE`", + "Category": "tx context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = TxContext.refundee`", + "Summary": "The recipient of fee refunds for this transaction", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "feeperl1gas", + "Name": "`FEEPERL1GAS`", + "Category": "tx context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = TxContext.feePerL1Gas`", + "Summary": "The fee to be paid per \"L1 gas\" - set by the transaction's original caller", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "feeperl2gas", + "Name": "`FEEPERL2GAS`", + "Category": "tx context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = TxContext.feePerL2Gas`", + "Summary": "The fee to be paid per \"L2 gas\" - set by the transaction's original caller", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "caller", + "Name": "`CALLER`", + "Category": "call context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = CallContext.sender`", + "Summary": "Get the address of the sender (the caller's context)", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "address", + "Name": "`ADDRESS`", + "Category": "call context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = CallContext.storageContractAddress`", + "Summary": "Get the address of the currently executing l2 contract", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "portal", + "Name": "`PORTAL`", + "Category": "call context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = CallContext.portalAddress`", + "Summary": "Get the address of the l1 portal contract", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "calldepth", + "Name": "`CALLDEPTH`", + "Category": "call context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = CallContext.calldepth`", + "Summary": "Get how many calls deep the current call context is", + "Details": "Note: security issues with EVM's tx.origin can be resolved by asserting the `calldepth == 0`.", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u8`", + }, + { + "id": "l1gas", + "Name": "`L1GAS`", + "Category": "latest context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = LatestContext.l1Gas`", + "Summary": "Remaining \"L1 gas\" for this call (after this instruction).", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, + { + "id": "l2gas", + "Name": "`L2GAS`", + "Category": "latest context", + "Flags": [], + "#memreads": "0", + "#memwrites": "1", + "Args": [ + {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, + ], + "Expression": "`M[dstOffset] = LatestContext.l2Gas`", + "Summary": "Remaining \"L2 gas\" for this call (after this instruction).", + "Details": "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = u32`", + }, +]; +const INSTRUCTION_SET = INSTRUCTION_SET_RAW.map((instr) => {instr['Bit-size'] = instructionSize(instr); return instr;}); + +module.exports = { + TOPICS_IN_TABLE, + TOPICS_IN_SECTIONS, + INSTRUCTION_SET, +}; diff --git a/yellow-paper/src/preprocess/InstructionSet/InstructionSetMarkdownGen.js b/yellow-paper/src/preprocess/InstructionSet/InstructionSetMarkdownGen.js new file mode 100644 index 00000000000..310efe12f20 --- /dev/null +++ b/yellow-paper/src/preprocess/InstructionSet/InstructionSetMarkdownGen.js @@ -0,0 +1,137 @@ +const fs = require("fs"); +const path = require("path"); + +const { + TOPICS_IN_TABLE, + TOPICS_IN_SECTIONS, + INSTRUCTION_SET, + instructionSize +} = require('./InstructionSet'); + +function escapeBraces(str) { + return str.replace(//g, ">"); +} + +function stripBraces(str) { + return str.replace(/[<>]/g, ''); +} + +function instructionSetPreface() { + let preface = "[comment]: # (THIS IS A GENERATED FILE! DO NOT EDIT!)\n"; + preface += "[comment]: # (Generated via `yarn preprocess`)\n\n"; + preface += "[comment]: # (Generated by InstructionSetMarkdownGen.tsx and InstructionSet.js)\n\n"; + preface += "import Markdown from 'react-markdown'\n"; + preface += "import CodeBlock from '@theme/CodeBlock'\n\n"; + return preface; +} + +function toOpcode(index) { + return '0x' + index.toString(16).padStart(2, '0'); +} + +function htmlInstructionSetTable() { + let table = "## Instructions Table\n"; + table += "\n\n"; + let header = ""; + for (let t = 0; t < TOPICS_IN_TABLE.length; t++) { + header += ``; + } + table += `${header}\n`; + + for (let i = 0; i < INSTRUCTION_SET.length; i++) { + const instr = INSTRUCTION_SET[i]; + const name = instr['Name']; + let row = `\n`; + row += `\t`; + row += `\t`; + + for (let t = 0; t < TOPICS_IN_TABLE.length; t++) { + const topic = TOPICS_IN_TABLE[t]; + + if (topic == 'Name') continue; // skip + let cell = instr[topic]; + if (cell[0] == '\n') { // if string starts with newline, assume it's a multi-line code block + cell = `\n{\`${cell.trim()}\`}\n\t`; + } else if (cell[0] == '`' && topic != 'Name') { + cell = `{\n\t\t\`${cell.replace(/`/g, '')}\`\n\t}`; + } else { + cell = escapeBraces(cell); // escape html + cell = `${cell}`; + } + row += `\n\t`; + } + row += "\n"; + table += `${row}\n`; + } + table += "
Opcode${TOPICS_IN_TABLE[t]}
${toOpcode(i)}[${stripBraces(name)}](#isa-section-${instr['id']})${cell}
\n"; + return table; +} + +function markdownSublist(items) { + let markdown = ""; + for (let i = 0; i < items.length; i++) { + let item = items[i]; + if (typeof item === 'string') { + markdown += `\n\t- ${item}`; + } else { + markdown += `\n\t- **${item['name']}**: ${item['description']}`; + } + } + return markdown; +} + +function markdownInstructionSetSection(pathToGenDir) { + let markdown = "## Instructions\n"; + for (let i = 0; i < INSTRUCTION_SET.length; i++) { + const instr = INSTRUCTION_SET[i]; + const name = instr['Name']; + let subsection = `###
${name} (${toOpcode(i)})\n`; + subsection += `${instr['Summary']}\n\n`; + subsection += `[See in table.](#isa-table-${instr['id']})\n\n`; + for (let t = 0; t < TOPICS_IN_SECTIONS.length; t++) { + const topic = TOPICS_IN_SECTIONS[t]; + let field = instr[topic]; + if (topic == 'Name' || topic == 'Summary' || !field || field.length == 0) continue; // skip + + let item = `- **${topic}**: ` + if (Array.isArray(field) ) { + item += markdownSublist(field); + } else if (field[0] == '\n') { // if string starts with newline, assume it's a multi-line code block + item += `\n\n{\`${field.trim()}\`}\n`; + } else { + item += field; + } + subsection += `${item}\n`; + } + const bitFormatPath = `./images/bit-formats/${name.replace(/`/g, '')}.png`; + if (fs.existsSync(`${pathToGenDir}/${bitFormatPath}`)) { + subsection += `\n![](${bitFormatPath})`; + } + markdown += `\n${subsection}\n`; + } + return markdown; +} + +async function generateInstructionSet() { + const rootDir = path.join(__dirname, "../../../"); + const docsDir = path.join(rootDir, "docs", "docs"); + + const relPath = path.relative(docsDir, "docs/public-vm/gen/_InstructionSet.mdx"); + const docsFilePath = path.resolve(docsDir, relPath); + const docsDirName = path.dirname(docsFilePath); + if (!fs.existsSync(docsDirName)) { + fs.mkdirSync(docsDirName, { recursive: true }); + } + + const preface = instructionSetPreface(); + const table = htmlInstructionSetTable(); + const section = markdownInstructionSetSection(docsDirName); + const doc = `${preface}\n${table}\n\n${section}`; + fs.writeFileSync(docsFilePath, doc); + + console.log("Preprocessing complete."); +} + +module.exports = { + generateInstructionSet, +}; \ No newline at end of file diff --git a/yellow-paper/src/preprocess/InstructionSet/InstructionSize.js b/yellow-paper/src/preprocess/InstructionSet/InstructionSize.js new file mode 100644 index 00000000000..37555faa4a3 --- /dev/null +++ b/yellow-paper/src/preprocess/InstructionSet/InstructionSize.js @@ -0,0 +1,80 @@ +const FIELD_SIZES = { // in bits + "Opcode": 8, + "Indirect": 8, +}; + +const DEFAULT_OPERAND_SIZE = 24; // for direct/indirect memory offsets + +function argSize(arg) { + if (arg['mode'] && arg['mode'] == 'immediate') { + if (arg['type']) { + return Number(arg['type'].replace(/u/, '')); + } else { + return undefined; // none specified! + } + } else { + return DEFAULT_OPERAND_SIZE; + } +} + +function toOpcode(index) { + return '0x' + index.toString(16).padStart(2, '0'); +} + +/* Compute bit-size of instruction based on flags and number of operands, + * whether they are immediate (and op-type if so) + * + * All instructions have: + * - 1 byte for opcode + * - 1 byte to toggle indirect mode for up to 8 non-immediate args + * 24 bits per-arg (for non-immediates) + * N bits per immediate arg, where N is 8, 16, 32, 64, or 128 based on type + * 1 byte for op-type + * 1 byte for dest-type + */ +function instructionSize(instr) { + let size = FIELD_SIZES['Opcode'] + FIELD_SIZES['Indirect']; + let numUntypedImmediates = 0; + for (let arg of instr['Args']) { + const aSize = argSize(arg); + if (aSize === undefined) { + numUntypedImmediates++; + } else { + size += aSize; + } + } + if (instr['Flags']) { + // assigns each flag a byte (op-type, dest-type) + size += instr['Flags'].length * 8; + } + let sizeStr = size.toString(); + if (numUntypedImmediates > 0) { + sizeStr += '+N'; + } + return sizeStr; +} + +function instructionBitFormat(instr, index) { + let bitFormat = { 'Name': instr['Name'], 'Opcode': {'code': toOpcode(index), 'size': 8}, 'Indirect': 8, 'Args': [], 'Flags': [] }; + + //for (let arg of instr['Args']) { + for (let a = 0; a < instr['Args'].length; a++) { + const arg = instr['Args'][a]; + const aSize = argSize(arg); + if (aSize === undefined) { + bitFormat['Args'][a] = {"name": arg['name'], "size": 'N'}; + } else { + bitFormat['Args'][a] = {"name": arg['name'], "size": aSize}; + } + } + for (let f = 0; f < instr['Flags'].length; f++) { + const flag = instr['Flags'][f]; + bitFormat['Flags'][f] = {"name": flag['name'], "size": 8}; + } + return bitFormat; +} + +module.exports = { + instructionSize, + instructionBitFormat, +}; \ No newline at end of file diff --git a/yellow-paper/src/preprocess/InstructionSet/genBitFormats.js b/yellow-paper/src/preprocess/InstructionSet/genBitFormats.js new file mode 100644 index 00000000000..968b769f51d --- /dev/null +++ b/yellow-paper/src/preprocess/InstructionSet/genBitFormats.js @@ -0,0 +1,16 @@ +const fs = require("fs"); + +const {instructionBitFormat} = require('./InstructionSize'); +const {INSTRUCTION_SET} = require('./InstructionSet'); + +function run() { + const formats = []; + for (let i = 0; i < INSTRUCTION_SET.length; i++) { + const instr = INSTRUCTION_SET[i]; + const bitFormat = instructionBitFormat(instr, i); + console.log(JSON.stringify(bitFormat)); + formats.push(bitFormat); + } + fs.writeFileSync('./InstructionBitFormats.json', JSON.stringify(formats)); +} +run(); \ No newline at end of file diff --git a/yellow-paper/src/preprocess/index.js b/yellow-paper/src/preprocess/index.js new file mode 100644 index 00000000000..71c4227df06 --- /dev/null +++ b/yellow-paper/src/preprocess/index.js @@ -0,0 +1,6 @@ +const {generateInstructionSet} = require('./InstructionSet/InstructionSetMarkdownGen'); + +async function run() { + await generateInstructionSet(); +} +run(); \ No newline at end of file diff --git a/yellow-paper/yarn.lock b/yellow-paper/yarn.lock index 3e351ffa146..9692b54cac9 100644 --- a/yellow-paper/yarn.lock +++ b/yellow-paper/yarn.lock @@ -3376,7 +3376,7 @@ debug@2.6.9, debug@^2.6.0: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -5142,6 +5142,17 @@ mdast-util-definitions@^4.0.0: dependencies: unist-util-visit "^2.0.0" +mdast-util-from-markdown@^0.8.0: + version "0.8.5" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" + integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string "^2.0.0" + micromark "~2.11.0" + parse-entities "^2.0.0" + unist-util-stringify-position "^2.0.0" + mdast-util-to-hast@10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" @@ -5156,6 +5167,20 @@ mdast-util-to-hast@10.0.1: unist-util-position "^3.0.0" unist-util-visit "^2.0.0" +mdast-util-to-hast@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz#61875526a017d8857b71abc9333942700b2d3604" + integrity sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + mdast-util-definitions "^4.0.0" + mdurl "^1.0.0" + unist-builder "^2.0.0" + unist-util-generated "^1.0.0" + unist-util-position "^3.0.0" + unist-util-visit "^2.0.0" + mdast-util-to-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" @@ -5203,6 +5228,14 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micromark@~2.11.0: + version "2.11.4" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" + integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== + dependencies: + debug "^4.0.0" + parse-entities "^2.0.0" + micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -6202,6 +6235,11 @@ react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.0: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-json-view@^1.21.3: version "1.21.3" resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" @@ -6224,6 +6262,24 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: dependencies: "@babel/runtime" "^7.10.3" +react-markdown@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-6.0.0.tgz#e63cd32d095e864384d524986c44c34c919de517" + integrity sha512-MC+zljUJeoLb4RbDm/wRbfoQFEZGz4TDOt/wb4dEehdaJWxLMn/T2IgwhQy0VYhuPEd2fhd7iOayE8lmENU0FA== + dependencies: + "@types/hast" "^2.0.0" + "@types/unist" "^2.0.3" + comma-separated-tokens "^1.0.0" + prop-types "^15.7.2" + property-information "^5.0.0" + react-is "^17.0.0" + remark-parse "^9.0.0" + remark-rehype "^8.0.0" + space-separated-tokens "^1.1.0" + style-to-object "^0.3.0" + unified "^9.0.0" + unist-util-visit "^2.0.0" + react-router-config@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" @@ -6461,6 +6517,20 @@ remark-parse@8.0.3: vfile-location "^3.0.0" xtend "^4.0.1" +remark-parse@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" + integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== + dependencies: + mdast-util-from-markdown "^0.8.0" + +remark-rehype@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-8.1.0.tgz#610509a043484c1e697437fa5eb3fd992617c945" + integrity sha512-EbCu9kHgAxKmW1yEYjx3QafMyGY3q8noUbNUI5xyKbaFP89wbhDrKxyIQNukNYthzjNHZu6J7hwFg7hRm1svYA== + dependencies: + mdast-util-to-hast "^10.2.0" + remark-squeeze-paragraphs@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead" @@ -6881,7 +6951,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -space-separated-tokens@^1.0.0: +space-separated-tokens@^1.0.0, space-separated-tokens@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==