├── .circleci
└── config.yml
├── .gitignore
├── LICENSE
├── README.md
├── assets
├── 1.73x2-hexagon-sticker-ewasm-with-border.pdf
├── 1.73x2-hexagon-sticker-ewasm-with-border.svg
├── 1.73x2-hexagon-sticker-ewasm.pdf
├── 1.73x2-hexagon-sticker-ewasm.svg
├── blocks.png
├── ewasm_logo.ai
├── ewasm_logo.eps
├── ewasm_logo.pdf
├── ewasm_logo.svg
├── ewasm_logo_100x141_tr.png
├── ewasm_logo_100x141_wb.png
├── ewasm_logo_200x281_tr.png
├── ewasm_logo_200x281_wb.png
├── ewasm_logo_300x422_tr.png
├── ewasm_logo_300x422_wb.png
├── ewasm_logo_50x70_tr.png
├── ewasm_logo_50x70_wb.png
├── ewasm_logo_text.svg
├── ewasm_logo_text_update.ai
├── if.png
├── logo_sq_tr_128x128.png
├── logo_sq_tr_256x256.png
├── logo_sq_tr_32x32.png
├── logo_sq_tr_512x512.png
├── logo_sq_tr_64x64.png
├── logo_sq_wb_128x128.png
├── logo_sq_wb_256x256.png
├── logo_sq_wb_32x32.png
├── logo_sq_wb_512x512.png
└── logo_sq_wb_64x64.png
├── backwards_compatibility.md
├── comparison.md
├── contract_interface.md
├── determining_wasm_gas_costs.md
├── eth_interface.md
├── evm_transcompiler.md
├── faq.md
├── fee_schedule.md
├── interface_questions.md
├── metering.md
├── rationale.md
├── sentinel.md
├── system_contracts.md
└── vm_semantics.md
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | codespell:
4 | docker:
5 | - image: circleci/python
6 |
7 | steps:
8 | - checkout
9 | - run:
10 | name: "Run codespell"
11 | command: |
12 | sudo pip install codespell
13 | codespell --skip=".git"
14 |
15 | workflows:
16 | version: 2
17 | build_all:
18 | jobs:
19 | - codespell
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ethereum flavored WebAssembly (ewasm)
2 |
3 | Specification **Revision 4**
4 |
5 | This repository contains documents describing the design and high-level overview of ewasm. Expect the contents of this repository to be in flux: everything is still under discussion.
6 |
7 | **This repository is also available through [ReadTheDocs](https://ewasm.readthedocs.io).**
8 |
9 | ## What is WebAssembly?
10 |
11 | > WebAssembly (or Wasm as a contraction) is a new, portable, size- and load-time-efficient format. WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms. WebAssembly is currently being designed as an open standard by a W3C Community Group.
12 |
13 | Please review the [WebAssembly](http://webassembly.org/) [design](http://webassembly.org/docs/high-level-goals/) and [instruction set](https://webassembly.github.io/spec/core/appendix/index-instructions.html#index-instr) first. (You can also make a pull request or raise an issue at the [Wasm Github repo](https://github.com/WebAssembly/design).)
14 |
15 | A few key points:
16 | * WebAssembly defines an instruction set, intermediate source format (wast) and a binary encoded format (wasm).
17 | * WebAssembly has a few higher level features, such as the ability to import and execute outside methods defined via an interface.
18 | * [LLVM](https://llvm.org/) includes a WebAssembly backend to generate Wasm output.
19 | * Major browser JavaScript engines will notably have native support for
20 | WebAssembly, including but not limited to: Google's
21 | [V8](https://github.com/v8/v8) engine (Node.js and Chromium-based browsers),
22 | Microsoft's [Chakra](https://github.com/Microsoft/ChakraCore) engine
23 | (Microsoft Edge), Mozilla's
24 | [Spidermonkey](https://github.com/mozilla/gecko-dev/tree/master/js) engine
25 | (Firefox and Thunderbird).
26 | * Other non-browser implementations exist too:
27 | [wasm-jit-prototype](https://github.com/WebAssembly/wasm-jit-prototype) (a
28 | standalone VM using an LLVM backend),
29 | [wabt](https://github.com/WebAssembly/wabt) (a stack-based interpreter),
30 | [ml-proto](https://github.com/WebAssembly/spec/tree/master/ml-proto) (the
31 | OCaml reference interpreter), etc.
32 |
33 | ## What is Ethereum flavored WebAssembly (ewasm)?
34 |
35 | ewasm is a restricted subset of Wasm to be used for contracts in Ethereum.
36 |
37 | ewasm:
38 | * specifies the [VM semantics](./vm_semantics.md)
39 | * specifies the [semantics for an *ewasm contract*](./contract_interface.md)
40 | * specifies an [Ethereum environment interface](./eth_interface.md) to facilitate interaction with the Ethereum environment from an *ewasm contract*
41 | * specifies [system contracts](./system_contracts.md)
42 | * specifies [metering](./metering.md) for instructions
43 | * and aims to restrict [non-deterministic behavior](https://github.com/WebAssembly/design/blob/master/Nondeterminism.md)
44 | * specifies a backwards compatible upgrade path to EVM1
45 |
46 | ### Goals of the ewasm project
47 |
48 | * To provide a specification of *ewasm contract* semantics and the *Ethereum interface*
49 | * To provide an *EVM transcompiler*, preferably as an ewasm contract
50 | * To provide a *metering injector*, preferably as an ewasm contract
51 | * To provide a VM implementation for executing ewasm contracts
52 | * To implement an ewasm backend in the Solidity compiler
53 | * To provide a library and instructions for writing contracts in Rust
54 | * To provide a library and instructions for writing contracts in C
55 |
56 | ### Glossary
57 |
58 | * *Ewasm contract*: a contract adhering to the ewasm specification
59 | * *Ethereum environment interface (EEI)*: a set of methods available to ewasm contracts
60 | * *metering*: the act of measuring execution cost in a deterministic way
61 | * *metering injector*: a transformation tool inserting metering code to an ewasm contract
62 | * *EVM transcompiler*: an EVM bytecode (the current Ethereum VM) to ewasm transcompiler. [See this chapter](./evm_transcompiler.md).
63 |
64 | ### Resources
65 |
66 | * [FAQ](./faq.md)
67 | * [Rationale](./rationale.md)
68 | * [VM semantics](./vm_semantics.md)
69 | * [Ethereum environment interface](./eth_interface.md)
70 | * [Ewasm Contract Interface](./contract_interface.md)
71 | * [System contracts](./system_contracts.md)
72 | * [Backwards compatibility instructions](./backwards_compatibility.md)
73 | * [Original Proposal](https://github.com/ethereum/EIPs/issues/48) (EIP#48)
74 | * [WebAssembly Specification](https://webassembly.github.io/spec/)
75 | * [WebAssembly design documents](https://github.com/WebAssembly/design)
76 |
77 | ### Projects
78 |
79 | * [ewasm-tests](https://github.com/ewasm/ewasm-tests)
80 | * [wasm-metering](https://github.com/ewasm/wasm-metering)
81 | * [ewasm-kernel](https://github.com/ewasm/ewasm-kernel)
82 | * [evm2wasm](https://github.com/ewasm/evm2wasm)
83 | * [ewasm-libc](https://github.com/ewasm/ewasm-libc)
84 | * [assemblyscript-ewasm-api](https://github.com/ewasm/assemblyscript-ewasm-api)
85 | * [ewasm-rust-api](https://github.com/ewasm/ewasm-rust-api)
86 |
87 | ### Design Process & Contributing
88 | For now, high-level design discussions should continue to be held in the design repository, via issues and pull requests. Feel free to file [issues](https://github.com/ethereum/ewasm-design/issues).
89 |
90 | ## Chat
91 | [Gitter](https://gitter.im/ewasm/Lobby)
92 |
--------------------------------------------------------------------------------
/assets/1.73x2-hexagon-sticker-ewasm-with-border.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/1.73x2-hexagon-sticker-ewasm-with-border.pdf
--------------------------------------------------------------------------------
/assets/1.73x2-hexagon-sticker-ewasm.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/1.73x2-hexagon-sticker-ewasm.pdf
--------------------------------------------------------------------------------
/assets/blocks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/blocks.png
--------------------------------------------------------------------------------
/assets/ewasm_logo.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo.ai
--------------------------------------------------------------------------------
/assets/ewasm_logo.eps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo.eps
--------------------------------------------------------------------------------
/assets/ewasm_logo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo.pdf
--------------------------------------------------------------------------------
/assets/ewasm_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
35 |
--------------------------------------------------------------------------------
/assets/ewasm_logo_100x141_tr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_100x141_tr.png
--------------------------------------------------------------------------------
/assets/ewasm_logo_100x141_wb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_100x141_wb.png
--------------------------------------------------------------------------------
/assets/ewasm_logo_200x281_tr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_200x281_tr.png
--------------------------------------------------------------------------------
/assets/ewasm_logo_200x281_wb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_200x281_wb.png
--------------------------------------------------------------------------------
/assets/ewasm_logo_300x422_tr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_300x422_tr.png
--------------------------------------------------------------------------------
/assets/ewasm_logo_300x422_wb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_300x422_wb.png
--------------------------------------------------------------------------------
/assets/ewasm_logo_50x70_tr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_50x70_tr.png
--------------------------------------------------------------------------------
/assets/ewasm_logo_50x70_wb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_50x70_wb.png
--------------------------------------------------------------------------------
/assets/ewasm_logo_text.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
135 |
--------------------------------------------------------------------------------
/assets/ewasm_logo_text_update.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/ewasm_logo_text_update.ai
--------------------------------------------------------------------------------
/assets/if.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/if.png
--------------------------------------------------------------------------------
/assets/logo_sq_tr_128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_tr_128x128.png
--------------------------------------------------------------------------------
/assets/logo_sq_tr_256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_tr_256x256.png
--------------------------------------------------------------------------------
/assets/logo_sq_tr_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_tr_32x32.png
--------------------------------------------------------------------------------
/assets/logo_sq_tr_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_tr_512x512.png
--------------------------------------------------------------------------------
/assets/logo_sq_tr_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_tr_64x64.png
--------------------------------------------------------------------------------
/assets/logo_sq_wb_128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_wb_128x128.png
--------------------------------------------------------------------------------
/assets/logo_sq_wb_256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_wb_256x256.png
--------------------------------------------------------------------------------
/assets/logo_sq_wb_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_wb_32x32.png
--------------------------------------------------------------------------------
/assets/logo_sq_wb_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_wb_512x512.png
--------------------------------------------------------------------------------
/assets/logo_sq_wb_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ewasm/design/8ecee83f9ac58aa5f81b01498bc729789535bc29/assets/logo_sq_wb_64x64.png
--------------------------------------------------------------------------------
/backwards_compatibility.md:
--------------------------------------------------------------------------------
1 | # Backwards Compatibility
2 | The current approach to achieving backwards compatibility with EVM1 is to
3 | support both of the instruction sets with the option to transcompiling EVM1 to
4 | ewasm. This approach gives clients optionality when dealing with EVM1 code.
5 | A client can either implement only an ewasm VM and transcompile all of the EVM1
6 | code. Or a client can implement a ewasm VM and EVM1 VM and leave the old code as
7 | is.
8 |
9 | ## Gas Prices
10 | In ewasm we will introduce sub-gas units so that each EVM1 opcode's
11 | transcompiled equivalent ewasm's gas cost is less then the original EM1 opcode's
12 | cost. The fee schedule for ewasm is yet to be specified.
13 |
14 | ## Identification of code
15 | We assume there is some sort of code handler function that all clients have
16 | implemented. The code handler identifies the instruction set type by whether it
17 | starts with Wasm's magic number or not.
18 |
19 | The Wasm magic number is the following byte sequence: `0x00, 0x61, 0x73, 0x6d`.
20 |
21 | ## Solidity
22 | Support of compiling to ewasm can be accomplished by adding a new backend to
23 | the Solidity compiler. Ewasm support for Solidity is part of the MVP.
24 |
25 | ## Transcompiler
26 | A post-MVP goal is to have the transcompiler itself become a contract by
27 | compiling it to ewasm. Once this is accomplished, EVM1 contracts created by
28 | the CREATE op will be transcompiled to ewasm. This will also allow us to assume
29 | that all EVM1 code is now transcompiled ewasm code, which should be reflected
30 | in the state root since the hash of the code is stored in the Merkle trie. Note:
31 | this should still allow clients to fallback to EVM1 VMs if running EVM1 code.
32 |
--------------------------------------------------------------------------------
/comparison.md:
--------------------------------------------------------------------------------
1 | # Wasm
2 | ### Good
3 | * limited well defined non-determinism
4 | * performant (near native speed)
5 | * portable
6 | * will be widely deployed
7 | * AST bytecode makes it easy to decouple metering from the VM
8 |
9 | ### Bad
10 | * not stable yet
11 |
12 | # LLVM IR
13 | ### Good
14 | * very tested
15 | * large community
16 | * was used by Google's PNaCl
17 | * widely deployed
18 |
19 | ### Bad
20 | * not intrinsically portable
21 | * not stable
22 | * large surface (ISA) that VM implementors would have to deal with
23 |
24 | Response from Derek Schuff (one of the engineers for PNaCl) from Google on Wasm vs LLVM
25 |
26 | >I'm guessing you are unfamiliar with PNaCl. This is more or less the approach taken by PNaCl; i.e. use LLVM as the starting point for a wire format. It turns out that LLVM IR/bitcode by itself is neither portable nor stable enough to be used for this purpose, and it is designed for compiler optimizations, it has a huge surface area, much more than is needed for this purpose. PNaCl solves these problems by defining a portable target triple (an architecture called "le32" used instead of e.g. i386 or arm), a subset of LLVM IR, and a stable frozen wire format based on LLVM's bitcode. So this approach (while not as simple as "use LLVM-IR directly") does work. However LLVM's IR and bitcode formats were designed (respectively) for use as a compiler IR and for temporary file serialization for link-time optimization. They were not designed for the goals we have, in particular a small compressed distribution format and fast decoding. We think we can do much better for wasm, with the experience we've gained from PNaCl
27 |
28 | LLVM IR is meant to make compiler optimizations easy to implement, and to represent the constructs and semantics required by C, C++, and other languages on a large variety of operating systems and architectures. This means that by default the IR is not portable (the same program has different representations for different architectures) or stable (it changes over time as optimization and language requirements change). It has representations for a huge variety of information that is useful for implementing mid-level compiler optimizations but is not useful for code generation (but which represents a large surface area for codegen implementers to deal with). It also has undefined behavior (largely similar to that of C and C++) which makes some classes of optimization feasible or more powerful, but which can lead to unpredictable behavior at runtime. LLVM's binary format (bitcode) was designed for temporary on-disk serialization of the IR for link-time optimization, and not for stability or compressibility (although it does have some features for both of those).
29 |
30 | None of these problems are insurmountable. For example PNaCl defines a small portable subset of the IR with reduced undefined behavior, and a stable version of the bitcode encoding. It also employs several techniques to improve startup performance. However, each customization, workaround, and special solution means less benefit from the common infrastructure
31 |
32 |
33 |
34 | # CLI / ECMA-335
35 | ### Good
36 | * Defines a Kernel runtime and CIL subset that should be all we need. (We could use just the CIL intermediate language subset, but that could cut us off from the larger ecosystem.)
37 | * Looks like the kernel can be implemented to be safe and deterministic. I didn't try to analyze much, but safety and security were design goals.
38 | * Stable international standards since 2000.
39 | * Stable .NET and open-source Mono implementations.
40 | * Mature tools and language support, large user base, open source (even from Microsoft).
41 |
42 | ### Bad
43 | * Missing standard SIMD support. (Both Mono and .NET are putting it in, so it should be standard eventually. )
44 | * Missing some of the nicer features of Wasm -- stack machine, not so compact, not AST-based, etc.
45 | * Likely a bigger runtime footprint than Wasm.
46 | * Microsoft.
47 | * Did I mention Microsoft?
48 |
49 | # RISCV
50 | ### Isn't RISCV a purely hardware spec?
51 |
52 | # JVM
53 | ### Nonstarter. Oracle ownership and intellectual property issues.
54 |
55 | # EVM1
56 | ### Good:
57 | * We own it.
58 | * It can evolve to where we need to go.
59 | * Coordination with other projects is optional.
60 | * We have the engineering talent we need.
61 | * We can incorporate wasm and other tech as appropriate.
62 |
63 | ### Bad:
64 | * We own it.
65 | * We will need to maintain and build our own community of developers and users. (This might be a pro.)
66 | * EVM design has some clunkiness that gets in the way of performance and clean evolution.
67 |
68 |
--------------------------------------------------------------------------------
/contract_interface.md:
--------------------------------------------------------------------------------
1 | # Ewasm Contract Interface (ECI) Specification
2 |
3 | The Ewasm Contract Interface (ECI) specifies the structure of a contract module.
4 |
5 | ### Wire format
6 |
7 | Every contract must be stored in the [WebAssembly Binary Encoding](https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md) format (in short, Wasm bytecode).
8 |
9 | ### Imports
10 |
11 | A contract can only import symbols specified in the [Ethereum Environment Interface or EEI](./eth_interface.md).
12 |
13 | In practice, this means that all imports specified by an ewasm module must be from the `ethereum` namespace,
14 | and having a function signature and name directly correspondent to a function specified in the EEI.
15 |
16 | As mentioned below, there is a `debug` namespace as well, but that is disallowed in production systems.
17 |
18 | #### Debug-mode
19 |
20 | Debug-mode is a special VM option, where an additional set of debugging interfaces are available to contracts. On a live VM, any bytecode trying to import these
21 | symbols should be rejected.
22 |
23 | The imports are available under the `debug` namespace:
24 | - `print32(value: i32)` - print value
25 | - `print64(value: i64)` - print value
26 | - `printMem(offset: i32, len: i32)` - print memory segment as printable characters
27 | - `printMemHex(offset: i32, len: i32)` - print memory segment as hex
28 | - `printStorage(pathOffset: i32)` - print storage value as printable characters
29 | - `printStorageHex(pathOffset: i32)` - print storage value as hex
30 |
31 | ### Exports
32 |
33 | A contract must have exactly two exported symbols:
34 | - `memory`: the shared memory space available for the EEI to write into.
35 | - `main`: a function with no parameters and no result value.
36 |
37 | ### Entry point
38 |
39 | The method exported as `main` will be executed by the VM.
40 |
41 | On successful execution, the code should return via a normal code path.
42 |
43 | If it needs to abort due to a failure, an *unreachable* instruction should be executed.
44 |
45 | ### Start function
46 |
47 | The use of a [start function](https://webassembly.github.io/spec/core/syntax/modules.html#start-function) is disallowed.
48 |
49 | The reason for this is that an ewasm VM would need to have access to the memory space of a contract and that must be acquired prior to executing it.
50 | In the [WebAssembly Javascript API](https://webassembly.org/docs/js/) however the start function is executed right during instantiation, which
51 | leaves no time for the client to acquire the memory area.
52 |
53 | *Note:* This decision was made on WebAssembly version 0xb (pre version 1) and should be revisited.
54 |
55 | ### Traps
56 |
57 | If execution of wasm code triggers the wasm _trap_, the contract execution is
58 | terminated with failure and all remaining gas is consumed (OOG-like exception).
59 | This includes execution of `unreachable` instruction.
60 |
--------------------------------------------------------------------------------
/determining_wasm_gas_costs.md:
--------------------------------------------------------------------------------
1 | # Determining ewasm gas costs
2 |
3 | The goal of this document is to describe the process of determining gas costs
4 | for ewasm instructions.
5 |
6 | Each Wasm opcode is assigned an appropriate Intel IA-32 (x86) opcode (or a
7 | series of opcodes). These opcodes have a fixed cycle count (called *latency*
8 | by Intel). We are selecting one specific CPU model from the Haswell architecture
9 | (family: `06`, model `3C`). This equals to CPUs produced in 2014.
10 |
11 | **Assumption 1**: This specific Haswell CPU represents a good average of the
12 | Ethereum nodes. We assume that a 2.2 Ghz model is the average.
13 |
14 | According to Intel, the 2.2 Ghz clock rate roughly equals to `2 200 000 000` cycles per second.
15 |
16 | **Assumption 2**: 1 second of CPU execution equals to 10 million gas
17 | (i.e. 1 gas equals to 0.1 µs).
18 |
19 | This equals to **`0.0045` gas per cycle**. (`10 000 000 / 2 200 000 000`)
20 |
21 | To put this in perspective, the average block gas limit as of August 2016 is around
22 | 4.7 million. With this assumption we allow contract execution to take up to 0.5 second
23 | of the 15 seconds block time, which also has to include other processing, including PoW
24 | and network roundtrip times.
25 |
26 | **Assumption 3**: The gas costs are adjusted on a *regular* basis, at least every 3 years.
27 |
28 | We assume that CPUs are continuously improving and the hardware for Ethereum
29 | nodes are upgraded every 3 years (as that matches usual depreciation rates).
30 |
31 | The upgrade procedure is not part of this document, but it is plausible to expect a
32 | dedicated **gas cost oracle** contract will exist in the future, which can be used
33 | by the *metering injection contract*.
34 |
35 | ## Gas vs. *Particles*
36 |
37 | The current gas handling fields do not offer the precision needed assuming that
38 | running Wasm opcodes takes significantly less processing power compared to EVM1
39 | opcodes.
40 |
41 | *Rationale*: EVM1 opcodes operate on 256-bits of data, while Wasm opcodes are limited
42 | to at most 64-bits, which results in executing four instructions in the best
43 | case to match EVM1. Most arithmetic instructions in EVM1 cost 3 gas, which would
44 | amount to 0.75 gas for most 64-bit Wasm instructions.
45 |
46 | Internally, ewasm gas measurements should be recorded in a 64 bit variable
47 | with 4 decimal digits precision. We call this *particles*. It is a minor
48 | implementation detail actually using integers and converting the below gas costs
49 | appropriately.
50 |
51 | When converting the *particles* count to Ethereum gas, it has to be divided by
52 | `10000` and has to be rounded up. If the result is less than `0`, then it should equal to `1`.
53 |
54 | ## Gas costs of individual instructions
55 |
56 | The formula for determining the gas cost is: ` * `
57 |
58 | ### Registers
59 | |Opcode |Cycle | IA-32 eqv. |Gas |
60 | |-----------|------|------------|--------|
61 | |get_local | 3 | MOV | 0.0135
62 | |set_local | 3 | MOV | 0.0135
63 | |tee_local | 3 | MOV | 0.0135
64 | |get_global | 3 | MOV | 0.0135
65 | |set_global | 3 | MOV | 0.0135
66 |
67 | ### Memory
68 | |Opcode |Cycle | IA-32 eqv. |Gas |
69 | |--------------|------|------------|--------|
70 | |i32.load8_s | 3 | MOV | 0.0135
71 | |i32.load8_u | 3 | MOV | 0.0135
72 | |i32.load16_s | 3 | MOV | 0.0135
73 | |i32.load16_u | 3 | MOV | 0.0135
74 | |i32.load | 3 | MOV | 0.0135
75 | |i64.load8_s | 3 | MOV | 0.0135
76 | |i64.load8_u | 3 | MOV | 0.0135
77 | |i64.load16_s | 3 | MOV | 0.0135
78 | |i64.load16_u | 3 | MOV | 0.0135
79 | |i64.load32_s | 3 | MOV | 0.0135
80 | |i64.load32_u | 3 | MOV | 0.0135
81 | |i64.load | 3 | MOV | 0.0135
82 | |grow_memory | ? | (breaking out from the VM)
83 | |current_memory| ? | (breaking out from the VM)
84 |
85 | ### Flow Control
86 | |Opcode |Cycle | IA-32 eqv. |
87 | |-----------|------|------------|
88 | |nop | ? |
89 | |block | 0 | (this is only a grouping)
90 | |loop | 0 | (same as block)
91 | |if | 0 | (only a grouping, then/else counts)
92 | |then | 2 | JMP (near)
93 | |else | 2 | JMP (near)
94 | |br | 2 | JMP (near)
95 | |br_if | 3 | CMP, JMP (near)
96 | |br_table | 2 | JMP (near)
97 | |return | 2 | RET or JMP
98 |
99 | ### Calls
100 | |Opcode |Cycle | IA-32 eqv. |
101 | |-------------|------|------------|
102 | |call | 2 | CALL (near)
103 | |call_indirect| ? | CALL (far) (breaking out from the VM)
104 | |call_import | ? | CALL (far) (breaking out from the VM)
105 |
106 | ### Constants
107 | |Opcode |Cycle | IA-32 eqv. |
108 | |-----------|------|------------|
109 | |i32.const | 0 |
110 | |i64.const | 0 |
111 |
112 |
113 | ### 32-bit Integer operators
114 | |Opcode |Cycle | IA-32 eqv. | Gas |
115 | |-----------|------|------------|--------|
116 | |i32.add |1 | ADD | 0.0045
117 | |i32.sub |1 | SUB | 0.0045
118 | |i32.mul |3 | MUL | 0.0135
119 | |i32.div_s |80 | DIV | 0.36
120 | |i32.div_u |80 | DIV | 0.36
121 | |i32.rem_s |80 | DIV | 0.36
122 | |i32.rem_u |80 | DIV | 0.36
123 | |i32.and |1 | AND | 0.0045
124 | |i32.or |1 | OR | 0.0045
125 | |i32.xor |1 | XOR | 0.0045
126 | |i32.shl |1.5 | SHL | 0.0067
127 | |i32.shr_u |1.5 | SHR | 0.0067
128 | |i32.shr_s |1.5 | SHR | 0.0067
129 | |i32.rotl |2 | ROL | 0.0090
130 | |i32.rotr |2 | ROR | 0.0090
131 | |i32.eq |1 | CMP | 0.0045
132 | |i32.eqz |1 | CMP | 0.0045
133 | |i32.ne |1 | CMP | 0.0045
134 | |i32.lt_s |1 | CMP | 0.0045
135 | |i32.lt_u |1 | CMP | 0.0045
136 | |i32.le_s |1 | CMP | 0.0045
137 | |i32.le_u |1 | CMP | 0.0045
138 | |i32.gt_s |1 | CMP | 0.0045
139 | |i32.gt_u |1 | CMP | 0.0045
140 | |i32.ge_s |1 | CMP | 0.0045
141 | |i32.ge_u |1 | CMP | 0.0045
142 | |i32.clz |105 | (clz) | 0.4725
143 | |i32.ctz |105 | (ctz) | 0.4725
144 | |i32.popcnt |? |
145 |
146 | ### 64-bit Integer operators
147 | |Opcode |Cycle | IA-32 eqv. | Gas |
148 | |-----------|------|------------|--------|
149 | |i64.add |1 | ADD | 0.0045
150 | |i64.sub |1 | SUB | 0.0045
151 | |i64.mul |3 | MUL | 0.0135
152 | |i64.div_s |80 | DIV | 0.36
153 | |i64.div_u |80 | DIV | 0.36
154 | |i64.rem_s |80 | DIV | 0.36
155 | |i64.rem_u |80 | DIV | 0.36
156 | |i64.and |1 | AND | 0.0045
157 | |i64.or |1 | OR | 0.0045
158 | |i64.xor |1 | XOR | 0.0045
159 | |i64.shl |1.5 | SHL | 0.0067
160 | |i64.shr_u |1.5 | SHR | 0.0067
161 | |i64.shr_s |1.5 | SHR | 0.0067
162 | |i64.rotl |2 | ROL | 0.0090
163 | |i64.rotr |2 | ROR | 0.0090
164 | |i64.eq |1 | CMP | 0.0045
165 | |i64.eqz |1 | CMP | 0.0045
166 | |i64.ne |1 | CMP | 0.0045
167 | |i64.lt_s |1 | CMP | 0.0045
168 | |i64.lt_u |1 | CMP | 0.0045
169 | |i64.le_s |1 | CMP | 0.0045
170 | |i64.le_u |1 | CMP | 0.0045
171 | |i64.gt_s |1 | CMP | 0.0045
172 | |i64.gt_u |1 | CMP | 0.0045
173 | |i64.ge_s |1 | CMP | 0.0045
174 | |i64.ge_u |1 | CMP | 0.0045
175 | |i64.clz |? |
176 | |i64.ctz |? |
177 | |i64.popcnt |? |
178 |
179 | ### Datatype conversions, truncations, reinterpretations, promotions, and demotions
180 | |Opcode |Cycle | IA-32 eqv. | Gas |
181 | |----------------|------|------------|--------|
182 | |i32.wrap/i64 |3 | MOV | 0.0135
183 | |i64.extend_s/i32|? | (signextend)
184 | |i64.extend_u/i32|3 | MOV | 0.0135
185 |
186 | ### Type-parametric operators.
187 | |Opcode |Cycle | IA-32 eqv. | Gas |
188 | |-----------|------|------------|--------|
189 | |drop |3 | MOV | 0.0135
190 | |select |3 | CMP, JMP | 0.0135
191 |
192 |
193 | ### Other
194 | |Opcode |Cycle | IA-32 eqv. | Gas |
195 | |-----------|------|------------|--------|
196 | |unreachable|0 | (breaking out from the VM - or *INT3*)
197 |
198 | ## Notes about complex instructions
199 |
200 | Some of the above instructions are complex and cannot be mapped 1-by-1 to a machine
201 | instruction. For them we assume the below algorithms and calculate gas based on the
202 | component costs.
203 |
204 | ### i32.clz
205 |
206 | Number of leading 0-bits within 32 bits.
207 |
208 | (Based on *Warren, Section 5-3: Counting Leading 0's*:)
209 |
210 | ```
211 | function clz(x)
212 | if x = 0 return 32
213 | n ← 0
214 | if (x & 0xFFFF0000) = 0: n ← n + 16, x ← x << 16
215 | if (x & 0xFF000000) = 0: n ← n + 8, x ← x << 8
216 | if (x & 0xF0000000) = 0: n ← n + 4, x ← x << 4
217 | if (x & 0xC0000000) = 0: n ← n + 2, x ← x << 2
218 | if (x & 0x80000000) = 0: n ← n + 1
219 | return n
220 | ```
221 |
222 | For an implementation in WebAssembly, see Appendix A.
223 |
224 | Counting the individual instructions results in:
225 | - 6 `if`
226 | - 6 `then`
227 | - 2 `return`
228 | - 5 `and`
229 | - 5 `eqz`,
230 | - 11 `get_local`,
231 | - 11 `set_local`,
232 | - 5 `add`,
233 | - 5 `shl`
234 |
235 | These amount to a total of 104.5 cycles in the worst case.
236 |
237 | Note: `clz` exists natively on most common CPUs, including Intel and ARM CPUs.
238 | We could consider it native for the purposes of Ethereum and assign a lower gas cost.
239 |
240 | ### i32.ctz
241 |
242 | Number of trailing 0-bits within 32 bits.
243 |
244 | (Based on *Warren, Section 5-4: Counting Trailing 0's.*:)
245 | ```
246 | function ctz (x)
247 | if x = 0 return 32
248 | n ← 0
249 | if (x & 0x0000FFFF) = 0: n ← n + 16, x ← x >> 16
250 | if (x & 0x000000FF) = 0: n ← n + 8, x ← x >> 8
251 | if (x & 0x0000000F) = 0: n ← n + 4, x ← x >> 4
252 | if (x & 0x00000003) = 0: n ← n + 2, x ← x >> 2
253 | if (x & 0x00000001) = 0: n ← n + 1
254 | return n
255 | ```
256 |
257 | This algorithm has the very same steps as `i32.clz` and therefore their cost equals.
258 |
259 | Note: `ctz` does not exists natively on ARM CPUs. ARM should be considered an
260 | important platform for Ethereum light clients and therefore it is sensible to assign
261 | a gas cost based on a complex implementation.
262 |
263 | ### i32.popcnt
264 |
265 | Number of 1-bits within 32 bits.
266 |
267 | **TBD**
268 |
269 | Note: `popcnt` is natively supported by recent CPUs, mostly through SIMD extensions only.
270 |
271 | ### i64.clz
272 |
273 | Number of leading 0-bits within 64 bits.
274 |
275 | **TBD**
276 |
277 | ### i64.ctz
278 |
279 | Number of trailing 0-bits within 64 bits.
280 |
281 | **TBD**
282 |
283 | ### i64.popcnt
284 |
285 | Number of 1-bits within 64 bits.
286 |
287 | **TBD**
288 |
289 | ### i64.extend_s/i32
290 |
291 | Sign extend i32 to i64.
292 |
293 | Given WebAssembly supports both arithmetic (`shr_s`) and logical right shifts
294 | (`shr_u`) it is fairly simple to implement:
295 |
296 | ```
297 | function signextend (x)
298 | return (x << 32) >>> 32
299 | ```
300 |
301 | This cost equals the sum of `i64.shl` and `i64.shr_s`, ? cycles.
302 |
303 | **TBD**
304 |
305 | ### select
306 |
307 | Ternary operator.
308 |
309 | **TBD**
310 |
311 | ### breaking out of the VM
312 |
313 | Any instruction pausing the VM and transferring data between the ewasm contract
314 | and the host is *breaking out of the VM*.
315 |
316 | These instructions include:
317 | - `current_memory`
318 | - `grow_memory`
319 | - `call_indirect`
320 | - `call_import`
321 |
322 | **TBD**
323 |
324 | ## Appendix A: i32.clz in WebAssembly
325 |
326 | ```
327 | (func $clz
328 | (param $x i32)
329 | (result i32)
330 |
331 | (local $n i32)
332 |
333 | (if (i32.eqz (get_local $x))
334 | (then
335 | (return (i32.const 32))
336 | )
337 | )
338 |
339 | (set_local $n (i32.const 0))
340 |
341 | (if (i32.eqz (i32.and (get_local $x) (i32.const 0xffff0000))
342 | (then
343 | (set_local $n (i32.add (get_local $n) (i32.const 16)))
344 | (set_local $x (i32.shl (get_local $x) (i32.const 16)))
345 | )
346 | )
347 |
348 | (if (i32.eqz (i32.and (get_local $x) (i32.const 0xff000000))
349 | (then
350 | (set_local $n (i32.add (get_local $n) (i32.const 8)))
351 | (set_local $x (i32.shl (get_local $x) (i32.const 8)))
352 | )
353 | )
354 |
355 | (if (i32.eqz (i32.and (get_local $x) (i32.const 0xf0000000))
356 | (then
357 | (set_local $n (i32.add (get_local $n) (i32.const 4)))
358 | (set_local $x (i32.shl (get_local $x) (i32.const 4)))
359 | )
360 | )
361 |
362 | (if (i32.eqz (i32.and (get_local $x) (i32.const 0xc0000000))
363 | (then
364 | (set_local $n (i32.add (get_local $n) (i32.const 2)))
365 | (set_local $x (i32.shl (get_local $x) (i32.const 2))
366 | )
367 | )
368 |
369 | (if (i32.eqz (i32.and (get_local $x) (i32.const 0x80000000))
370 | (then
371 | (set_local $n (i32.add (get_local $n) (i32.const 1)))
372 | )
373 | )
374 |
375 | (return (get_local $n))
376 | )
377 | ```
378 |
379 | ## References
380 |
381 | - Appendix C of *Architecture Optimization Manual* (http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html)
382 | - Haswell CPU family (http://ark.intel.com/products/codename/42174/Haswell)
383 | - Instruction tables by Agner Fog: http://www.agner.org/optimize/instruction_tables.pdf
384 | - EVM 1.0 gas costs (https://docs.google.com/spreadsheets/d/1m89CVujrQe5LAFJ8-YAUCcNK950dUzMQPMJBxRtGCqs/edit#gid=0)
385 | - Warren, Henry S. (2003). Hacker's Delight (1st ed.). Boston, Mass.: Addison-Wesley. ISBN 0-201-91465-4
386 |
--------------------------------------------------------------------------------
/eth_interface.md:
--------------------------------------------------------------------------------
1 | # Ethereum Environment Interface (EEI) Specification
2 |
3 | The Ethereum Environment Interface exposes the core Ethereum API to the ewasm environment. The Ethereum [module](https://github.com/WebAssembly/design/blob/master/Modules.md) will be implemented in the Ethereum client's native language. All parameters and returns are restricted to 32 or 64 bit integers. Floats are disallowed.
4 |
5 | # Data types
6 |
7 | We define the following Ethereum data types:
8 | - `bytes`: an array of bytes with unrestricted length
9 | - `bytes32`: an array of 32 bytes
10 | - `address`: an array of 20 bytes
11 | - `u128`: a 128 bit number, represented as a 16 bytes long little endian unsigned integer in memory
12 | - `u256`: a 256 bit number, represented as a 32 bytes long little endian unsigned integer in memory
13 |
14 | We also define the following WebAssembly data types:
15 | - `i32`: same as `i32` in WebAssembly
16 | - `i32ptr`: same as `i32` in WebAssembly, but treated as a pointer to a WebAssembly memory offset
17 | - `i64`: same as `i64` in WebAssembly
18 |
19 | # API
20 |
21 | ## useGas
22 |
23 | Subtracts an amount to the gas counter
24 |
25 | **Parameters**
26 |
27 | - `amount` **i64** the amount to subtract to the gas counter
28 |
29 | **Returns**
30 |
31 | *nothing*
32 |
33 | ## getAddress
34 |
35 | Gets address of currently executing account and stores it in memory at the given
36 | offset.
37 |
38 | **Parameters**
39 |
40 | - `resultOffset` **i32ptr** the memory offset at which the address is to be stored (`address`)
41 |
42 | **Returns**
43 |
44 | *nothing*
45 |
46 | **Trap conditions**
47 |
48 | - store to memory at `resultOffset` results in out of bounds access.
49 |
50 | ## getExternalBalance
51 |
52 | Gets balance of the given account and loads it into memory at the given
53 | offset.
54 |
55 | **Parameters**
56 |
57 | - `addressOffset` **i32ptr** the memory offset to load the address from (`address`)
58 | - `resultOffset` **i32ptr** the memory offset to load the balance into (`u128`)
59 |
60 | **Returns**
61 |
62 | *nothing*
63 |
64 | **Trap conditions**
65 |
66 | - load from memory at `addressOffset` results in out of bounds access,
67 | - store to memory at `resultOffset` results in out of bounds access.
68 |
69 | ## getBlockHash
70 |
71 | Gets the hash of one of the 256 most recent complete blocks.
72 |
73 | **Parameters**
74 |
75 | - `number` **i64** which block to load
76 | - `resultOffset` **i32ptr** the memory offset to load the hash into (`bytes32`)
77 |
78 | **Returns**
79 |
80 | `result` **i32** Returns 0 on success and 1 on failure
81 |
82 | *Note:* in case of failure, the output memory pointed by `resultOffset` is unchanged.
83 |
84 | **Trap conditions**
85 |
86 | - store to memory at `resultOffset` results in out of bounds access (also checked on failure).
87 |
88 | ## call
89 |
90 | Sends a message with arbitrary data to a given address path
91 |
92 | **Parameters**
93 |
94 | - `gas` **i64** the gas limit
95 | - `addressOffset` **i32ptr** the memory offset to load the address from (`address`)
96 | - `valueOffset` **i32ptr** the memory offset to load the value from (`u128`)
97 | - `dataOffset` **i32ptr** the memory offset to load data from (`bytes`)
98 | - `dataLength` **i32** the length of data
99 |
100 | **Returns**
101 |
102 | `result` **i32** Returns 0 on success, 1 on failure and 2 on `revert`
103 |
104 | **Trap conditions**
105 |
106 | - load `address` from memory at `addressOffset` results in out of bounds access,
107 | - load `u128` from memory at `valueOffset` results in out of bounds access,
108 | - load `dataLength` number of bytes from memory at `dataOffset` results in out of bounds access.
109 |
110 | ## callDataCopy
111 |
112 | Copies the input data in current environment to memory. This pertains to
113 | the input data passed with the message call instruction or transaction.
114 |
115 | **Parameters**
116 |
117 | - `resultOffset` **i32ptr** the memory offset to load data into (`bytes`)
118 | - `dataOffset` **i32** the offset in the input data
119 | - `length` **i32** the length of data to copy
120 |
121 | **Returns**
122 |
123 | *nothing*
124 |
125 | **Trap conditions**
126 |
127 | - load `length` number of bytes from input data buffer at `dataOffset` results in out of bounds access,
128 | - store `length` number of bytes to memory at `resultOffset` results in out of bounds access.
129 |
130 | ## getCallDataSize
131 |
132 | Get size of input data in current environment. This pertains to the input
133 | data passed with the message call instruction or transaction.
134 |
135 | **Parameters**
136 |
137 | *none*
138 |
139 | **Returns**
140 |
141 | `callDataSize` **i32**
142 |
143 | ## callCode
144 |
145 | Message-call into this account with an alternative account's code.
146 |
147 | **Parameters**
148 |
149 | - `gas` **i64** the gas limit
150 | - `addressOffset` **i32ptr** the memory offset to load the address from (`address`)
151 | - `valueOffset` **i32ptr** the memory offset to load the value from (`u128`)
152 | - `dataOffset` **i32ptr** the memory offset to load data from (`bytes`)
153 | - `dataLength` **i32** the length of data
154 |
155 | **Returns**
156 |
157 | `result` **i32** Returns 0 on success, 1 on failure and 2 on `revert`
158 |
159 | **Trap conditions**
160 |
161 | - load `address` from memory at `addressOffset` results in out of bounds access,
162 | - load `u128` from memory at `valueOffset` results in out of bounds access,
163 | - load `dataLength` number of bytes from memory at `dataOffset` results in out of bounds access.
164 |
165 | ## callDelegate
166 |
167 | Message-call into this account with an alternative account’s code, but
168 | persisting the current values for sender and value.
169 |
170 | **Parameters**
171 |
172 | - `gas` **i64** the gas limit
173 | - `addressOffset` **i32ptr** the memory offset to load the address from (`address`)
174 | - `dataOffset` **i32ptr** the memory offset to load data from (`bytes`)
175 | - `dataLength` **i32** the length of data
176 |
177 | **Returns**
178 |
179 | `result` **i32** Returns 0 on success, 1 on failure and 2 on `revert`
180 |
181 | **Trap conditions**
182 |
183 | - load `address` from memory at `addressOffset` results in out of bounds access,
184 | - load `dataLength` number of bytes from memory at `dataOffset` results in out of bounds access.
185 |
186 | ## callStatic
187 |
188 | Sends a message with arbitrary data to a given address path, but disallow state
189 | modifications. This includes `log`, `create`, `selfdestruct` and `call` with a non-zero
190 | value.
191 |
192 | **Parameters**
193 |
194 | - `gas` **i64** the gas limit
195 | - `addressOffset` **i32ptr** the memory offset to load the address from (`address`)
196 | - `dataOffset` **i32ptr** the memory offset to load data from (`bytes`)
197 | - `dataLength` **i32** the length of data
198 |
199 | **Returns**
200 |
201 | `result` **i32** Returns 0 on success, 1 on failure and 2 on `revert`
202 |
203 | **Trap conditions**
204 |
205 | - load `address` from memory at `addressOffset` results in out of bounds access,
206 | - load `dataLength` number of bytes from memory at `dataOffset` results in out of bounds access.
207 |
208 | ## storageStore
209 |
210 | Store 256-bit a value in memory to persistent storage
211 |
212 | **Parameters**
213 |
214 | - `pathOffset` **i32ptr** the memory offset to load the path from (`bytes32`)
215 | - `valueOffset` **i32ptr** the memory offset to load the value from (`bytes32`)
216 |
217 | **Returns**
218 |
219 | *nothing*
220 |
221 | **Trap conditions**
222 |
223 | - load `bytes32` from memory at `pathOffset` results in out of bounds access,
224 | - load `bytes32` from memory at `valueOffset` results in out of bounds access.
225 |
226 | ## storageLoad
227 |
228 | Loads a 256-bit a value to memory from persistent storage
229 |
230 | **Parameters**
231 |
232 | - `pathOffset` **i32ptr** the memory offset to load the path from (`bytes32`)
233 | - `resultOffset` **i32ptr** the memory offset to store the result at (`bytes32`)
234 |
235 | **Returns**
236 |
237 | *nothing*
238 |
239 | **Trap conditions**
240 |
241 | - load `bytes32` from memory at `pathOffset` results in out of bounds access,
242 | - store `bytes32` to memory at `resultOffset` results in out of bounds access.
243 |
244 | ## getCaller
245 |
246 | Gets caller address and loads it into memory at the given offset. This is
247 | the address of the account that is directly responsible for this execution.
248 |
249 | **Parameters**
250 |
251 | - `resultOffset` **i32ptr** the memory offset to load the address into (`address`)
252 |
253 | **Returns**
254 |
255 | *nothing*
256 |
257 | **Trap conditions**
258 |
259 | - store `address` to memory at `resultOffset` results in out of bounds access.
260 |
261 | ## getCallValue
262 |
263 | Gets the deposited value by the instruction/transaction responsible for
264 | this execution and loads it into memory at the given location.
265 |
266 | **Parameters**
267 |
268 | - `resultOffset` **i32ptr** the memory offset to load the value into (`u128`)
269 |
270 | **Returns**
271 |
272 | *nothing*
273 |
274 | **Trap conditions**
275 |
276 | - store `u128` to memory at `resultOffset` results in out of bounds access.
277 |
278 | ## codeCopy
279 |
280 | Copies the code running in current environment to memory.
281 |
282 | **Parameters**
283 |
284 | - `resultOffset` **i32ptr** the memory offset to load the result into (`bytes`)
285 | - `codeOffset` **i32** the offset within the code
286 | - `length` **i32** the length of code to copy
287 |
288 | **Returns**
289 |
290 | *nothing*
291 |
292 | **Trap conditions**
293 |
294 | - load `length` number of bytes from the current code buffer at `codeOffset` results in out of bounds access,
295 | - store `length` number of bytes to memory at `resultOffset` results in out of bounds access.
296 |
297 | ## getCodeSize
298 |
299 | Gets the size of code running in current environment.
300 |
301 | **Parameters**
302 |
303 | *none*
304 |
305 | **Returns**
306 |
307 | `codeSize` **i32**
308 |
309 | ## getBlockCoinbase
310 |
311 | Gets the block’s beneficiary address and loads into memory.
312 |
313 | **Parameters**
314 |
315 | - `resultOffset` **i32ptr** the memory offset to load the coinbase address into (`address`)
316 |
317 | **Returns**
318 |
319 | *nothing*
320 |
321 | **Trap conditions**
322 |
323 | - store `address` to memory at `resultOffset` results in out of bounds access.
324 |
325 | ## create
326 |
327 | Creates a new contract with a given value.
328 |
329 | **Parameters**
330 |
331 | - `valueOffset` **i32ptr** the memory offset to load the value from (`u128`)
332 | - `dataOffset` **i32ptr** the memory offset to load the code for the new contract from (`bytes`)
333 | - `dataLength` **i32** the data length
334 | - `resultOffset` **i32ptr** the memory offset to write the new contract address to (`address`)
335 |
336 | *Note*: `create` will clear the return buffer in case of success or may fill it with data coming from `revert`.
337 |
338 | **Returns**
339 |
340 | `result` **i32** Returns 0 on success, 1 on failure and 2 on `revert`
341 |
342 | **Trap conditions**
343 |
344 | - load `u128` from memory at `valueOffset` results in out of bounds access,
345 | - load `dataLength` number of bytes from memory at `dataOffset` results in out of bounds access.
346 | - store `address` to memory at `resultOffset` results in out of bounds access.
347 |
348 | ## getBlockDifficulty
349 |
350 | Get the block’s difficulty.
351 |
352 | **Parameters**
353 |
354 | - `resultOffset` **i32ptr** the memory offset to load the difficulty into (`u256`)
355 |
356 | **Returns**
357 |
358 | *nothing*
359 |
360 | **Trap conditions**
361 |
362 | - store `u256` to memory at `resultOffset` results in out of bounds access.
363 |
364 | ## externalCodeCopy
365 |
366 | Copies the code of an account to memory.
367 |
368 | **Parameters**
369 |
370 | - `addressOffset` **i32ptr** the memory offset to load the address from (`address`)
371 | - `resultOffset` **i32ptr** the memory offset to load the result into (`bytes`)
372 | - `codeOffset` **i32** the offset within the code
373 | - `length` **i32** the length of code to copy
374 |
375 | **Returns**
376 |
377 | *nothing*
378 |
379 | **Trap conditions**
380 |
381 | - load `address` from memory at `addressOffset` results in out of bounds access,
382 | - load `length` number of bytes from the account code buffer at `codeOffset` results in out of bounds access,
383 | - store `length` number of bytes to memory at `resultOffset` results in out of bounds access.
384 |
385 | ## getExternalCodeSize
386 |
387 | Get size of an account’s code.
388 |
389 | **Parameters**
390 |
391 | - `addressOffset` **i32ptr** the memory offset to load the address from (`address`)
392 |
393 | **Returns**
394 |
395 | `extCodeSize` **i32**
396 |
397 | **Trap conditions**
398 |
399 | - load `address` from memory at `addressOffset` results in out of bounds access.
400 |
401 | ## getGasLeft
402 |
403 | Returns the current gasCounter
404 |
405 | **Parameters**
406 |
407 | *none*
408 |
409 | **Returns**
410 |
411 | `gasLeft` **i64**
412 |
413 | ## getBlockGasLimit
414 |
415 | Get the block’s gas limit.
416 |
417 | **Parameters**
418 |
419 | *none*
420 |
421 | **Returns**
422 |
423 | `blockGasLimit` **i64**
424 |
425 | ## getTxGasPrice
426 |
427 | Gets price of gas in current environment.
428 |
429 | **Parameters**
430 |
431 | - `resultOffset` **i32ptr** the memory offset to write the value to (`u128`)
432 |
433 | **Returns**
434 |
435 | *nothing*
436 |
437 | **Trap conditions**
438 |
439 | - store `u128` to memory at `resultOffset` results in out of bounds access.
440 |
441 | ## log
442 |
443 | Creates a new log in the current environment
444 |
445 | **Parameters**
446 |
447 | - `dataOffset` **i32ptr** the memory offset to load data from (`bytes`)
448 | - `dataLength` **i32** the data length
449 | - `numberOfTopics` **i32** the number of topics following (0 to 4)
450 | - `topic1` **i32ptr** the memory offset to load topic1 from (`bytes32`)
451 | - `topic2` **i32ptr** the memory offset to load topic2 from (`bytes32`)
452 | - `topic3` **i32ptr** the memory offset to load topic3 from (`bytes32`)
453 | - `topic4` **i32ptr** the memory offset to load topic4 from (`bytes32`)
454 |
455 | **Returns**
456 |
457 | *nothing*
458 |
459 | **Trap conditions**
460 |
461 | - load `dataLength` number of bytes from memory at `dataOffset` results in out of bounds access,
462 | - `numberOfTopics` is greater than 4,
463 | - load `bytes32` from memory at `topic1` results in out of bounds access,
464 | - load `bytes32` from memory at `topic2` results in out of bounds access,
465 | - load `bytes32` from memory at `topic3` results in out of bounds access,
466 | - load `bytes32` from memory at `topic4` results in out of bounds access.
467 |
468 | ## getBlockNumber
469 |
470 | Get the block’s number.
471 |
472 | **Parameters**
473 |
474 | *none*
475 |
476 | **Returns**
477 |
478 | `blockNumber` **i64**
479 |
480 | ## getTxOrigin
481 |
482 | Gets the execution's origination address and loads it into memory at the
483 | given offset. This is the sender of original transaction; it is never an
484 | account with non-empty associated code.
485 |
486 | **Parameters**
487 |
488 | - `resultOffset` **i32ptr** the memory offset to load the origin address from (`address`)
489 |
490 | **Returns**
491 |
492 | *nothing*
493 |
494 | **Trap conditions**
495 |
496 | - store `address` to memory at `resultOffset` results in out of bounds access.
497 |
498 | ## finish
499 |
500 | Set the returning output data for the execution. This will halt the execution immediately.
501 |
502 | **Parameters**
503 |
504 | - `dataOffset` **i32ptr** the memory offset of the output data (`bytes`)
505 | - `dataLength` **i32** the length of the output data
506 |
507 | **Returns**
508 |
509 | *doesn't return*
510 |
511 | **Trap conditions**
512 |
513 | - load `dataLength` number of bytes from memory at `dataOffset` results in out of bounds access.
514 |
515 | ## revert
516 |
517 | Set the returning output data for the execution. This will halt the execution immediately and set the execution result to "reverted".
518 |
519 | **Parameters**
520 |
521 | - `dataOffset` **i32ptr** the memory offset of the output data (`bytes`)
522 | - `dataLength` **i32** the length of the output data
523 |
524 | **Returns**
525 |
526 | *doesn't return*
527 |
528 | **Trap conditions**
529 |
530 | - load `dataLength` number of bytes from memory at `dataOffset` results in out of bounds access.
531 |
532 | ## getReturnDataSize
533 |
534 | Get size of current return data buffer to memory. This contains the return data
535 | from the last executed `call`, `callCode`, `callDelegate`, `callStatic` or `create`.
536 |
537 | *Note*: `create` only fills the return data buffer in case of a failure.
538 |
539 | **Parameters**
540 |
541 | *none*
542 |
543 | **Returns**
544 |
545 | `dataSize` **i32**
546 |
547 | ## returnDataCopy
548 |
549 | Copies the current return data buffer to memory. This contains the return data
550 | from last executed `call`, `callCode`, `callDelegate`, `callStatic` or `create`.
551 |
552 | *Note*: `create` only fills the return data buffer in case of a failure.
553 |
554 | **Parameters**
555 |
556 | - `resultOffset` **i32ptr** the memory offset to load data into (`bytes`)
557 | - `dataOffset` **i32** the offset in the return data
558 | - `length` **i32** the length of data to copy
559 |
560 | **Returns**
561 |
562 | *nothing*
563 |
564 | **Trap conditions**
565 |
566 | - load `length` number of bytes from input data buffer at `dataOffset` results in out of bounds access,
567 | - store `length` number of bytes to memory at `resultOffset` results in out of bounds access.
568 |
569 | ## selfDestruct
570 |
571 | Mark account for later deletion and give the remaining balance to the specified
572 | beneficiary address. This will cause a trap and the execution will be aborted immediately.
573 |
574 | **Parameters**
575 |
576 | - `addressOffset` **i32ptr** the memory offset to load the address from (`address`)
577 |
578 | **Returns**
579 |
580 | *doesn't return*
581 |
582 | **Trap conditions**
583 |
584 | - load `address` from memory at `addressOffset` results in out of bounds access.
585 |
586 | ## getBlockTimestamp
587 |
588 | Get the block’s timestamp.
589 |
590 | **Parameters**
591 |
592 | *none*
593 |
594 | **Returns**
595 |
596 | `blockTimestamp` **i64**
597 |
--------------------------------------------------------------------------------
/evm_transcompiler.md:
--------------------------------------------------------------------------------
1 | # EVM Transcompiler
2 |
3 | Transcompiles EVM1 bytecode into ewasm bytecode. It takes EVM bytecode as an input and returns an ewasm compatible bytecode,
4 | which can be executed the same way regular ewasm contracts can.
5 |
6 | When executing it, one must make sure however that host functions dealing with the bytecode in the state
7 | (such as `codeCopy` and `externalCodeCopy`) must always refer to the untransformed EVM1 bytecode.
8 |
9 | The transcompiler is implemented as a contract or a precompiled contract at a specific address.
10 |
--------------------------------------------------------------------------------
/faq.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | Wasm's FAQ can be found [here](https://github.com/WebAssembly/design/blob/master/FAQ.md)
4 |
5 | ## Is ewasm primarily the replacement for EVM?
6 | Currently it is being researched as a replacement instruction set for EVM1. Other instruction sets have been considered but so far Wasm seems the most suitable.
7 |
8 | ## What are alternatives to Wasm?
9 | Some that have been considered are [here](./comparison.md)
10 |
11 | ## What are the benefits?
12 | * Performance
13 | * A well Standardized ISA, that will be widely deployed
14 | * Stack machine; which can decouple metering, make it more performant and can be transformed to any machine on target architecture
15 | * Shared tooling / Broader Tooling Compatibility
16 |
17 | ## What is metering?
18 | Metering VMs is the same concept as electrical power companies have when charging you for the amount of electricity that you used. With VM's we attempt to get a measurement of computation time of some code and instead of electricity used, you are charged for the CPU's time used. We call this metering.
19 |
20 | ## Will Solidity/Serpent be compatible with ewasm, or will another HLL have to be created?
21 | Not off the bat, a transcompiler will have to be created to compile existing EVM code into ewasm. As far as other High level languages you should be able to use a language that can be compiled by LLVM (c/c++/rust/go)
22 |
23 | ## How does ewasm handle non-determinism when a variety of programming languages are allowed to be used?
24 | Part of the project goal is to eliminate nasal-demons. It's in the MVP. There are still a couple of edge case like sign values on NaNs but they can be canonicalized by AST transforms.
25 |
26 | ## Will ewasm be compatible with Wasm?
27 | Yes, the Ethereum System Interface can also be written in Wasm.
28 |
29 | ## Can ewasm be built even if Wasm is not currently complete or will we need to wait for its completion/MVP?
30 | Yes, but we would lose the "Shared tooling" benefit. So It might not make sense.
31 |
32 | ## Does ewasm use synchronous or asynchronous methods?
33 | An answer to this question as well as the reasoning for both can be [read here](./interface_questions.md).
34 |
--------------------------------------------------------------------------------
/fee_schedule.md:
--------------------------------------------------------------------------------
1 | # Fee Schedule
2 |
3 | Fees are charged in three different ways:
4 | - running opcodes
5 | - expanding memory
6 | - calls to EEI methods
7 |
8 | ## Opcodes
9 |
10 | All fees for opcodes are currently 1 gas. This needs to be updated before finalising this specification.
11 |
12 | ### Registers
13 | |Opcode |Price |
14 | |-----------|------|
15 | |get_local | 1 |
16 | |set_local | 1 |
17 | |tee_local | 1 |
18 | |get_global | 1 |
19 | |set_global | 1 |
20 |
21 | ### Memory
22 | |Opcode |Price |
23 | |--------------|------|
24 | |i32.load8_s | 1 |
25 | |i32.load8_u | 1 |
26 | |i32.load16_s | 1 |
27 | |i32.load16_u | 1 |
28 | |i32.load | 1 |
29 | |i64.load8_s | 1 |
30 | |i64.load8_u | 1 |
31 | |i64.load16_s | 1 |
32 | |i64.load16_u | 1 |
33 | |i64.load32_s | 1 |
34 | |i64.load32_u | 1 |
35 | |i64.load | 1 |
36 | |grow_memory | 1 |
37 | |current_memory| 1 |
38 |
39 | ### Flow Control
40 | |Opcode |Price |
41 | |-----------|------|
42 | |nop | 1 |
43 | |block | 1 |
44 | |loop | 1 |
45 | |if | 1 |
46 | |br | 1 |
47 | |br_if | 1 |
48 | |br_table | 1 |
49 | |return | 1 |
50 |
51 | ### Calls
52 | |Opcode |Price |
53 | |-------------|------|
54 | |call | 1 |
55 | |call_indirect| 1 |
56 | |call_import | 1 |
57 |
58 | ### Constants
59 | |Opcode |Price |
60 | |-----------|------|
61 | |i32.const | 1 |
62 | |i64.const | 1 |
63 |
64 |
65 | ### 32-bit Integer operators
66 | |Opcode |Price |
67 | |-----------|------|
68 | |i32.add |1 |
69 | |i32.sub |1 |
70 | |i32.mul |1 |
71 | |i32.div_s |1 |
72 | |i32.div_u |1 |
73 | |i32.rem_s |1 |
74 | |i32.rem_u |1 |
75 | |i32.and |1 |
76 | |i32.or |1 |
77 | |i32.xor |1 |
78 | |i32.shl |1 |
79 | |i32.shr_u |1 |
80 | |i32.shr_s |1 |
81 | |i32.rotl |1 |
82 | |i32.rotr |1 |
83 | |i32.eq |1 |
84 | |i32.ne |1 |
85 | |i32.lt_s |1 |
86 | |i32.le_s |1 |
87 | |i32.lt_u |1 |
88 | |i32.le_u |1 |
89 | |i32.gt_sa |1 |
90 | |i32.ge_s |1 |
91 | |i32.gt_u |1 |
92 | |i32.ge_u |1 |
93 | |i32.clz |1 |
94 | |i32.ctz |1 |
95 | |i32.popcnt |1 |
96 | |i32.eqz |1 |
97 |
98 | ### 64-bit Integer operators
99 | |Opcode |Price |
100 | |-----------|------|
101 | |i64.add |1 |
102 | |i64.sub |1 |
103 | |i64.mul |1 |
104 | |i64.div_s |1 |
105 | |i64.div_u |1 |
106 | |i64.rem_s |1 |
107 | |i64.rem_u |1 |
108 | |i64.and |1 |
109 | |i64.or |1 |
110 | |i64.xor |1 |
111 | |i64.shl |1 |
112 | |i64.shr_u |1 |
113 | |i64.shr_s |1 |
114 | |i64.rotl |1 |
115 | |i64.rotr |1 |
116 | |i64.eq |1 |
117 | |i64.ne |1 |
118 | |i64.lt_s |1 |
119 | |i64.le_s |1 |
120 | |i64.lt_u |1 |
121 | |i64.le_u |1 |
122 | |i64.gt_sa |1 |
123 | |i64.ge_s |1 |
124 | |i64.gt_u |1 |
125 | |i64.ge_u |1 |
126 | |i64.clz |1 |
127 | |i64.ctz |1 |
128 | |i64.popcnt |1 |
129 | |i64.eqz |1 |
130 |
131 | ### Datatype conversions, truncations, reinterpretations, promotions, and demotions
132 | |Opcode |Price |
133 | |----------------|------|
134 | |i32.wrap/i64 |1 |
135 | |i64.extend_s/i32|1 |
136 | |i64.extend_u/i32|1 |
137 |
138 | ### Type-parametric operators.
139 | |Opcode |Price |
140 | |-----------|------|
141 | |drop |1 |
142 | |select |1 |
143 |
144 |
145 | ### Other
146 | |Opcode |Price |
147 | |-----------|------|
148 | |unreachable|1 |
149 |
150 |
151 | ## Expanding memory
152 |
153 | Memory can be expanded in pages, where a page corresponds to 65536 bytes of space.
154 |
155 | The EVM1 formula for extending memory is `words * 3 + words ^ 2 / 512` where `word` corresponds to 32 bytes.
156 |
157 | From this we can calculate that a 65536 byte page should cost 14336 gas.
158 |
159 |
160 | ## Calls to the EEI
161 |
162 | Calls to the EEI are charged the same price as their equivalent EVM1 opcode.
163 |
164 | | Method | EVM1 Opcode |
165 | |----------------------|--------------|
166 | | getAddress | ADDRESS |
167 | | getBalance | BALANCE |
168 | | getBlockHash | BLOCKHASH |
169 | | call | CALL |
170 | | callDataCopy | CALLDATACOPY |
171 | | getCallDataSize | CALLDATASIZE |
172 | | callCode | CALLCODE |
173 | | callDelegate | DELEGATECALL |
174 | | storageStore | SSTORE |
175 | | storageLoad | SLOAD |
176 | | getCaller | CALLER |
177 | | getCallValue | CALLVALUE |
178 | | codeCopy | CODECOPY |
179 | | getCodeSize | CODESIZE |
180 | | getBlockCoinbase | COINBASE |
181 | | create | CREATE |
182 | | getBlockDifficulty | DIFFICULTY |
183 | | externalCodeCopy | EXTCODECOPY |
184 | | getExternalCodeSize | EXTCODESIZE |
185 | | getGasLeft | GAS |
186 | | getBlockGasLimit | GASLIMIT |
187 | | getTxGasPrice | GASPRICE |
188 | | log | LOG*n* |
189 | | getBlockNumber | NUMBER |
190 | | getTxOrigin | ORIGIN |
191 | | return | RETURN |
192 | | selfDestruct | SELFDESTRUCT |
193 | | getBlockTimestamp | TIMESTAMP |
194 |
--------------------------------------------------------------------------------
/interface_questions.md:
--------------------------------------------------------------------------------
1 | ## ewasm interface methods: synchronous vs asynchronous
2 |
3 | One design question that arose while prototyping ewasm in Javascript is the issue of a synchronous versus an asynchronous [Ethereum Environment Interface aka EEI specification](./eth_interface.md). The initial design specified synchronous EEI methods: `storageLoad`, `storageStore`, `callDelegate`, etc. These environment methods are provided to the wasm VM as "host functions" imported by the wasm instance. When running browser-based wasm VMs (e.g. in Chrome or Firefox), these host functions are implemented in Javascript. By contrast, in a wasm VM such as [binaryen](https://github.com/WebAssembly/binaryen), a C++ wasm interpreter, the host functions are implemented in C++. A C++ implementation has full control over environment method execution, and is fully synchronous by default. When some wasm code calls to a host function, the wasm instance will pause and wait until the host function returns, and then continue with wasm execution.
4 |
5 | Javascript, however, has a [never blocking](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Never_blocking) event loop. As a consequence, when a browser wasm instance calls to a host function, the host function cannot use any callbacks (or Promises, async/await, etc.) because the event loop continues wasm execution without waiting. Thus, _synchronously_ returning a Javascript host function result from a callback to a wasm instance is [not currently supported](https://github.com/WebAssembly/design/issues/720).
6 |
7 | Asynchronous ewasm methods [were proposed](https://github.com/ewasm/design/pull/48) to overcome this limitation of JS wasm environments. In the asynchronous version, contract code has callback entry points. This allows the wasm instance to call the host function, terminate, and then restart the instance at the callback entry point.
8 |
9 | Here are example ewasm contracts comparing the two versions:
10 |
11 | #### synchronous
12 |
13 | ```
14 | ;; address 5d48c1018904a172886829bbbd9c6f4a2d06c47b has a balance of 0xde0b6b3a7640000 (1 ETH)
15 | (module
16 | ;; syhchronous getBalance method
17 | ;; params are addressOffset, resultOffset
18 | (import "ethereum" "getBalance" (func $getBalance (param i32 i32)))
19 | (memory 1 )
20 | ;; address memory location at offset 0
21 | (data (i32.const 0) "\5d\48\c1\01\89\04\a1\72\88\68\29\bb\bd\9c\6f\4a\2d\06\c4\7b")
22 | (export "memory" (memory 0))
23 | (export "main" (func $main))
24 | (func $main
25 | ;; pass 0 as the addressOffset, 100 as the resultOffset
26 | (call $getBalance (i32.const 0) (i32.const 100))
27 | ;; getBalance host function result written to memory location 100
28 | (if (i64.eq (i64.load (i32.const 100)) (i64.const 0xde0b6b3a7640000))
29 | (return)
30 | )
31 | (unreachable) ;; throw if getBalance result not equal to 1 ETH
32 | )
33 | )
34 | ```
35 |
36 |
37 | #### async proposal, example using getBalance
38 |
39 | ```
40 | ;; address 5d48c1018904a172886829bbbd9c6f4a2d06c47b has a balance of 0xde0b6b3a7640000 (1 ETH)
41 | (module
42 | ;; asynchronous getBalance method
43 | ;; params are addressOffset, resultOffset, and callbackIndex
44 | (import "ethereum" "getBalance" (func $balance (param i32 i32 i32)))
45 | (memory 1)
46 | (data (i32.const 0) "\5d\48\c1\01\89\04\a1\72\88\68\29\bb\bd\9c\6f\4a\2d\06\c4\7b")
47 | (export "memory" (memory 0))
48 | (export "main" (func $main))
49 | (export "1" (func $callback)) ;; callback entry point is an export with name "1"
50 |
51 | (func $main
52 | ;; pass 0 as the address memory location
53 | ;; pass 100 as the result memory location
54 | ;; pass 1 as the callback param
55 | (call $balance (i32.const 0) (i32.const 100) (i32.const 1))
56 | )
57 |
58 | (func $callback
59 | (block
60 | (if (i64.eq (i64.load (i32.const 100)) (i64.const 0xde0b6b3a7640000))
61 | (return)
62 | )
63 | (unreachable) ;; throw if test fails
64 | )
65 | )
66 | )
67 | ```
68 |
69 | After evaluating the trade-offs between the sync and async ewasm interfaces, we've decided to adopt the synchronous version. First, the synchronous interface better matches the EVM execution model, which synchronously executes contract calls. Secondly, although implementing the synchronous interface in Javascript requires inconvenient workarounds, in other programming languages (C++, Go, Rust, etc.) it is simpler than the async version. Lastly, adapting existing EVM higher-level languages such as Solidity to the async ewasm version would be much more complicated.
70 |
71 | ### Implementing the Synchronous EEI methods in Javascript
72 |
73 | Implementing the synchronous interface in Javascript requires a workaround for returning data from host functions to the wasm instance, and there are several approaches.
74 |
75 | One approach is to use a `SharedArrayBuffer` and [Atomics](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics) inside the host function to block execution of the wasm instance. The problem with this approach is that browser vendors are [disabling SharedArrayBuffer](https://www.mozilla.org/en-US/security/advisories/mfsa2018-01/) to mitigate the [Spectre timing attack](https://blog.mozilla.org/security/2018/01/03/mitigations-landing-new-class-timing-attack/). For this approach to be practical, the sharedArrayBuffer would need to be re-enabled in browsers and remain as an [ECMAScript standard feature](https://github.com/tc39/security/issues/3).
76 |
77 | A second approach is to preload all environment data that an ewasm contract will access. The problem with this approach is that the current Ethereum transaction protocol permits contracts to dynamically access environment data, so which data a contract will access is not known prior to execution. For a Javascript host function to provide synchronous dynamic data access, each time the contract tries to access some piece of environment data that is not preloaded, a fetch is initiated and the wasm instance would be terminated. Once the fetch returns and the piece of data is loaded, then the wasm instance is restarted and the contract ran from the beginning. For contracts which access lots of unknown environment data, the wasm instance would need to be restarted from the beginning many times. Although this approach is very inefficient under the current transaction protocol, proposed protocol improvements such as [EIP 648](https://github.com/ethereum/EIPs/issues/648) require transactions to specify access ranges. Under such proposals, any potential data that the contract could access is known ahead of time, and could simply be preloaded.
78 |
79 | A third approach is to execute wasm code in an interpreter (i.e. a wasm interpreter written in or compiled to Javascript), rather than executing wasm code in a browser's native wasm instance. Interpreting the wasm code gives full control over its execution, but would be slower than a native wasm instance.
80 |
--------------------------------------------------------------------------------
/metering.md:
--------------------------------------------------------------------------------
1 | # Metering
2 |
3 | Given a set of operations and a corresponding set of costs for each operation we can deterministically run computation for any number of cost units by summing up the costs on the execution of each operation. We call the cost units here "gas" and it stands as a estimation for computational time.
4 |
5 | ## Metering in Wasm
6 |
7 | The following has been implemented [here](https://github.com/ewasm/wasm-metering)
8 |
9 | ## Metering by Branch
10 | To meter Webassembly we first define all the operation that can cause branches.
11 |
12 | `const branching_ops = new Set(['end', 'br', 'br_table', 'br_if', 'if', 'else', 'return', 'loop'])`
13 |
14 | We also define a map that contains each opcode and its associated cost. We will refer to this as the cost table. The Default cost table is defined [here](https://github.com/ewasm/design/blob/master/determining_wasm_gas_costs.md)
15 |
16 | ```
17 | cost_table = {
18 | 'op': cost
19 | }
20 | ```
21 |
22 | Lastly we need a metering statement, we will uses
23 | ```
24 | i64.const
25 | call $meter
26 | ```
27 |
28 | And a metering function `$meter`. The meter function has a signature of `(type (func (param i64)))`. Internally this function should keep a running sum and if that sum grows larger than a given threshold, end the program's execution. The metering function can be embedded in the binary itself or can use wasm's import to define it externally.
29 |
30 | Then given an array of opcodes we iterate the array and divided into segments that start with one of the `branching_ops`
31 |
32 | ```javascript
33 | const code = [...opcodes]
34 | const segments = []
35 | let current_segment = []
36 |
37 | for (let op in code) {
38 | current_segment.push(op)
39 | if (branching_ops.has(op)) {
40 | segments.push(current_segment)
41 | current_segment = []
42 | }
43 | }
44 | ```
45 |
46 | Then for each segment we calculate the sum of the operations. At the beginning for each segment we then append a metering statement.
47 |
48 | ```javascript
49 | metered_segments = segments.map(segment => {
50 | let cost_of_segment = segment.reduce((sum, op) => {
51 | return sum + cost_table[op]
52 | }, 0)
53 |
54 | return getMeterStatement(cost).concat(segment)
55 | })
56 | ```
57 |
58 | Lastly we concatenate all the metered segments together
59 | ```javascript
60 | metered_code = metered_segments.reduce(a, b => {
61 | return a.concat(b)
62 | },[])
63 | ```
64 |
65 | ## Special metering: memory
66 |
67 | Metering memory makes use of the separate memory system of WebAssembly:
68 | - the module parameter `memory`
69 | - the two instructions:
70 | - `grow_memory`
71 | - `current_memory`
72 |
73 | Memory size is expressed in pages, where a page is 65536 bytes.
74 |
75 | The module parameter specifies the initial page count and an optional maximum page count the module cannot exceed. The currently available page count can be queried via `current_memory` and new pages can be allocated via `grow_memory`. Read more about memory in the [the WebAssembly design](https://github.com/WebAssembly/design/blob/master/Modules.md#linear-memory-section).
76 |
77 | Gas needs to be charged for the initial allocated pages as well as any increase of pages via `grow_memory`.
78 |
79 | ### Initial memory allocation
80 |
81 | The cost of pre-allocated memory should be counted before instantiating the module.
82 |
83 | ### Increasing memory
84 |
85 | Any calls to `grow_memory` needs to be prepended with a call for metering.
86 |
87 | ## Examples
88 |
89 | The following examples assume we have a cost table that defines all operations to have the cost of 1
90 |
91 | ### Basic
92 | ```
93 | (module
94 | (fun
95 | i64.const 1 ;; +1
96 | drop ;; +1
97 | end ;; +1
98 | )
99 | )
100 | ```
101 | This code can be transformed to
102 | ```
103 | (module
104 | (type (func))
105 | (type (func (param i64)))
106 |
107 | (import "ethereum" "useGas" (func $meter (type 1)))
108 | (func (type 0)
109 | i64.const 5 ;; 3 + 2 the cost of metering
110 | call $meter
111 | i64.const 1
112 | drop
113 | end
114 | )
115 |
116 | ```
117 | ### Conditionals
118 |
119 |
120 | ```
121 | (module
122 | (func $fac (param i64) (result i64)
123 | (if i64
124 | (i64.lt_s (get_local 0) (i64.const 1))
125 | (then (i64.const 1))
126 | (else
127 | (i64.mul
128 | (get_local 0)
129 | (call $fac
130 | (i64.sub
131 | (get_local 0)
132 | (i64.const 1)))))))
133 | (export "fac" (func $fac)))
134 | ```
135 | This code can be transformed to
136 | ```
137 | (module
138 | (type $type0 (func (param i32) (result i32)))
139 | (type $type1 (func (param i32)))
140 | (import $meter "metering" "usegas" (param i32))
141 | (export "fac" $func1)
142 | (func $func1 (param $var0 i32) (result i32)
143 | i32.const 211
144 | call $meter
145 | get_local $var0
146 | i32.const 1
147 | i32.lt_s
148 | if i32
149 | i32.const 180
150 | call $import0
151 | i32.const 1
152 | else
153 | i32.const 420
154 | call $meter
155 | get_local $var0
156 | get_local $var0
157 | i32.const 1
158 | i32.sub
159 | call $func1
160 | i32.mul
161 | end
162 | )
163 | )
164 | ```
165 |
166 | ## Future Work
167 |
168 | More efficient metering algorithms can be defined. For example if we can prove that an `end` is impossible to jump to it doesn't need to be segmented. The tradeoff here is the complexity for implementing these algorithms.
169 |
--------------------------------------------------------------------------------
/rationale.md:
--------------------------------------------------------------------------------
1 | ## Why do we want ewasm?
2 |
3 | * Fast & Efficient: To truly distinguish Ethereum as the World Computer we need to have a very performant VM. The current architecture of the VM is one of the greatest blockers to raw performance. WebAssembly aims to execute at near native speed by taking advantage of common hardware capabilities available on a wide range of platforms. This will open the door to a wide array of uses that require performance/throughput.
4 | * Security: With the add performance gains from ewasm we will be able to implement parts of Ethereum such as the precompiled contract in the VM itself which will minimize our trusted computing base.
5 | * Standardized Instruction Set: WebAssembly is currently being designed as an open standard by a W3C Community Group and is actively being developed by engineers from Mozilla, Google, Microsoft, and Apple.
6 | * Toolchain Compatibility: A LLVM front-end for Wasm is part of the MVP. This will allow developers to write contracts and reuse applications written in common languages such as C/C++, go and rust.
7 | * Portability: Wasm is targeted to be deployed in all the major web browsers which will result in it being one of the most widely deployed VM architecture. Contracts compiled to ewasm will share compatibility with any standard Wasm environment. Which will make running a program either directly on Ethereum, on a cloud hosting environment, or on one's local machine - a frictionless process.
8 | * Optional And Flexible Metering: Metering the VM adds overhead but is essential for running untrusted code. If code is trusted then metering maybe optional. ewasm defines metering as an optional layer to accommodate for these use cases.
9 | * Furthermore some of [Wasm's top design goals](https://github.com/WebAssembly/design/blob/master/HighLevelGoals.md) are largely applicable to Ethereum, including:
10 |
11 | > Define a portable, size- and load-time-efficient binary format to serve as a compilation target which can be compiled to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms, including mobile and IoT.
12 |
13 |
14 | ### Details
15 | #### Rationale For Register-Based ISA
16 |
17 | * Register-based virtual machines are more like actual hardware
18 | * Easier to JIT
19 | * Although most early computers used stack or accumulator-style architectures, virtually every new architecture designed after 1980 uses a load-store register architecture. The major reasons for the emergence of general-purpose register (GPR) computers are twofold. First, registers—like other forms of storage internal to the processor are faster than memory. Second, registers are more efficient for a compiler to use than other forms of internal storage. For example, on a register computer the expression (A * B) – (B * C) – (A * D) may be evaluated by doing the multiplications in any order, which may be more efficient because of the location of the operands or because of pipelining concerns. Nevertheless, on a stack computer the hardware must evaluate the expression in only one order, since operands are hidden on the stack, and it may have to load an operand multiple times. More importantly, registers can be used to hold variables. When variables are allocated to registers, the memory traffic reduces, the program speeds up (since registers are faster than memory), and the code density improves (since a register can be named with fewer bits than can a memory location). ([Reference](http://www.tandon-books.com/Computer%20Science/CS6143%20-%20Computer%20Architecture%20II/(CS6143)%20Computer%20Architecture%20-%20A%20Quantitative%20Approach%205e.pdf))
20 | * Java, by contrast, is stack-based: "Java byte-codes have additional disadvantages. Directly mapping byte-codes onto the underlying architecture is much more difficult than generating machine instructions from an abstract syntax-tree. Code generators that are based on a high-level representation do not have to deal with unfavorable peculiarities of Java byte-codes but can tailor their output towards advanced and specific processor features, such as special purpose instructions, size of register sets, and cache architectures. This is especially true for today's most common RISC processors which are less suited for byte-code's heavily used stack operations." ([Reference](https://bit.ly/2FykC0k) - [original FTP location](ftp://ftp.cis.upenn.edu/pub/cis700/public_html/papers/Kistler96.pdf))
21 | * [The design of the Inferno virtual machine](http://herpolhode.com/rob/hotchips.html)
22 | * [Virtual Machine Showdown: Stack Versus Registers](http://static.usenix.org/events/vee05/full_papers/p153-yunhe.pdf)
23 |
24 | ## Further Reading
25 | * [wasm's design docs](https://github.com/WebAssembly/design)
26 | * [chrome's binary encoding](https://docs.google.com/document/d/1-G11CnMA0My20KI9D7dBR6ZCPOBCRD0oCH6SHCPFGx0/edit?pref=2&pli=1)
27 | * A Tree-Based Alternative to Java Byte-Code - ftp://ftp.cis.upenn.edu/pub/cis700/public_html/papers/Kistler96.pdf
28 | * [JavaTrees](http://central.kaserver5.org/Kasoft/Typeset/JavaTree/Pt06.html#Head363)
29 | * Adaptive Compression of Syntax Trees and Iterative Dynamic Code Optimization: Two Basic Technologies for Mobile-Object Systems -ftp://ftp.cis.upenn.edu/pub/cis700/public_html/papers/Franz97b.pdf
30 | * [Computer Architecture A Quantitative Approach (5th edition)](http://www.tandon-books.com/Computer%20Science/CS6143%20-%20Computer%20Architecture%20II/(CS6143)%20Computer%20Architecture%20-%20A%20Quantitative%20Approach%205e.pdf)
31 |
--------------------------------------------------------------------------------
/sentinel.md:
--------------------------------------------------------------------------------
1 | # Sentinel Contract
2 |
3 | This system contract performs two important tasks:
4 | - validates contracts
5 | - injects metering statements into contracts
6 |
7 | The process of metering is [explained in its own chapter](./metering.md).
8 |
9 | The Sentinel is a system contract which means its code is fixed and is part of the genesis or hardfork ewasm is enabled on.
10 | As a result, changing or updating it requires a hard fork. In order to facilitate a more dynamic ecosystem a proposal follows
11 | here under the *Governance* subsection to introduce upgradability for the Sentinel contract.
12 |
13 | The Sentinel contract has two interfaces:
14 | - raw interface
15 | - ABI encoded interface
16 |
17 | The raw interface is used by the node for contract validation during deployment, while the ABI encoded interface is a more
18 | friendly way to interact with the contract otherwise.
19 |
20 | ## Error handling
21 |
22 | In both modes, the contract will use an invalid instruction (e.g. regular failure) when an unexpected issue occurs,
23 | or the `revert` operation if the supplied input is invalid.
24 |
25 | ## Raw interface
26 |
27 | In the raw interface it accepts any valid WebAssembly binary, applies the Sentinel steps, and returns the transformed
28 | WebAssembly binary. There is no encapsulation of any kind.
29 |
30 | ## ABI encoded interface
31 |
32 | The ABI encoded interface is demonstrated by the following Solidity interface:
33 | ```solidity
34 | interface Sentinel {
35 | // Expects a WebAssembly binary and returns a transformed WebAssembly binary.
36 | function validateAndMeter(bytes) external view returns (bytes);
37 | }
38 | ```
39 |
40 | ## Governance (upgradability)
41 |
42 | The Sentinel contract is split into two parts:
43 | - metering injection ("Sentinel")
44 | - gas cost dataset ("CostTable")
45 |
46 | There is also a governance contract ("SentinelGovernance") controlling the update process.
47 |
48 | The `CostTable` is queried by the Sentinel during injection. This makes it possible to update either of them with a lower risk.
49 |
50 | As a first step, we only propose to have the on-chain ability to update the `CostTable`.
51 |
52 | Both of the contracts should conform to the Contract ABI. Their interfaces are given as Solidity `interface`s (which have a
53 | strict translation to the ABI):
54 |
55 | ```
56 | interface CostTable {
57 | enum CostKind {
58 | BaseInstantiation,
59 | MemoryPage,
60 | I32Add,
61 | I32Sub,
62 | I32Mul,
63 | I32Div,
64 | I32Mod,
65 | // TBA
66 | }
67 |
68 | // Returns the cost for the given kind.
69 | function getCost(CostKind kind) external view returns (uint64);
70 |
71 | // Returns all the costs as an array, in order the enum is defined above.
72 | function getAllCosts() external view returns (uint64[]);
73 | }
74 |
75 | interface Sentinel {
76 | // Takes a contract as an input, validates and injects metering statements and returns the updated version.
77 | //
78 | // Note, the Sentinel contract should also accept an incoming call with the `0x0061736D` selector and process
79 | // it as if it were a non-ABI wrapped call to this function. This refers to the "raw interface" explained above.
80 | function validateAndMeter(bytes) external view returns (bytes);
81 |
82 | // Returns the current CostTable contract.
83 | function getCostTable() external view returns (CostTable);
84 |
85 | // Replaces the CostTable contract with the specified one.
86 | //
87 | // Returns a failure if the setting failed.
88 | function setCostTable(CostTable) external;
89 | }
90 | ```
91 |
92 | In order to compose multiple governance systems we propose an intermediate contract to be used instead of directly
93 | modifying the Sentinel. Understandably only this intermediate contract will have access to call `setCostTable` on the Sentinel successfully.
94 |
95 | In the prototype testnet we intend to use multiple governance systems, all of whose addresses are hardcoded in this
96 | intermediate contract and all of which have to agree to a proposed change.
97 |
98 | ```
99 | interface SentinelGovernance {
100 | // Returns the current CostTable contract.
101 | //
102 | // This is only a proxy method through the Sentinel.
103 | function getCostTable() external view returns (CostTable);
104 |
105 | // Proposes a new CostTable contract for adoption. The proposer is the sender.
106 | // This method is to be called by a governance system upon reaching consensus.
107 | function proposeCostTable(CostTable) external;
108 |
109 | // Revokes the current proposal made sender.
110 | function revokeProposal() external;
111 |
112 | // Can be called by anyone. Applies the change to the Sentinel if and only all
113 | // governance systems proposed the same address.
114 | //
115 | // Returns a failure (revert) if the setting failed;
116 | function applyChange() external;
117 | }
118 | ```
119 |
120 | A sample implementation of the above exists under the [sentinel-governance](https://github.com/ewasm/sentinel-governance) project.
121 |
--------------------------------------------------------------------------------
/system_contracts.md:
--------------------------------------------------------------------------------
1 | # System Contracts
2 |
3 | System contracts are interfaces defined as contracts, which are essential or
4 | recommended for an ewasm VM.
5 |
6 | An ewasm VM implementation may opt to implement these interfaces natively
7 | or to rely on implementations written in ewasm.
8 |
9 | Each of these contracts have a pre defined address and can be executed through
10 | regular contract invocations.
11 |
12 | ## Sentinel Contract
13 |
14 | Address: `0x000000000000000000000000000000000000000a`
15 |
16 | Every newly deployed ewasm contract must be processed by the *Sentinel Contract*
17 | prior to including the code in the state. The sentinel will perform three very
18 | important processing steps:
19 | - Validate ewasm semantics
20 | - Inject metering code
21 | - Wrap the result in the deployer preamble (*see Appendix A*)
22 |
23 | See the [dedicated chapter](./sentinel.md) about it.
24 |
25 | ## EVM Transcompiler
26 |
27 | Address: `0x000000000000000000000000000000000000000b`
28 |
29 | Transcompiles EVM1 bytecode into ewasm bytecode. See the [dedicated chapter](./evm_transcompiler.md) about it.
30 |
31 | The use of this is optional. A compatible client may implement EVM1 natively or
32 | may choose to use this transcompiler.
33 |
34 | Input:
35 | - **variable length**: *EVM1 contract code*
36 |
37 | Output:
38 | - **variable length**: *ewasm contract code*
39 |
40 | ## EVM Precompiled Contracts
41 |
42 | Precompiled contracts are defined for EVM1 (see the Yellow Paper). Several
43 | extensions have been proposed as *[Ethereum Improvement Proposals](http://github.com/ethereum/EIPs)*.
44 |
45 | We assume the contracts defined in the Yellow Paper still apply for ewasm.
46 |
47 | ### ecrecover
48 |
49 | Address: `0x0000000000000000000000000000000000000001`
50 |
51 | Calculates the corresponding Ethereum address for the public key which created the given signature.
52 |
53 | Input:
54 | - **32 bytes**: *message hash*
55 | - **32 bytes**: *recovery id*
56 | - **32 bytes**: *R component*
57 | - **32 bytes**: *S component*
58 |
59 | Output:
60 | - **32 bytes**: *Ethereum address* (left padded with zeroes)
61 |
62 | ### sha2-256
63 |
64 | Address: `0x0000000000000000000000000000000000000002`
65 |
66 | Returns the SHA2-256 hash of the input.
67 |
68 | Input:
69 | - **variable length**: *input data*
70 |
71 | Output:
72 | - **32 bytes**: *sha2-256 hash*
73 |
74 | ### ripemd160
75 |
76 | Address: `0x0000000000000000000000000000000000000003`
77 |
78 | Returns the RIPEMD-160 hash of the input.
79 |
80 | Input:
81 | - **variable length**: *input data*
82 |
83 | Output:
84 | - **32 bytes**: *ripemd160 hash* (left padded with zeroes)
85 |
86 | ### identity
87 |
88 | Address: `0x0000000000000000000000000000000000000004`
89 |
90 | Copies the input data to the output.
91 |
92 | Input:
93 | - **variable length**: *input data*
94 |
95 | Output:
96 | - **variable length**: *output data*
97 |
98 | ### keccak256
99 |
100 | Address: `0x0000000000000000000000000000000000000009`
101 |
102 | Returns the KECCAK-256 hash of the input. It is being used by the EVM Transcompiler.
103 |
104 | Input:
105 | - **variable length**: *input data*
106 |
107 | Output:
108 | - **32 bytes**: *keccak-256 hash*
109 |
110 | ### Appendix A: ewasm deployer preamble
111 |
112 | ```
113 | ;;
114 | ;; Standard ewasm deployer code.
115 | ;;
116 | ;; We keep the to-be-deployed contract as a memory segment and simply return it.
117 | ;;
118 |
119 | (module
120 | (memory 1
121 | (segment 0 "\10\00\00\00") ;; Here comes the size of the code in LSB
122 | (segment 4 "Hello World CODE") ;; Here comes the code as a escaped hex string
123 | )
124 | (export "memory" memory)
125 | (export "main" $main)
126 | (import $ethereum_return "ethereum" "return" (param i32 i32))
127 | (func $main
128 | (call_import $ethereum_return (i32.const 4) (i32.load (i32.const 0)))
129 | )
130 | )
131 | ```
132 |
--------------------------------------------------------------------------------
/vm_semantics.md:
--------------------------------------------------------------------------------
1 | # VM Semantics
2 |
3 | We assume an existing Ethereum client (with EVM1) as the basis for extension.
4 |
5 | There are only 3 new rules:
6 |
7 | 1. Whenever a contract is loaded from the state it must be checked for the ewasm signature.
8 |
9 | If the signature is present, it must be executed as an ewasm contract, otherwise it must be executed as an EVM1 contract.
10 |
11 | 2. If there's no native EVM1 support in the client, it can use the [EVM Transcompiler](./evm_transcompiler.md) to translate the code.
12 |
13 | 3. When deploying an ewasm contract, the bytecode must be verified and annotated by the [*Sentinel Contract*](./sentinel.md).
14 |
--------------------------------------------------------------------------------