Skip to content

Commit

Permalink
3690: Clarifications, better wording, and change PC (#3716)
Browse files Browse the repository at this point in the history
* Some updates and clarifications to 3690

* Change PC to be within code section in 3690
  • Loading branch information
axic authored Aug 11, 2021
1 parent d64ec9a commit a91f98b
Showing 1 changed file with 17 additions and 16 deletions.
33 changes: 17 additions & 16 deletions EIPS/eip-3690.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,41 +34,42 @@ This feature is introduced on the very same block [EIP-3540](./eip-3540.md) is e

1. A new EOF section called `jumpdests` (`section_kind = 3`) is introduced. It contains a sequence of *n* unsigned integers *jumploc<sub>i</sub>*.
2. The *jumploc<sub>i</sub>* values are encoded with [unsigned LEB128](https://en.wikipedia.org/wiki/LEB128#Unsigned_LEB128).
| description | encoding |
|-------------|-----------|

| description | encoding |
|---------------------|-----------------|
| jumploc<sub>0</sub> | unsigned LEB128 |
| jumploc<sub>1</sub> | unsigned LEB128 |
| ... | |
| ... | |
| jumploc<sub>n</sub> | unsigned LEB128 |
3. We define `CODE_SECTION_OFFSET` which is the offset from the EOF container beginning to the beginning of the `code` section contents.
4. The jump destinations represent the set of valid code positions as arguments to jump instructions. They are delta-encoded therefore partial sum must be performed to retrieve the absolute offsets.

3. The jump destinations represent the set of valid code positions as arguments to jump instructions. They are delta-encoded therefore partial sum must be performed to retrieve the absolute offsets.
```python
def jumpdest(n: int, jumpdests_table: list[int]) -> int:
return CODE_SECTION_OFFSET + sum(jumpdests_table[:n+1])
return sum(jumpdests_table[:n+1])
```

### Validation rules

> This section extends contact creation validation rules (as defined in EIP-3540).
5. The `jumpdests` section MUST be present if and only if the `code` section contains `JUMP` or `JUMPI` opcodes.
6. If the `jumpdests` section is present it MUST directly precede the `code` section. In this case a valid EOF bytecode will have the form of `format, magic, version, [jumpdests_section_header], code_section_header, [data_section_header], 0, [jumpdests_section_contents], code_section_contents, [data_section_contents]`.
7. The LEB128 encoding of a `jumploc` must be valid: the encoding must be complete and not read out of `jumpdests` section. As an additional constraint, the shortest possible encoding must be used.
8. With an exception of the first entry, the value of `jumploc` MUST NOT be 0.
9. Every `jumploc` MUST point to a valid opcode. They MUST NOT point into PUSH-data or outside of the code section.
10. The `JUMPDEST` (0x5b) instruction becomes undefined (Note: According to rules of EIP-3670, deploying the code will fail if it contains `JUMPDEST`)
4. The `jumpdests` section MUST be present if and only if the `code` section contains `JUMP` or `JUMPI` opcodes.
5. If the `jumpdests` section is present it MUST directly precede the `code` section. In this case a valid EOF bytecode will have the form of `format, magic, version, [jumpdests_section_header], code_section_header, [data_section_header], 0, [jumpdests_section_contents], code_section_contents, [data_section_contents]`.
6. The LEB128 encoding of a `jumploc` must be valid: the encoding must be complete and not read out of `jumpdests` section. As an additional constraint, the shortest possible encoding must be used.
7. With an exception of the first entry, the value of `jumploc` MUST NOT be 0.
8. Every `jumploc` MUST point to a valid opcode. They MUST NOT point into PUSH-data or outside of the code section.
9. The `JUMPDEST` (0x5b) instruction becomes undefined (Note: According to rules of EIP-3670, deploying the code will fail if it contains `JUMPDEST`)

### Execution

12. When executing `JUMP` or `JUMPI` instructions, the jump destination MUST be in the `jumpdests` table. Otherwise, the execution aborts with *bad jump destination*. In case of `JUMPI`, the check is done only when the jump is to be taken (no change to the previous behaviour).
10. When executing `JUMP` or `JUMPI` instructions, the jump destination MUST be in the `jumpdests` table. Otherwise, the execution aborts with *bad jump destination*. In case of `JUMPI`, the check is done only when the jump is to be taken (no change to the previous behaviour).

## Rationale

### Jumpdests section is bounded

The length of the `jumpdests` section is bounded by the EOF maximum section size value 0xffff. Moreover, for deployed code this additionally limited by the max bytecode size 0x6000. Then any valid `jumpdests` section may not be larger than 0x3000.
The length of the `jumpdests` section is bounded by the EOF maximum section size value 0xffff. Moreover, for deployed code this additionally limited by the max bytecode size 0x6000. Then any valid `jumpdests` section may not be more larger than 0x3000.

### Delta-encoding
### Delta encoding

Delta-encoding is very efficient for this job. From a quick analysis of a small set of contracts `JUMPDEST` opcodes are relatively close to each other. In the delta-encoding the values almost never exceed 128. Combined with any form of variable-length quantity (VLQ) where values < 128 occupy one byte, encoding of single jumpdest takes ~1 byte. We also remove `JUMPDEST` opcodes from the code section therefore the total bytecode length remains the same if extreme examples are ignored.

Expand Down Expand Up @@ -191,7 +192,7 @@ def process_jumpdests(delta: list[int]) -> list[int]:
else:
assert(d != 0)
partial_sum += d
jumpdests.append(CODE_SECTION_OFFSET + partial_sum)
jumpdests.append(partial_sum)
return jumpdests

# Fails with assertion on invalid code
Expand Down

0 comments on commit a91f98b

Please sign in to comment.