From 2b3e8bb651fce362cf768ab2453b8f140d9edea9 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Tue, 15 Mar 2022 11:58:59 -0400 Subject: [PATCH 01/12] Modules Expand code sections from single-entry functions to multiple-entry modules. --- EIPS/eip-4750.md | 118 ++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 68 deletions(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index e51ef25da84f6..8c81faee11247 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -1,7 +1,7 @@ --- eip: 4750 -title: EOF - Functions -description: Individual sections for functions with `CALLF` and `RETF` instructions +title: EOF - Modules +description: Individual sections for modules with `CALLPROC` and `RETURNPROC` instructions author: Andrei Maiboroda (@gumb0), Alex Beregszaszi (@axic), Paweł Bylica (@chfast) discussions-to: https://ethereum-magicians.org/t/eip-4750-eof-functions/8195 status: Draft @@ -13,110 +13,90 @@ requires: 3540, 3670 ## Abstract -Introduce the ability to have several code sections in EOF-formatted ([EIP-3540](./eip-3540.md)) bytecode, each one representing a separate subroutine/function. Two new opcodes,`CALLF` and `RETF`, are introduced to call and return from such a function. +Introduce the ability to have several code sections in EOF-formatted ([EIP-3540](./eip-3540.md)) bytecode, , each one representing a separate module. + +Each code section has a corresponding type section which speficies one or more procedural entry points to that module. + +Two new opcodes,`CALLPROC` and `RETURNPROC`, are introduced to call and return from these procedures. ## Motivation Currently in the EVM everything is a dynamic jump. Languages like Solidity generate most jumps in a static manner (i.e. the destination is pushed to the stack right before, `PUSHn .. JUMP`). Unfortunately however this cannot be used by most EVM interpreters, because of added requirement of validation/analysis. This also restricts them from making optimisations and potentially reducing the cost of jumps. +Dynamic jumps also impede (but do not completely prevent) the validation of safety properties promised by [EIP-3779](./EIP-3779.md): that no valid program will halt with an exeption exception via lack of gas or recursive stack overflow. + +This EIP aims to remove the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from procedures. While it removes the need, it does not disallow those instructions. + [EIP-4200](./eip-4200.md) introduces static jump instructions, which remove the need for *most* dynamic jump use cases, but not everything can be solved with them. -This EIP aims to remove the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from functions. While it removes the need, it does not disallow those instructions. +[EIP-2315](./EIP-2315.md) removes the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from subroutine. But only bare mechanism is provided -- no structure is imposed on the code. -Furthermore it aims to improve analysis opportunities by encoding the number of inputs and outputs for each given function, and isolating the stack of each function (i.e. a function cannot read the stack of the caller/callee). +This proposal goes further in providing a typed, modular structure. Modules are mapped to multiple code sections, and procedures are mapped to typed entry points in each code section. It aims to improve analysis opportunities by encoding the number of inputs and outputs as the type for each given procedure, and isolating the stack of each procedure (i.e. a procedure cannot read the stack of the caller/callee). ## Specification +### EOF Code and Type Sections + +We propose to allow for multiple `EOF` *code* and corresponding *type* sections. Code sections after the first can be entered only via a `CALLPROC` to one of the entry point procedures specified in its coresponding type section, and can be left only via `RETURNPROC`. + +`CALLPROC` and `RETURNPROC` are in turn defined in terms of `JUMPSUB` and `RETURNSUB` from [EIP-2315](./EIP-2315.md). + + ### EOF container changes 1. The requirement of [EIP-3540](./eip-3540.md) "Exactly one code section MUST be present." is relaxed to "At least one code section MUST be present.", i.e. multiple code sections (`kind = 1`) are allowed. 2. Total number of code sections MUST NOT exceed 1024. 3. All code sections MUST precede a data section, if data section is present. 4. New section with `kind = 3` is introduced called the *type section*. -5. Exactly one type section MUST be present. -6. The type section MUST directly precede all code sections. -7. The type section contains a sequence of pairs of bytes: first byte in a pair encodes number of inputs, and second byte encodes number of outputs of the code section with the same index. *Note:* This implies that there is a limit of 256 stack for the input and in the output. -8. Therefore type section size MUST be `n * 2` bytes, where `n` is the number of code sections. -9. First code section MUST have 0 inputs and 0 outputs. +5. Exactly one type section MUST be present for each code section. +6. The type sections MUST directly precede all code sections. +7. The type section contains a sequence of triples: +* the first uint8 encodes number of inputs +* a second unint8 encodes number of outputs, and +* a final uint16 encodes the offset of the entry point, relative to the beginning of each code section. +* *Note: This implies that there is a limit of 256 stack for the input and in the output.* +9. First code section MUST have 1 entry point at offset 0 with 0 inputs and 0 outputs. To summarize, a well-formed EOF bytecode will have the following format: ``` -bytecode := format, magic, version, type_section_header, (code_section_header)+, [data_section_header], 0, type_section_contents, (code_section_contents)+, [data_section_contents] +bytecode := format, magic, version, (type_section_header)+, (code_section_header)+, [data_section_header], 0, (type_section_contents)+, (code_section_contents)+, [data_section_contents] -type_section_header := 3, number_of_code_sections * 2 # section kind and size -type_section_contents := 0, 0, code_section_1_inputs, code_section_1_outputs, code_section_2_inputs, code_section_2_outputs, ..., code_section_n_inputs, code_section_n_outputs +type_section_header := 3, number_of_code_sections * 4 # section kind and size +type_section_contents := 0, 0, code_section_1_inputs, code_section_1_outputs, code_section_2_inputs, code_section_2_outputs, ..., code_section_n_inputs, code_section_n_outputs, code_section_entry_offest ``` -### New execution state in EVM - -A return stack is introduced, separate from the data stack. It is a stack of items representing execution state to return to after function execution is finished. Each item is comprised of: code section index, offset in the code section (PC value), calling function stack height. - -Note: Implementations are free to choose particular encoding for a stack item. In the specification below we assume that representation is three unsigned integers: `code_section_index`, `offset`, `stack_height`. - -The return stack is limited to a maximum 1024 items. - -Additionally, EVM keeps track of the index of currently executing section - `current_section_index`. - ### New instructions We introduce two new instructions: -1. `CALLF` (`0x5e`) -2. `RETF` (`0x5f`) +1. **`CALLPROC`** (`0x5e`) +2. **`RETURNPROC`** (`0x5f`) If the code is legacy bytecode, both of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*) -First we define several helper values: -- `caller_stack_height = return_stack.top().stack_height` - stack height value saved in the top item of return stack -- `type[i].inputs = type_section_contents[i * 2]` - number of inputs of ith section -- `type[i].outputs = type_section_contents[i * 2 + 1]` - number of outputs of ith section - -If the code is valid EOF1, the following execution rules apply: +#### CALLPROC (0x5e) dest_section: uint8, dest_proc: uint8 + ``` + JUMPSUB + +``` +> Transfer control as if via `JUMPSUB` to the offset of the Nth (N=*dest_proc*) _procedure_ in the Mth(M=*dest_section*) _section_ of the code. _Section 0_ is the current code section, any other code sections are indexed starting at _1_. -#### `CALLF` + *Note: That the procedure is defined and the required `n_inputs` words are available on the `data stack` must be shown at validation time.* -1. Has one immediate argument,`code_section_index`, encoded as a 16-bit unsigned big-endian value. -2. If data stack has less than `caller_stack_height + type[code_section_index].inputs`, execution results in exceptional halt. -3. If return stack already has `1024` items, execution results in exceptional halt. -4. Pops nothing and pushes nothing to data stack. -5. Pushes to return stack an item: +#### RETURNPROC (0x??) ``` -(code_section_index = current_section_index, -offset = PC_post_instruction, -stack_height = data_stack.height - types[code_section_index].inputs) + RETURNSUB ``` +> Return control to the calling procedure as if via `RETURNSUB`. -Under `PC_post_instruction` we mean the PC position after the entire immediate argument of `CALLF`. Data stack height is saved as it was before function inputs were pushed. - -*Note:* Code validation rules of EIP-3670 guarantee there is always an instruction following `CALLF` (since terminating instruction is required to be final one in the section), therefore `PC_post_instruction` always points to an instruction inside section bounds. - -6. Sets `current_section_index` to `code_section_index` and `PC` to `0`, and execution continues in the called section. - -#### `RETF` - -1. Does not have immediate arguments. -2. If data stack has less than `caller_stack_height + types[code_section_index].outputs`, execution results in exceptional halt. -3. Pops nothing and pushes nothing to data stack. -4. Pops an item from return stack and sets `current_section_index` and `PC` to values from this item. - 4.1. If return stack is empty after this, execution halts with success. - -### Code Validation - -In addition to container format validation rules above, we extend code section validation rules (as defined in [EIP-3670](./eip-3670.md)). - -1. Code validation rules of EIP-3670 are applied to every code section. -2. List of allowed *terminating instructions* in EIP-3670 is extended to include `RETF`. (*Note that `CALLF`, like other instructions with immediates, cannot be truncated.*) -3. Code section is invalid in case an immediate argument of any `CALLF` is greater than or equal to the total number of code sections. -4. `RJUMP` and `RJUMPI` immediate argument value (jump destination relative offset) validation: - 4.1. Code section is invalid in case offset points to a position outside of section bounds. - 4.2. Code section is invalid in case offset points to one of two bytes directly following `CALLF` instruction. +*Note: That the promised `n_outputs` words are available on the `data stack` must be shown at validation time.* ### Execution 1. Execution starts at the first byte of the first code section, and PC is set to 0. 2. Return stack is initialized to contain one item: `(code_section_index = 0, offset = 0, stack_height = 0)` -3. Destinations of jumps are allowed only to be inside current code section. `JUMP` and `JUMPI` result in exceptional halt when destination is outside of current section bounds. -4. If any instruction would access a data stack item below `caller_stack_height`, execution results in exceptional halt. This rule replaces the old stack underflow check. +3. Destinations of jumps are allowed only to be inside current code section. `JUMP`, `JUMPI`, `RJUMP, and `RJUMPI` result in an invalid program when destination is outside of current section bounds. + +*Note: That jumps are valid must be shown at validation time.* #### Implications on the JUMPDEST analysis @@ -125,11 +105,13 @@ In addition to container format validation rules above, we extend code section v ## Rationale +Each code section is a module with defined procedural interfaces, identified with address-independent indexes. Given that all jumps within a section are relative, and cannot jump out of a section, this allows external tools to compose contracts out of pre-compiled code sections. + ### `RETF` in the top frame ends execution vs exceptionally halts -Alternative logic for executing `RETF` in the top frame could be to exceptionally halt execution, because there is arguably no caller for the starting function. This would mean that return stack is initialized as empty, and `RETF` exceptionally aborts when return stack is empty. +Alternative logic for executing `RETF` in the top frame could be to exceptionally halt execution, because there is arguably no caller for the starting procedure. This would mean that return stack is initialized as empty, and `RETF` exceptionally aborts when return stack is empty. -We have decided in favor of always having at least one item in the return stack, because it allows to avoid having a special case for empty stack in the interpreter loop stack underflow check. We keep the stack underflow rule general by having `caller_stack_height = 0` in the top frame. +We have decided in favor of always having at least one item in the return stack, because it allows to avoid having a special case for empty stack in the interpreter loop stack underflow check. We keep the stack underflow. ## Backwards Compatibility From 4d4ee5e9d154f117026146ee2754b21c88cc74e0 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Tue, 15 Mar 2022 12:27:30 -0400 Subject: [PATCH 02/12] Update eip-4750.md --- EIPS/eip-4750.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index 8c81faee11247..7623e08147193 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -3,7 +3,8 @@ eip: 4750 title: EOF - Modules description: Individual sections for modules with `CALLPROC` and `RETURNPROC` instructions author: Andrei Maiboroda (@gumb0), Alex Beregszaszi (@axic), Paweł Bylica (@chfast) -discussions-to: https://ethereum-magicians.org/t/eip-4750-eof-functions/8195 +discussions-to: https://ethereum-magicians.org/ +4750-eof-functions/8195 status: Draft type: Standards Track category: Core @@ -13,9 +14,9 @@ requires: 3540, 3670 ## Abstract -Introduce the ability to have several code sections in EOF-formatted ([EIP-3540](./eip-3540.md)) bytecode, , each one representing a separate module. +Introduce the ability to have several code sections in EOF-formatted ([EIP-3540](./eip-3540.md)) bytecode, each one representing a separate module. -Each code section has a corresponding type section which speficies one or more procedural entry points to that module. +Each code section has a corresponding type section which `specifies` one or more procedural entry points to that module. Two new opcodes,`CALLPROC` and `RETURNPROC`, are introduced to call and return from these procedures. @@ -23,13 +24,14 @@ Two new opcodes,`CALLPROC` and `RETURNPROC`, are introduced to call and return f Currently in the EVM everything is a dynamic jump. Languages like Solidity generate most jumps in a static manner (i.e. the destination is pushed to the stack right before, `PUSHn .. JUMP`). Unfortunately however this cannot be used by most EVM interpreters, because of added requirement of validation/analysis. This also restricts them from making optimisations and potentially reducing the cost of jumps. -Dynamic jumps also impede (but do not completely prevent) the validation of safety properties promised by [EIP-3779](./EIP-3779.md): that no valid program will halt with an exeption exception via lack of gas or recursive stack overflow. +Dynamic jumps also impede (but do not completely prevent) the validation of safety properties promised by [EIP-3779](./eip-3779.md): that no valid program will halt with an +exception via lack of gas or recursive stack overflow. This EIP aims to remove the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from procedures. While it removes the need, it does not disallow those instructions. [EIP-4200](./eip-4200.md) introduces static jump instructions, which remove the need for *most* dynamic jump use cases, but not everything can be solved with them. -[EIP-2315](./EIP-2315.md) removes the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from subroutine. But only bare mechanism is provided -- no structure is imposed on the code. +[EIP-2315](./eip-2315.md) removes the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from subroutine. But only bare mechanism is provided -- no structure is imposed on the code. This proposal goes further in providing a typed, modular structure. Modules are mapped to multiple code sections, and procedures are mapped to typed entry points in each code section. It aims to improve analysis opportunities by encoding the number of inputs and outputs as the type for each given procedure, and isolating the stack of each procedure (i.e. a procedure cannot read the stack of the caller/callee). @@ -37,9 +39,9 @@ This proposal goes further in providing a typed, modular structure. Modules are ### EOF Code and Type Sections -We propose to allow for multiple `EOF` *code* and corresponding *type* sections. Code sections after the first can be entered only via a `CALLPROC` to one of the entry point procedures specified in its coresponding type section, and can be left only via `RETURNPROC`. +We propose to allow for multiple `EOF` *code* and corresponding *type* sections. Code sections after the first can be entered only via a `CALLPROC` to one of the entry point procedures specified in its corresponding type section, and can be left only via `RETURNPROC`. -`CALLPROC` and `RETURNPROC` are in turn defined in terms of `JUMPSUB` and `RETURNSUB` from [EIP-2315](./EIP-2315.md). +`CALLPROC` and `RETURNPROC` are in turn defined in terms of `JUMPSUB` and `RETURNSUB` from [EIP-2315](./eip-2315.md). ### EOF container changes From 793dcb11f04eb074eb5d094c855098b81d74bd88 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Tue, 15 Mar 2022 12:38:06 -0400 Subject: [PATCH 03/12] Update eip-4750.md --- EIPS/eip-4750.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index 7623e08147193..7debab738a0ed 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -1,15 +1,14 @@ --- eip: 4750 -title: EOF - Modules +title: EOF - Modules description: Individual sections for modules with `CALLPROC` and `RETURNPROC` instructions author: Andrei Maiboroda (@gumb0), Alex Beregszaszi (@axic), Paweł Bylica (@chfast) -discussions-to: https://ethereum-magicians.org/ -4750-eof-functions/8195 +discussions-to: https://ethereum-magicians.org/4750-eof-functions/8195 status: Draft type: Standards Track category: Core created: 2022-01-10 -requires: 3540, 3670 +requires: 2315, 3540, 3670, 4200 --- ## Abstract From a74fee6bf7af3cf76af750dbbb43d434822875b5 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Tue, 15 Mar 2022 12:47:43 -0400 Subject: [PATCH 04/12] maybe the bot will be happy now --- EIPS/eip-4750.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index 7debab738a0ed..ef25d6a1c2e65 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -13,7 +13,7 @@ requires: 2315, 3540, 3670, 4200 ## Abstract -Introduce the ability to have several code sections in EOF-formatted ([EIP-3540](./eip-3540.md)) bytecode, each one representing a separate module. +Introduce the ability to have several code sections in EOF-formatted ([EIP-3540](./eip-3540.md) bytecode, each one representing a separate module. Each code section has a corresponding type section which `specifies` one or more procedural entry points to that module. From 16647b07cff54da33a248f8c36a05548a2d4328c Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Tue, 15 Mar 2022 12:57:47 -0400 Subject: [PATCH 05/12] still wasn't happy --- EIPS/eip-4750.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index ef25d6a1c2e65..b10f292d439d1 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -8,7 +8,7 @@ status: Draft type: Standards Track category: Core created: 2022-01-10 -requires: 2315, 3540, 3670, 4200 +requires: 2315, 3540, 3670, 3779, 4200 --- ## Abstract From d26c590e00033d0d104284f61361fa53b9c928d4 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Tue, 15 Mar 2022 13:42:16 -0400 Subject: [PATCH 06/12] please --- EIPS/eip-4750.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index b10f292d439d1..15d2b0c8fbcfa 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -13,9 +13,9 @@ requires: 2315, 3540, 3670, 3779, 4200 ## Abstract -Introduce the ability to have several code sections in EOF-formatted ([EIP-3540](./eip-3540.md) bytecode, each one representing a separate module. +Introduce the ability to have several code sections in EOF-formatted [EIP-3540](./eip-3540.md) bytecode, each one representing a separate module. -Each code section has a corresponding type section which `specifies` one or more procedural entry points to that module. +Each code section has a corresponding type section which specifies one or more procedural entry points to that module. Two new opcodes,`CALLPROC` and `RETURNPROC`, are introduced to call and return from these procedures. From ce22c9af67c90280d56b06f3db87d079815a6146 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Tue, 15 Mar 2022 16:24:09 -0400 Subject: [PATCH 07/12] no --- EIPS/eip-4750.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index 15d2b0c8fbcfa..cad7f4bc19c07 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -23,8 +23,7 @@ Two new opcodes,`CALLPROC` and `RETURNPROC`, are introduced to call and return f Currently in the EVM everything is a dynamic jump. Languages like Solidity generate most jumps in a static manner (i.e. the destination is pushed to the stack right before, `PUSHn .. JUMP`). Unfortunately however this cannot be used by most EVM interpreters, because of added requirement of validation/analysis. This also restricts them from making optimisations and potentially reducing the cost of jumps. -Dynamic jumps also impede (but do not completely prevent) the validation of safety properties promised by [EIP-3779](./eip-3779.md): that no valid program will halt with an -exception via lack of gas or recursive stack overflow. +Dynamic jumps also impede the validation of safety properties promised by [EIP-3779](./eip-3779.md): that no valid program will encounter an exceptional halting condition except via lack of gas or recursive stack overflow. This EIP aims to remove the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from procedures. While it removes the need, it does not disallow those instructions. From 7cc51c92825c6d0d5f9d2062b932ea3f17f872f9 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Tue, 15 Mar 2022 17:54:06 -0400 Subject: [PATCH 08/12] Update eip-4750.md --- EIPS/eip-4750.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index cad7f4bc19c07..0025b95cad8e8 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -1,6 +1,6 @@ --- eip: 4750 -title: EOF - Modules +title: EOF - Modules and Procedures description: Individual sections for modules with `CALLPROC` and `RETURNPROC` instructions author: Andrei Maiboroda (@gumb0), Alex Beregszaszi (@axic), Paweł Bylica (@chfast) discussions-to: https://ethereum-magicians.org/4750-eof-functions/8195 @@ -23,13 +23,13 @@ Two new opcodes,`CALLPROC` and `RETURNPROC`, are introduced to call and return f Currently in the EVM everything is a dynamic jump. Languages like Solidity generate most jumps in a static manner (i.e. the destination is pushed to the stack right before, `PUSHn .. JUMP`). Unfortunately however this cannot be used by most EVM interpreters, because of added requirement of validation/analysis. This also restricts them from making optimisations and potentially reducing the cost of jumps. -Dynamic jumps also impede the validation of safety properties promised by [EIP-3779](./eip-3779.md): that no valid program will encounter an exceptional halting condition except via lack of gas or recursive stack overflow. +Dynamic jumps also impede the validation of safety properties promised by [EIP-3779: Safer Control Flow for the EVM](./eip-3779.md), for programs whose jumps are all static: that no valid program will encounter an exceptional halting condition except via lack of gas or recursive stack overflow. This EIP aims to remove the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from procedures. While it removes the need, it does not disallow those instructions. -[EIP-4200](./eip-4200.md) introduces static jump instructions, which remove the need for *most* dynamic jump use cases, but not everything can be solved with them. +[EIP-4200: Static relative jumps](./eip-4200.md) introduces static jump instructions, which remove the need for *most* dynamic jump use cases, but not everything can be solved with them. -[EIP-2315](./eip-2315.md) removes the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from subroutine. But only bare mechanism is provided -- no structure is imposed on the code. +[EIP-2315: Simple Subroutines for the EVM ](./eip-2315.md) provides for calling into and returning from subroutine. But only bare mechanism is provided -- no structure is imposed on the code. This proposal goes further in providing a typed, modular structure. Modules are mapped to multiple code sections, and procedures are mapped to typed entry points in each code section. It aims to improve analysis opportunities by encoding the number of inputs and outputs as the type for each given procedure, and isolating the stack of each procedure (i.e. a procedure cannot read the stack of the caller/callee). @@ -41,7 +41,6 @@ We propose to allow for multiple `EOF` *code* and corresponding *type* sections. `CALLPROC` and `RETURNPROC` are in turn defined in terms of `JUMPSUB` and `RETURNSUB` from [EIP-2315](./eip-2315.md). - ### EOF container changes 1. The requirement of [EIP-3540](./eip-3540.md) "Exactly one code section MUST be present." is relaxed to "At least one code section MUST be present.", i.e. multiple code sections (`kind = 1`) are allowed. @@ -75,17 +74,13 @@ We introduce two new instructions: If the code is legacy bytecode, both of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*) #### CALLPROC (0x5e) dest_section: uint8, dest_proc: uint8 - ``` - JUMPSUB + -``` + > Transfer control as if via `JUMPSUB` to the offset of the Nth (N=*dest_proc*) _procedure_ in the Mth(M=*dest_section*) _section_ of the code. _Section 0_ is the current code section, any other code sections are indexed starting at _1_. *Note: That the procedure is defined and the required `n_inputs` words are available on the `data stack` must be shown at validation time.* #### RETURNPROC (0x??) -``` - RETURNSUB -``` + > Return control to the calling procedure as if via `RETURNSUB`. *Note: That the promised `n_outputs` words are available on the `data stack` must be shown at validation time.* From b78eb445eb184dd7e170f9a579e9f152cb49b377 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Thu, 17 Mar 2022 00:30:49 -0400 Subject: [PATCH 09/12] Update eip-4750.md --- EIPS/eip-4750.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index 0025b95cad8e8..973d4793605eb 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -33,6 +33,8 @@ This EIP aims to remove the need for dynamic jumps as it offers the most importa This proposal goes further in providing a typed, modular structure. Modules are mapped to multiple code sections, and procedures are mapped to typed entry points in each code section. It aims to improve analysis opportunities by encoding the number of inputs and outputs as the type for each given procedure, and isolating the stack of each procedure (i.e. a procedure cannot read the stack of the caller/callee). +We are following Intel in calling the low level concept subroutines and the higher level concept procedures. The distinction is that subroutines are little more than a jump that knows where it came from, whereas procedures have a defined interface and manage memory as a stack. So this EIP defines typed procedures in terms of the untyped subroutines of EIP-2315. + ## Specification ### EOF Code and Type Sections @@ -83,7 +85,7 @@ If the code is legacy bytecode, both of these instructions result in an *excepti > Return control to the calling procedure as if via `RETURNSUB`. -*Note: That the promised `n_outputs` words are available on the `data stack` must be shown at validation time.* +*Note: That the required `n_outputs` words are available on the `data stack` must be shown at validation time.* ### Execution From 679e044d8bd89702a1a30cb1952d891f4c13106f Mon Sep 17 00:00:00 2001 From: Pandapip1 <45835846+Pandapip1@users.noreply.github.com> Date: Wed, 31 Aug 2022 21:32:03 -0400 Subject: [PATCH 10/12] Apply suggestions from code review --- EIPS/eip-4750.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index 973d4793605eb..a168c5544fb99 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -1,9 +1,9 @@ --- eip: 4750 -title: EOF - Modules and Procedures +title: EOF - Modules and Procedures description: Individual sections for modules with `CALLPROC` and `RETURNPROC` instructions author: Andrei Maiboroda (@gumb0), Alex Beregszaszi (@axic), Paweł Bylica (@chfast) -discussions-to: https://ethereum-magicians.org/4750-eof-functions/8195 +discussions-to: https://ethereum-magicians.org/t/eip-4750-eof-functions/8195 status: Draft type: Standards Track category: Core @@ -23,13 +23,13 @@ Two new opcodes,`CALLPROC` and `RETURNPROC`, are introduced to call and return f Currently in the EVM everything is a dynamic jump. Languages like Solidity generate most jumps in a static manner (i.e. the destination is pushed to the stack right before, `PUSHn .. JUMP`). Unfortunately however this cannot be used by most EVM interpreters, because of added requirement of validation/analysis. This also restricts them from making optimisations and potentially reducing the cost of jumps. -Dynamic jumps also impede the validation of safety properties promised by [EIP-3779: Safer Control Flow for the EVM](./eip-3779.md), for programs whose jumps are all static: that no valid program will encounter an exceptional halting condition except via lack of gas or recursive stack overflow. +Dynamic jumps also impede the validation of safety properties promised by [EIP-3779](./eip-3779.md), for programs whose jumps are all static: that no valid program will encounter an exceptional halting condition except via lack of gas or recursive stack overflow. This EIP aims to remove the need for dynamic jumps as it offers the most important feature those are used for: calling into and returning from procedures. While it removes the need, it does not disallow those instructions. [EIP-4200: Static relative jumps](./eip-4200.md) introduces static jump instructions, which remove the need for *most* dynamic jump use cases, but not everything can be solved with them. -[EIP-2315: Simple Subroutines for the EVM ](./eip-2315.md) provides for calling into and returning from subroutine. But only bare mechanism is provided -- no structure is imposed on the code. +[EIP-2315](./eip-2315.md) provides for calling into and returning from the subroutine. But only a bare mechanism is provided – no structure is imposed on the code. This proposal goes further in providing a typed, modular structure. Modules are mapped to multiple code sections, and procedures are mapped to typed entry points in each code section. It aims to improve analysis opportunities by encoding the number of inputs and outputs as the type for each given procedure, and isolating the stack of each procedure (i.e. a procedure cannot read the stack of the caller/callee). @@ -91,7 +91,7 @@ If the code is legacy bytecode, both of these instructions result in an *excepti 1. Execution starts at the first byte of the first code section, and PC is set to 0. 2. Return stack is initialized to contain one item: `(code_section_index = 0, offset = 0, stack_height = 0)` -3. Destinations of jumps are allowed only to be inside current code section. `JUMP`, `JUMPI`, `RJUMP, and `RJUMPI` result in an invalid program when destination is outside of current section bounds. +3. Destinations of jumps are allowed only to be inside the current code section. `JUMP`, `JUMPI`, `RJUMP`, and `RJUMPI` result in an invalid program when the destination is outside of current section bounds. *Note: That jumps are valid must be shown at validation time.* @@ -102,7 +102,7 @@ If the code is legacy bytecode, both of these instructions result in an *excepti ## Rationale -Each code section is a module with defined procedural interfaces, identified with address-independent indexes. Given that all jumps within a section are relative, and cannot jump out of a section, this allows external tools to compose contracts out of pre-compiled code sections. +Each code section is a module with defined procedural interfaces, identified with address-independent indexes. Given that all jumps within a section are relative, and cannot jump out of a section, this allows external tools to compose contracts out of pre-compiled code sections. ### `RETF` in the top frame ends execution vs exceptionally halts From d1d645490bbef17084108727ead0e51a073107c8 Mon Sep 17 00:00:00 2001 From: Pandapip1 <45835846+Pandapip1@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:01:30 -0400 Subject: [PATCH 11/12] Fix MD in preamble --- EIPS/eip-4750.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index 9f8c4994520e5..40eee54ae0c9a 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -1,7 +1,7 @@ --- eip: 4750 title: EOF - Modules and Procedures -description: Individual sections for modules with `CALLPROC` and `RETURNPROC` instructions +description: Individual sections for modules with CALLPROC and RETURNPROC instructions author: Andrei Maiboroda (@gumb0), Alex Beregszaszi (@axic), Paweł Bylica (@chfast) discussions-to: https://ethereum-magicians.org/t/eip-4750-eof-functions/8195 status: Draft From a9d11270fe851288a9ea3f139dff0b7b65bae980 Mon Sep 17 00:00:00 2001 From: Greg Colvin Date: Mon, 24 Oct 2022 13:54:31 -0400 Subject: [PATCH 12/12] Add myself as author. --- EIPS/eip-4750.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-4750.md b/EIPS/eip-4750.md index f5438c5dcf524..f6996fa334deb 100644 --- a/EIPS/eip-4750.md +++ b/EIPS/eip-4750.md @@ -2,7 +2,7 @@ eip: 4750 title: EOF - Modules and Procedures description: Individual sections for modules with CALLPROC and RETURNPROC instructions -author: Andrei Maiboroda (@gumb0), Alex Beregszaszi (@axic), Paweł Bylica (@chfast) +author: Andrei Maiboroda (@gumb0), Alex Beregszaszi (@axic), Paweł Bylica (@chfast), Greg Colvin (@gcolvin) discussions-to: https://ethereum-magicians.org/t/eip-4750-eof-functions/8195 status: Draft type: Standards Track