├── .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 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 28 | 29 | 31 | 32 | wasm 33 | e 34 | 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 | 22 | 24 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 59 | 68 | 73 | 78 | 83 | 89 | 94 | 99 | 104 | 109 | wasm 121 | e 133 | 134 | 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 | --------------------------------------------------------------------------------