├── .github ├── pull_request_template.md └── workflows │ ├── docs.yml │ ├── gh-pages.yml │ └── mdbook.yml ├── .gitignore ├── .markdownlint.yaml ├── .spellcheck.yml ├── LICENSE ├── README.md ├── book.toml ├── spell-check-custom-words.txt ├── src ├── SUMMARY.md ├── abi │ ├── argument-encoding.md │ ├── fn-selector-encoding.md │ ├── hash-based-ids.md │ ├── index.md │ ├── json-abi-format.md │ └── receipts.md ├── fuel-vm │ ├── index.md │ └── instruction-set.md ├── identifiers │ ├── asset.md │ ├── blob-id.md │ ├── contract-id.md │ ├── index.md │ ├── predicate-id.md │ ├── transaction-id.md │ └── utxo-id.md ├── index.md ├── networks │ ├── index.md │ └── poa.md ├── protocol │ ├── block-header.md │ ├── cryptographic-primitives.md │ ├── index.md │ ├── relayer.md │ ├── storage-initialization.md │ └── tx-validity.md ├── tests │ ├── index.md │ └── sparse-merkle-tree-tests.md └── tx-format │ ├── consensus_parameters.md │ ├── index.md │ ├── input.md │ ├── output.md │ ├── policy.md │ ├── transaction.md │ ├── tx-pointer.md │ ├── upgrade_purpose.md │ └── witness.md └── test_vectors └── sparse_merkle_tree ├── Test Delete Non-existent Key.yaml ├── Test Delete Sparse Union.yaml ├── Test Empty Root.yaml ├── Test Interleaved Update Delete.yaml ├── Test Update 1 Delete 1.yaml ├── Test Update 1.yaml ├── Test Update 10 Delete 5.yaml ├── Test Update 10.yaml ├── Test Update 100.yaml ├── Test Update 2 Delete 1.yaml ├── Test Update 2.yaml ├── Test Update 3.yaml ├── Test Update 5.yaml ├── Test Update Overwrite Key.yaml ├── Test Update Sparse Union.yaml ├── Test Update Union.yaml ├── Test Update With Empty Data Performs Delete.yaml ├── Test Update With Empty Data.yaml └── Test Update With Repeated Inputs.yaml /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | [Link to related issue(s) here, if any] 2 | 3 | [Short description of the changes.] 4 | 5 | ### Before requesting review 6 | - [ ] I have reviewed the code myself 7 | 8 | ### After merging, notify other teams 9 | 10 | [Add or remove entries as needed] 11 | 12 | - [ ] [Rust SDK](https://github.com/FuelLabs/fuels-rs/) 13 | - [ ] [Sway compiler](https://github.com/FuelLabs/sway/) 14 | - [ ] [Platform documentation](https://github.com/FuelLabs/devrel-requests/issues/new?assignees=&labels=new+request&projects=&template=NEW-REQUEST.yml&title=%5BRequest%5D%3A+) (for out-of-organization contributors, the person merging the PR will do this) 15 | - [ ] Someone else? 16 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | uses: FuelLabs/github-actions/.github/workflows/mdbook-docs.yml@master 12 | with: 13 | docs-src-path: 'src' 14 | spellcheck-config-path: '.spellcheck.yml' 15 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: github pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: Swatinem/rust-cache@v1 14 | - uses: actions-rs/toolchain@v1 15 | with: 16 | profile: minimal 17 | toolchain: stable 18 | - name: Setup mdBook 19 | uses: peaceiris/actions-mdbook@v1 20 | with: 21 | mdbook-version: "0.4.21" 22 | - run: mdbook build 23 | - name: Deploy master 24 | uses: peaceiris/actions-gh-pages@v3 25 | with: 26 | github_token: ${{ secrets.GITHUB_TOKEN }} 27 | publish_dir: ./book 28 | destination_dir: master 29 | cname: specs.fuel.network 30 | if: github.ref == 'refs/heads/master' 31 | -------------------------------------------------------------------------------- /.github/workflows/mdbook.yml: -------------------------------------------------------------------------------- 1 | name: mdbook checks 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | mdbook-build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions-rs/toolchain@v1 15 | with: 16 | profile: minimal 17 | toolchain: stable 18 | - name: mdbook build 19 | uses: peaceiris/actions-mdbook@v1 20 | with: 21 | mdbook-version: "0.4.21" 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | .idea/ 3 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | "default": true # Default state for all rules 2 | "MD013": false # Disable rule for line length 3 | "MD033": false # Disable rule banning inline HTML -------------------------------------------------------------------------------- /.spellcheck.yml: -------------------------------------------------------------------------------- 1 | matrix: 2 | - name: SPCheck 3 | aspell: 4 | lang: en 5 | dictionary: 6 | encoding: utf-8 7 | wordlists: 8 | - spell-check-custom-words.txt 9 | pipeline: 10 | - pyspelling.filters.context: 11 | context_visible_first: true 12 | escapes: \\[\\`~] 13 | delimiters: 14 | # Ignore all code blocks 15 | - open: '(?s)^(?P *`{3,}\s*(\w+\s*,?\s*)+.*?)$' 16 | close: '^( *`{3,})$' 17 | - pyspelling.filters.markdown: 18 | markdown_extensions: 19 | - pymdownx.superfences: 20 | - pyspelling.filters.html: 21 | comments: false 22 | ignores: 23 | - code 24 | - pre 25 | sources: 26 | - 'src/*.md' 27 | - 'src/**/*.md' 28 | default_encoding: utf-8 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fuel Specifications 2 | 3 | 4 | **Fuel: A Secure Decentralized Generalized Massively Scalable Transaction Ledger** 5 | 6 | This repository specifies the Fuel protocol, including the Fuel Virtual Machine (short: FuelVM), a blazingly fast verifiable blockchain virtual machine. 7 | 8 | ## mdbook 9 | 10 | The Fuel Specifications book is built with mdbook. 11 | 12 | Install `mdbook` and then open a new terminal session in order to run the subsequent commands 13 | 14 | ```sh 15 | cargo install mdbook 16 | ``` 17 | 18 | To build book: 19 | 20 | ```sh 21 | mdbook build 22 | ``` 23 | 24 | To serve locally: 25 | 26 | ```sh 27 | mdbook serve 28 | ``` 29 | 30 | ## Contributing 31 | 32 | Markdown files must conform to [GitHub Flavored Markdown](https://github.github.com/gfm/). Markdown must be formatted with: 33 | 34 | - [markdownlint](https://github.com/DavidAnson/markdownlint) 35 | - [Markdown Table Prettifier](https://github.com/darkriszty/MarkdownTablePrettify-VSCodeExt) 36 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Fuel Labs "] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "Fuel Specifications" 7 | 8 | [output.html] 9 | git-repository-url = "https://github.com/FuelLabs/fuel-specs" 10 | 11 | [output.html.redirect] 12 | "/fuel-specs.html" = "./index.html" 13 | "/protocol/abi.html" = "./abi/index.html" 14 | "/protocol/tx_format/index.html" = "../../tx-format/index.html" 15 | "/protocol/tx_format/constants.html" = "../../tx-format/constants.html" 16 | "/protocol/tx_format/transaction.html" = "../../tx-format/transaction.html" 17 | "/protocol/tx_format/input.html" = "../../tx-format/input.html" 18 | "/protocol/tx_format/output.html" = "../../tx-format/output.html" 19 | "/protocol/tx_format/witness.html" = "../../tx-format/witness.html" 20 | "/protocol/tx_format/tx_pointer.html" = "../../tx-format/tx-pointer.html" 21 | "/protocol/id/index.html" = "../../identifiers/index.html" 22 | "/protocol/id/transaction.html" = "../../identifiers/transaction-id.html" 23 | "/protocol/id/contract.html" = "../../identifiers/contract-id.html" 24 | "/protocol/id/utxo.html" = "../../identifiers/utxo-id.html" 25 | "/protocol/id/predicate.html" = "../../identifiers/predicate-id.html" 26 | "/protocol/tx_validity.html" = "./tx-validity.html" 27 | "/protocol/cryptographic_primitives.html" = "./cryptographic-primitives.html" 28 | "/protocol/storage_initialization.html" = "./storage-initialization.html" 29 | "/protocol/block_header.html" = "./block-header.html" 30 | "/protocol/abi/index.html" = "../../abi/index.html" 31 | "/protocol/abi/json_abi_format.html" = "../../abi/json-abi-format.html" 32 | "/protocol/abi/receipts.html" = "../../abi/receipts.html" 33 | "/protocol/abi/fn_selector_encoding.html" = "../../abi/fn-selector-encoding.html" 34 | "/protocol/abi/argument_encoding.html" = "../../abi/argument-encoding.html" 35 | "/vm/index.html" = "../fuel-vm/index.html" 36 | "/vm//instruction_set.html" = "../fuel-vm/instruction-set.html" 37 | "/network/index.html" = "../networks/index.html" 38 | "/network/poa.html" = "../networks/poa.html" 39 | "/tests/sparse_merkle_tree_tests.html" = "./sparse-merkle-tree-tests.html" 40 | -------------------------------------------------------------------------------- /spell-check-custom-words.txt: -------------------------------------------------------------------------------- 1 | ABI 2 | ABIs 3 | ASM 4 | IDE 5 | IDEs 6 | LSP 7 | namespace 8 | ALU 9 | APIs 10 | JSON 11 | BrowserStack 12 | CLI 13 | Deserialization 14 | deserializing 15 | deserializes 16 | DApp 17 | subcurrency 18 | Subcurrency 19 | intrinsics 20 | Intrinsics 21 | workspace 22 | workspaces 23 | Workspaces 24 | neovim 25 | EVM 26 | EVM's 27 | EOA 28 | ERC 29 | Ethereum 30 | Ethereum's 31 | FVM 32 | FuelVM 33 | Fuelup 34 | Github 35 | GraphQL 36 | Infura 37 | JSON 38 | LSP 39 | Merkle 40 | PoA 41 | PoS 42 | PoW 43 | RPC 44 | SDK 45 | SDK's 46 | SDKs 47 | SauceLabs 48 | Sepolia 49 | Structs 50 | Sway 51 | TAI 52 | TODO 53 | TypeScript 54 | UpgradePurpose 55 | UTF 56 | UTXO 57 | UTXOs 58 | Utils 59 | VM 60 | VSCode 61 | abigen 62 | args 63 | async 64 | backend 65 | backtraces 66 | blockchain 67 | blockchain's 68 | bytecode 69 | codespace 70 | codespaces 71 | config 72 | cryptographic 73 | customizable 74 | customizations 75 | dapp 76 | dev 77 | dropdown 78 | enum 79 | enums 80 | env 81 | forc 82 | frontend 83 | fuelup 84 | fullstack 85 | graphQL 86 | graphql 87 | http 88 | https 89 | js 90 | localhost 91 | mainnet 92 | mempool 93 | merkle 94 | monorepo 95 | monorepos 96 | natively 97 | npm 98 | nvm 99 | onboarding 100 | params 101 | pnpm 102 | prerelease 103 | queryable 104 | quickstart 105 | relayer 106 | relayers 107 | repo 108 | repos 109 | runnable 110 | stateful 111 | struct 112 | structs 113 | struct's 114 | testnet 115 | testnets 116 | toolchain 117 | toolchains 118 | urql 119 | validator 120 | validators 121 | superABI 122 | superABIs 123 | SuperABIs 124 | supertraits 125 | compositional 126 | typeclass 127 | turbofish 128 | DSL 129 | TOML 130 | IPFS 131 | Bitwise 132 | Bitwise 133 | runtime 134 | runtimes 135 | formatter 136 | deployable 137 | Utils 138 | ETH 139 | initializer 140 | initializers 141 | destructuring 142 | instantiation 143 | VMs 144 | superset 145 | CEI 146 | pre 147 | entrancy 148 | interoperable 149 | blockchains 150 | keccak 151 | SHA 152 | UI 153 | backtrace 154 | Collateralized 155 | collateralized 156 | submodule 157 | DEX 158 | TypeChain 159 | inlines 160 | inlining 161 | MiB 162 | FuelVM's 163 | deterministically 164 | CLI 165 | VS 166 | GraphViz 167 | DOT 168 | DCA 169 | AST 170 | GitHub 171 | decrypt 172 | subcommand 173 | subcommands 174 | Subcommands 175 | supertrait 176 | supertraits 177 | Supertraits 178 | incrementor 179 | monomorphization 180 | Booleans 181 | boolean 182 | Orchestrator 183 | orchestrator 184 | growable 185 | arity 186 | tuple's 187 | unary 188 | SRC 189 | DEX 190 | FuelLabs 191 | PRs 192 | codebase 193 | PostgreSQL 194 | Postgres 195 | MacOS 196 | macOS 197 | backends 198 | hoc 199 | semver 200 | SQLx 201 | Homebrew 202 | Changelog 203 | lookups 204 | namespaces 205 | YAML 206 | WASM 207 | WebAssembly 208 | dApp 209 | dApps 210 | JWT 211 | Schemas 212 | schemas 213 | AssemblyScript 214 | indexable 215 | Macbook 216 | Dockerized 217 | TLDR 218 | IaaS 219 | Updatable 220 | coinbase 221 | Coinbase 222 | postcondition 223 | Postcondition 224 | Cryptocurrency 225 | cryptocurrency 226 | ECDSA 227 | EcDSA 228 | secp 229 | Secp 230 | Bitfield 231 | SMT 232 | SMTs 233 | subtrees 234 | subtree 235 | prepended 236 | unhashed 237 | preimage 238 | FIPS 239 | EdDSA 240 | curve25519 241 | blazingly 242 | pseudocode 243 | Pseudocode 244 | endian 245 | KiB 246 | SUT 247 | Celestia 248 | encodings 249 | callee 250 | inlined 251 | parsable 252 | underflows 253 | bitmask 254 | XORs 255 | XOR 256 | ORs 257 | ANDs 258 | rhs 259 | lhs 260 | scalable 261 | Scalable 262 | Exponentiate 263 | exponentiate 264 | Executability 265 | executability 266 | Unwritable 267 | unwritable 268 | untrusted 269 | intra 270 | OOB 271 | unspendable 272 | priori 273 | padding 274 | incentivize 275 | EIPS 276 | eip 277 | eips 278 | ethereum 279 | xnor 280 | XNOR -------------------------------------------------------------------------------- /src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | [Fuel Specifications](./index.md) 4 | 5 | - [Transaction Format](./tx-format/index.md) 6 | - [Consensus Parameters](./tx-format/consensus_parameters.md) 7 | - [Transaction](./tx-format/transaction.md) 8 | - [UpgradePurpose](./tx-format/upgrade_purpose.md) 9 | - [Policy](./tx-format/policy.md) 10 | - [Input](./tx-format/input.md) 11 | - [Output](./tx-format/output.md) 12 | - [Witness](./tx-format/witness.md) 13 | - [Transaction Pointer](./tx-format/tx-pointer.md) 14 | - [Computing Identifiers](./identifiers/index.md) 15 | - [Asset ID](./identifiers/asset.md) 16 | - [Blob ID](./identifiers/blob-id.md) 17 | - [Contract ID](./identifiers/contract-id.md) 18 | - [Predicate ID](./identifiers/predicate-id.md) 19 | - [Transaction ID](./identifiers/transaction-id.md) 20 | - [UTXO ID](./identifiers/utxo-id.md) 21 | - [Protocol](./protocol/index.md) 22 | - [Transaction Validity Rules](./protocol/tx-validity.md) 23 | - [Cryptographic Primitives](./protocol/cryptographic-primitives.md) 24 | - [Storage Slot Initialization](./protocol/storage-initialization.md) 25 | - [Block Header Format](./protocol/block-header.md) 26 | - [Layer 1 Relayer/Bridge Protocol](./protocol/relayer.md) 27 | - [Application Binary Interface (ABI)](./abi/index.md) 28 | - [JSON ABI Format](./abi/json-abi-format.md) 29 | - [Receipts](./abi/receipts.md) 30 | - [Function Selector Encoding](./abi/fn-selector-encoding.md) 31 | - [Argument Encoding](./abi/argument-encoding.md) 32 | - [Hash Based Ids](./abi/hash-based-ids.md) 33 | - [FuelVM](./fuel-vm/index.md) 34 | - [Instruction Set](./fuel-vm/instruction-set.md) 35 | - [Networks](./networks/index.md) 36 | - [Proof of Authority (PoA)](./networks/poa.md) 37 | - [Testing](./tests/index.md) 38 | - [Sparse Merkle Tree](./tests/sparse-merkle-tree-tests.md) 39 | -------------------------------------------------------------------------------- /src/abi/argument-encoding.md: -------------------------------------------------------------------------------- 1 | # Argument Encoding 2 | 3 | ## Version 0 4 | 5 | > :warning: This version is being deprecated for Version 1 (see below). 6 | 7 | When crafting transaction script data, you must encode the arguments you wish to pass to the script. 8 | 9 | ### Types 10 | 11 | These are the available types that can be encoded in the ABI: 12 | 13 | - Unsigned integers: 14 | - `u8`, 8 bits. 15 | - `u16`, 16 bits. 16 | - `u32`, 32 bits. 17 | - `u64`, 64 bits. 18 | - `u128`, 128 bits. 19 | - `u256`, 256 bits. 20 | - Boolean: `bool`, either `0` or `1` encoded identically to `u8`. 21 | - B256: `b256`, arbitrary 256-bits value. 22 | - Address : `address`, a 256-bit (32-byte) address. 23 | - Fixed size string 24 | - Array 25 | - Enums (sum types) 26 | - Structs 27 | - Vectors 28 | - Tuples 29 | 30 | These types are encoded in-place. Here's how to encode them. We define `enc(X)` the encoding of the type `X`. 31 | 32 | ### Unsigned Integers 33 | 34 | `u` where `M` is either 8, 16, 32, 64, 128 or 256 bits. 35 | 36 | `enc(X)` is the big-endian (i.e. right-aligned) representation of `X` left-padded with zero-bytes. 37 | 38 | - In the case of `M` being 8, 16, 32 or 64, total length must be 8 bytes. 39 | - If `M` is 128, total length must be 16 bytes. 40 | - If `M` is 256, total length must be 32 bytes. 41 | 42 | > **Note:** since all integer values are unsigned, there is no need to preserve the sign when extending/padding; padding with only zeroes is sufficient._ 43 | 44 | **Example:** 45 | 46 | Encoding `42` yields: `0x000000000000002a`, which is the hexadecimal representation of the decimal number `42`, right-aligned to 8 bytes. 47 | Encoding `u128::MAX - 1` yields: `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE`, it's right-aligned to 16 bytes 48 | 49 | ### `Boolean` 50 | 51 | `enc(X)` is `0` if `X` is false or `1` if `X` is true, left-padded with zero-bytes. Total length must be 8 bytes. Similar to the `u8` encoding. 52 | 53 | **Example:** 54 | 55 | Encoding `true` yields: 56 | 57 | ```text 58 | 0x0000000000000001 59 | ``` 60 | 61 | ### `B256` 62 | 63 | `b256` is a fixed size bit array of length 256. Used for 256-bit hash digests and other 256-bit types. It is encoded as-is. 64 | 65 | **Example:** 66 | 67 | Encoding `0xc7fd1d987ada439fc085cfa3c49416cf2b504ac50151e3c2335d60595cb90745` yields: 68 | 69 | ```text 70 | 0xc7fd1d987ada439fc085cfa3c49416cf2b504ac50151e3c2335d60595cb90745 71 | ``` 72 | 73 | ### `Address` 74 | 75 | A 256-bit (32-byte) address, encoded in the same way as a `b256` argument: encoded as-is. 76 | 77 | **Example:** 78 | 79 | Encoding `0xc7fd1d987ada439fc085cfa3c49416cf2b504ac50151e3c2335d60595cb90745` yields: 80 | 81 | ```text 82 | 0xc7fd1d987ada439fc085cfa3c49416cf2b504ac50151e3c2335d60595cb90745 83 | ``` 84 | 85 | ### Array 86 | 87 | An array of a certain type `T`, `[T; n]`, where `n` is the length of the array. 88 | 89 | Arrays in Sway have a fixed-length which is known at compile time. This means the ABI encoding for arrays also happens in-place, with no need to account for dynamic sizing. 90 | 91 | The encoding for the array contains, in order, the encoding of each element in `[T; n]`, recursively following the encoding for the type `T`. 92 | 93 | For instance, consider the function signature `my_func(bool, [u64; 2])` with the values `(true, [1, 2])`. 94 | 95 | The encoding will be: 96 | 97 | 1. `0x0000000000000001`, the `true` bool encoded in-place. 98 | 2. `0x0000000000000001`, First element of the parameter `[u64; 2]`, `1`, encoded as a `u64`. 99 | 3. `0x0000000000000002`, Second element of the parameter `[u64; 2]`, `2`, encoded as a `u64`. 100 | 101 | The resulting encoded ABI will be: 102 | 103 | ```text 104 | 0x000000000000000100000000000000010000000000000002 105 | ``` 106 | 107 | ### Fixed-length Strings 108 | 109 | Strings have fixed length and are encoded in-place. `str[n]`, where `n` is the fixed-size of the string. Rather than padding the string, the encoding of the elements of the string is tightly packed. And unlike the other type encodings, the string encoding is left-aligned. 110 | 111 | Note that all strings are encoded in UTF-8. 112 | 113 | **Example:** 114 | 115 | Encoding `"Hello, World"` as a `str[12]` **yields**: 116 | 117 | ```text 118 | 0x48656c6c6f2c20576f726c6400000000 119 | ``` 120 | 121 | Note that we're padding with zeroes in order to keep it right-aligned to 8 bytes (FuelVM's word size). 122 | 123 | ### Structs 124 | 125 | Encoding ABIs that contain custom types, such as structs, is similar to encoding a set of primitive types. The encoding will proceed in the order that the inner types of a custom type are declared and _recursively_ just like encoding any other type. This way you can encode structs with primitive types or structs with more complex types in them such as other structs, arrays, strings, and enums. 126 | 127 | Here's an example: 128 | 129 | ```rust 130 | struct InputStruct { 131 | field_1: bool, 132 | field_2: u8, 133 | } 134 | 135 | 136 | abi MyContract { 137 | fn foo(a: u64); 138 | fn bar(a: InputStruct); 139 | } { 140 | fn baz(a: ()) { } 141 | } 142 | ``` 143 | 144 | Calling `bar` with `InputStruct { field_1: true, field_2: 5 }` yields: 145 | 146 | ```plaintext 147 | 0x 148 | 0000000000000001 // `true` encoded as a bool 149 | 0000000000000005 // `5` encoded as u8 150 | ``` 151 | 152 | A more complex scenario: 153 | 154 | ```rust 155 | struct InputStruct { 156 | field_1: bool, 157 | field_2: [u8; 2], // An array of u8, with length 2. 158 | } 159 | 160 | 161 | abi MyContract { 162 | fn foo(a: u64); 163 | fn bar(a: InputStruct); 164 | } { 165 | fn baz(a: ()) { } 166 | } 167 | ``` 168 | 169 | Calling `bar` with `InputStruct { field_1: true, field_2: [1, 2] }` yields: 170 | 171 | ```plaintext 172 | 0x 173 | 0000000000000001 // `true` encoded as a bool 174 | 0000000000000001 // `1` encoded as u8 175 | 0000000000000002 // `2` encoded as u8 176 | ``` 177 | 178 | ### Enums (sum types) 179 | 180 | ABI calls containing enums (sum types) are encoded similarly to structs: encode the discriminant first, then recursively encode the type of the enum variant being passed to the function being called. 181 | 182 | ```rust 183 | enum MySumType 184 | { 185 | X: u32, 186 | Y: bool, 187 | } 188 | 189 | abi MyContract { 190 | fn foo(a: u64); 191 | fn bar(a: MySumType); 192 | } { 193 | fn baz(a: ()) { } 194 | } 195 | ``` 196 | 197 | Calling `bar` with `MySumType::X(42)` yields: 198 | 199 | ```plaintext 200 | 0x 201 | 0000000000000000 // The discriminant of the chosen enum, in this case `0`. 202 | 000000000000002a // `42` encoded as u64 203 | ``` 204 | 205 | If the sum type has variants of different sizes, then left padding is required. 206 | 207 | ```rust 208 | enum MySumType 209 | { 210 | X: b256, 211 | Y: u32, 212 | } 213 | 214 | abi MyContract { 215 | fn foo(a: u64); 216 | fn bar(a: MySumType); 217 | } { 218 | fn baz(a: ()) { } 219 | } 220 | ``` 221 | 222 | Calling `bar` with `MySumType::Y(42)` yields: 223 | 224 | ```plaintext 225 | 0x 226 | 0000000000000001 // The discriminant of the chosen enum, in this case `1`. 227 | 0000000000000000 // Left padding 228 | 0000000000000000 // Left padding 229 | 0000000000000000 // Left padding 230 | 000000000000002a // `42` encoded as u64 231 | ``` 232 | 233 | Note that three words of padding are required because the largest variant of `MySumType` is 4 words wide. 234 | 235 | If all the variants of a sum type are of type `()`, or unit, then only the discriminant needs to be encoded. 236 | 237 | ```rust 238 | enum MySumType 239 | { 240 | X: (), 241 | Y: (), 242 | Z: (), 243 | } 244 | 245 | abi MyContract { 246 | fn foo(a: u64); 247 | fn bar(a: MySumType); 248 | } { 249 | fn baz(a: ()) { } 250 | } 251 | ``` 252 | 253 | Calling `bar` with `MySumType::Z` yields: 254 | 255 | ```plaintext 256 | 0x 257 | 0000000000000002 // The discriminant of the chosen enum, in this case `2`. 258 | ``` 259 | 260 | ### Vectors 261 | 262 | ABI calls containing vectors are encoded in the following way: 263 | 264 | - First, figure out the the length `l` of the vector. Its length will also be its capacity. 265 | - Encode the content of the vector according to the spec of its type, e.g. for a `Vec`, 266 | encode each `bool` element according to the `bool` specs. This gives out data that is stored 267 | on the heap, and we encode only the pointer to this data 268 | 269 | ```rust 270 | abi MyContract { 271 | fn foo(a: Vec); 272 | } { 273 | fn foo(a: Vec) {}; 274 | } 275 | ``` 276 | 277 | Calling `foo` with `vec![1u32, 2u32, 3u32, 4u32]`: 278 | 279 | - `length` is 4, `capacity` is 4 280 | - `data`: [0x0000000000000001, 0x0000000000000002, 0x0000000000000003, 0x0000000000000004], stored at pointer address `0x000000000000beef` 281 | 282 | > Note: to understand how the `u32` are encoded, see the section about encoding integers. 283 | 284 | ```plaintext 285 | 0x 286 | 000000000000beef // pointer address 287 | 0000000000000004 // length = 4 288 | 0000000000000004 // capacity = 4 289 | ``` 290 | 291 | At the pointer address, then the vector's content are encoded as such: 292 | 293 | ```plaintext 294 | 0x 295 | 0000000000000001 // 1u32 296 | 0000000000000002 // 2u32 297 | 0000000000000003 // 3u32 298 | 0000000000000004 // 4u32 299 | ``` 300 | 301 | ### Tuples 302 | 303 | ABI calls containing tuples are encoded as such: 304 | If `X` is a tuple with the type signature `(T_1, T_2, ..., T_n)`, with `T_1,...,T_n` being any type except for vector, then `enc(X)` is encoded as the concatenation of `enc(T_1)`, `enc(T_2)`,`enc (T_3)`, ..., `enc(T_n)`. 305 | 306 | ```rust 307 | abi MyContract { 308 | fn foo(a: (u64, str[3], bool)); 309 | } { 310 | fn foo(a: (u64, str[4], bool)) {}; 311 | } 312 | ``` 313 | 314 | Calling `foo` with `(1u64, "fuel", true)` : 315 | 316 | ```plaintext 317 | 0x 318 | 0000000000000001 // 1u64 319 | 6675656c00000000 // "fuel" encoded as per the specs 320 | 0000000000000001 // true 321 | ``` 322 | 323 | ## Version 1 324 | 325 | This version was created to replace the older version 0 described above, and follows three philosophical tenets: 326 | 327 | - being self-sufficient: it must be possible to completely decode the original data only using the encoded bytes and the original type (there are no references to data outside the encoded bytes); 328 | - no overhead: only the bare minimum bytes are necessary to do the encoding. No metadata, headers, etc...; 329 | - no relation with runtime memory layout: no padding, no alignment, etc... 330 | 331 | ### Primitive Types 332 | 333 | Primitive types will be encoded using the exact number of bits they need: 334 | 335 | - `u8`: 1 byte; 336 | - `u16`: 2 bytes; 337 | - `u32`: 4 bytes; 338 | - `u64`: 8 bytes; 339 | - `u256`: 32 bytes; 340 | - `b256`: 32 bytes; 341 | 342 | ### Arrays 343 | 344 | Arrays are encoded without any padding or alignment, with one item after the other. 345 | 346 | - [T; 1] is encoded [encode(T)]; 347 | - [T; 2] is encoded [encode(T), encode(T)] 348 | 349 | ### Strings 350 | 351 | String arrays are encoded just like arrays, without any overhead. 352 | 353 | - `str[1]` = 1 byte 354 | - `str[2]` = 2 bytes 355 | - `str[n]` = `n` bytes 356 | 357 | String slices do contain their length as u64, and the string itself is encoded packed without alignment or padding. 358 | 359 | - `"abc"` = `[0, 0, 0, 0, 0, 0, 0, 3, "a", "b", "c"]` 360 | 361 | ### Slices 362 | 363 | `raw_slice`, also being dynamic, contains their length as u64 and is treated as a "slice of bytes". Each byte is encoded as `u8` (1 byte) and is packed without alignment and padding. 364 | 365 | For example, a slice of three bytes like `[0u8, 1u8, 2u8]` will be encoded as bytes `[0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 2]` 366 | 367 | ### Tuple 368 | 369 | Tuples are encoded just like arrays, without any overhead like padding and alignment: 370 | 371 | - `(A, B, C)` = `[encode(A), encode(B), encode(C)]` 372 | 373 | ### Structs (v1) 374 | 375 | Structs can be encoded in two ways: 376 | 377 | - first, with the automatic implementation; 378 | - second, with the custom implementation. 379 | 380 | Auto implementation follows the same rules as tuples. So we can imagine that 381 | 382 | ```sway 383 | struct S { 384 | a: A, 385 | b: B, 386 | c: C 387 | } 388 | ``` 389 | 390 | is encoded the same way as the tuple `(A, B, C)`. 391 | 392 | Custom implementation allows the developer to choose how a struct is encoded. 393 | 394 | A struct has auto-implemented encoding if no custom was found. 395 | 396 | ### Enums 397 | 398 | `Enums` can also be encoded with the automatic or the custom implementation. 399 | 400 | The auto implementation first encoded the variant with a `u64` number starting from zero as the first variant and increments this value for each variant, following declaration order. 401 | 402 | ```sway 403 | enum E { 404 | VARIANT_A: A, // <- variant 0 405 | VARIANT_B: B, // <- variant 1 406 | VARIANT_C: C // <- variant 2 407 | } 408 | ``` 409 | 410 | will be encoded as `[encode(variant), encode(value)]`. 411 | 412 | The variant data will be encoded right after the variant tag, without any alignment or padding. 413 | 414 | An enum has auto-implemented encoding if no custom was found. 415 | 416 | ### Data Structures 417 | 418 | Some common data structures also have well-defined encoding: 419 | 420 | - `Vec` will be encoded as `[encode(length), ]` 421 | - `Bytes` will be encoded as `[encode(length), ]` 422 | - `String` will be encoded as `[encode (length), ]` 423 | 424 | All of them first contain the length and then their data right after, without any padding or alignment. 425 | -------------------------------------------------------------------------------- /src/abi/fn-selector-encoding.md: -------------------------------------------------------------------------------- 1 | # Function Selector Encoding 2 | 3 | To select which function you want to call, first, this function must be in an ABI struct of a Sway program. For instance: 4 | 5 | ```rust 6 | abi MyContract { 7 | fn foo(a: u64); 8 | fn bar(a: InputStruct ); 9 | } { 10 | fn baz(a: ()) { } 11 | } 12 | ``` 13 | 14 | The function selector is the first 4 bytes of the SHA-256 hash function of the signature of the Sway function being called. Then, these 4 bytes are right-aligned to 8 bytes, left-padded with zeroes. 15 | 16 | > **Note**: The word size for the FuelVM is 8 bytes. 17 | 18 | ## Function Signature 19 | 20 | The signature is composed of the function name with the parenthesized list of comma-separated parameter types without spaces. All strings encoded with UTF-8. For custom types such as `enum` and `struct`, there is a prefix added to the parenthesized list (see below). Generic `struct` and `enum` types also accept a list of comma-separated type arguments in between angle brackets right after the prefix. 21 | 22 | For instance, to compute the selector for the following function: 23 | 24 | ```rust 25 | fn entry_one(arg: u64); 26 | ``` 27 | 28 | we should pass `"entry_one(u64)"` to the `sha256()` hashing algorithm. The full digest would be: 29 | 30 | ```text 31 | 0x0c36cb9cb766ff60422db243c4fff06d342949da3c64a3c6ac564941f84b6f06 32 | ``` 33 | 34 | Then we would get only the first 4 bytes of this digest and left-pad it to 8 bytes: 35 | 36 | ```text 37 | 0x000000000c36cb9c 38 | ``` 39 | 40 | The table below summarizes how each function argument type is encoded 41 | 42 | | Type | Encoding | 43 | | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 44 | | `bool` | `bool` | 45 | | `u8` | `u8` | 46 | | `u16` | `u16` | 47 | | `u32` | `u32` | 48 | | `u64` | `u64` | 49 | | `b256` | `b256` | 50 | | `struct` | `s<,,...>(,,...)` where ``, ``, ... are the encoded types of the struct fields and ``, ``, ... are the encoded type arguments | 51 | | `enum` | `e<>,,...>(,,...)` where ``, ``, ... are the encoded types of the enum variants and ``, ``, ... are the encoded type arguments | 52 | | `str[]` | `str[]` | 53 | | `array` | `a[;]` where `` is the encoded element type of the array and `` is its length | 54 | | `tuple` | `(,,...)` where ``, ``, ... are the encoded types of the tuple fields | 55 | 56 | > **Note:** Non-generic structs and enums do not require angle brackets. 57 | 58 | ## A Complex Example 59 | 60 | ```rust 61 | enum MyEnum { 62 | Foo: u64, 63 | Bar: bool, 64 | } 65 | struct MyStruct { 66 | bim: T, 67 | bam: MyEnum, 68 | } 69 | 70 | struct MyOtherStruct { 71 | bom: u64, 72 | } 73 | 74 | fn complex_function( 75 | arg1: MyStruct<[b256; 3], u8>, 76 | arg2: [MyStruct; 4], 77 | arg3: (str[5], bool), 78 | arg4: MyOtherStruct, 79 | ); 80 | ``` 81 | 82 | is encoded as: 83 | 84 | ```text 85 | abi MyContract { 86 | complex_function(s(a[b256;3],e(u64,bool)),a[s(u64,e(u64,bool));4],(str[5],bool),s(u64)) 87 | } 88 | ``` 89 | 90 | which is then hashed into: 91 | 92 | ```text 93 | 51fdfdadc37ff569e281a622281af7ec055f8098c40bc566118cbb48ca5fd28b 94 | ``` 95 | 96 | and then the encoded function selector is: 97 | 98 | ```text 99 | 0x0000000051fdfdad 100 | ``` 101 | -------------------------------------------------------------------------------- /src/abi/hash-based-ids.md: -------------------------------------------------------------------------------- 1 | # Hash based IDs 2 | 3 | Hash based ids are deterministically generated from associated types and are used in the JSON ABI for `type` IDs and for `logId`. 4 | This document specifies how the hash based IDS are generated for `type` IDs and for `logId`. 5 | 6 | ## Generation 7 | 8 | Hash based ids for `type` IDs are generated from the `sha256` of a string that represents the type. 9 | 10 | For `logIds` we use the first 8 bytes of the `sha256` of a string that represents the type, this is because the `LOG` and `LOGD` opcodes use a 64bit value as log id. 11 | 12 | ## String representation of types 13 | 14 | For describing the string representation of type we will use the notation `{abi_str(T)}` that should be replaced by the respective ABI string representation of the respective type `T`. 15 | 16 | ### Intrinsics 17 | 18 | `u8` => `"u8"` 19 | `u16` => `"u16"` 20 | `u32` => `"u32"` 21 | `u64` => `"u64"` 22 | `u256` => `"u256"` 23 | `b256` => `"b256"` 24 | `bool` => `"bool"` 25 | 26 | ### String arrays 27 | 28 | String array of size `1` => `"str[1]"` 29 | String array of size `2` => `"str[2]"` 30 | etc. 31 | 32 | ### String slices 33 | 34 | String slice => `"str"` 35 | 36 | ### Arrays 37 | 38 | `[T; 1]` => `"[{abi_str(T)}; 1]"` 39 | `[T; 2]` => `"[{abi_str(T)}; 2]"` 40 | etc. 41 | 42 | ### Tuples 43 | 44 | `()` => `"()"` 45 | `(T1)` => `"({abi_str(T1)})"` 46 | `(T1,T2)` => `"({abi_str(T1)}, {abi_str(T2)})"` 47 | etc. 48 | 49 | ### Enums 50 | 51 | `Option` enum with type parameter `T` => `"enum std::option::Option<{abi_str(T)}>"` 52 | Enum without type parameters named `MyEnum` => `"enum MyEnum"` 53 | Enum with type parameter `T1` named `MyEnum` => `"enum MyEnum<{abi_str(T1)}>"` 54 | Enum with type parameters `T1`, `T2` named `MyEnum` in `my_module` => `"enum my_module::MyEnum<{abi_str(T1)},{abi_str(T2)}>"` 55 | 56 | ### Structs 57 | 58 | `Vec` struct with type parameter `T` => `"struct std::vec::Vec<{abi_str(T)}>"` 59 | Struct without type parameters named `MyStruct` => `"struct MyStruct"` 60 | Struct with type parameter `T1` named `MyStruct` => `"struct MyStruct<{abi_str(T1)}>"` 61 | Struct with type parameters `T1`, `T2` named `MyStruct` in `my_module` => `"struct my_module::MyStruct<{abi_str(T1)},{abi_str(T2)}>"` 62 | 63 | ### Generic Type Parameter 64 | 65 | Generic type parameter `T` if root type => `"generic T"` 66 | Generic type parameter `T` if not root type => `"T"` as in `"struct MyStruct"` 67 | 68 | ### Complex examples composition 69 | 70 | Tuple of array and `u64` => `"([u64,1]; u64)"` 71 | Array of `Option`=> `"[enum std::option::Option; 3]"` 72 | Struct with tuple type parameter => `"struct my_module::MyStruct<(u64, u64)>"` 73 | -------------------------------------------------------------------------------- /src/abi/index.md: -------------------------------------------------------------------------------- 1 | # Application Binary Interface (ABI) 2 | 3 | This document describes and specifies the ABI (Application Binary Interface) of the FuelVM, the Sway programming language, and contracts written in Sway. 4 | 5 | - [JSON ABI Format](./json-abi-format.md) 6 | - [Receipts](./receipts.md) 7 | - [Function Selector Encoding](./fn-selector-encoding.md) 8 | - [Argument Encoding](./argument-encoding.md) 9 | - [Hash Based Ids](./hash-based-ids.md) 10 | -------------------------------------------------------------------------------- /src/abi/receipts.md: -------------------------------------------------------------------------------- 1 | # Receipts 2 | 3 | Upon execution of ABI calls, i.e scripts being executed, a JSON object representing a list of receipts will be returned to the caller. Below is the JSON specification of the possible receipt types. The root will be `receipts_root` which will include an array of `receipts`. 4 | 5 | ```json 6 | { 7 | "receipts_list":[ 8 | { 9 | "type":"", 10 | ... 11 | }, 12 | ... 13 | ] 14 | } 15 | ``` 16 | 17 | All receipts will have a `type` property: 18 | 19 | - `type`: String; the type of the receipt. Can be one of: 20 | - [`Call`](#call-receipt) 21 | - [`Return`](#return-receipt) 22 | - [`ReturnData`](#returndata-receipt) 23 | - [`Panic`](#panic-receipt) 24 | - [`Revert`](#revert-receipt) 25 | - [`Log`](#log-receipt) 26 | - [`Mint`](#mint-receipt) 27 | - [`Burn`](#burn-receipt) 28 | - [`LogData`](#logdata-receipt) 29 | - [`Transfer`](#transfer-receipt) 30 | - [`TransferOut`](#transferout-receipt) 31 | - [`ScriptResult`](#scriptresult-receipt) 32 | - [`MessageOut`](#messageout-receipt) 33 | 34 | Then, each receipt type will have its own properties. Some of these properties are related to the FuelVM's registers, as specified in more detail [here](../fuel-vm/instruction-set.md). 35 | 36 | _Important note:_ For the JSON representation of receipts, we represent 64-bit unsigned integers as a JSON `String` due to limitations around the type `Number` in the JSON specification, which only supports numbers up to `2^{53-1}`, while the FuelVM's registers hold values up to `2^64`. 37 | 38 | ## Panic Receipt 39 | 40 | - `type`: `Panic`. 41 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context. `null` otherwise. 42 | - `reason`: Optional decimal string representation of an 8-bit unsigned integer; panic reason. 43 | Not included in canonical receipt form. 44 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 45 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 46 | - `contractId`: Optional hexadecimal string representation of the 256-bit (32-byte) contract ID if applicable. `null` otherwise. 47 | Not included in canonical receipt form. Primary use is for access-list estimation by SDK. 48 | 49 | ```json 50 | { 51 | "type": "Panic", 52 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 53 | "reason": "1", 54 | "pc": "0xffffffffffffffff", 55 | "is": "0xfffffffffffffffe", 56 | "contractId": "0x0000000000000000000000000000000000000000000000000000000000000000" 57 | } 58 | ``` 59 | 60 | ## `Return` Receipt 61 | 62 | - `type`: `Return`. 63 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context; `null` otherwise. 64 | - `val`: Decimal string representation of a 64-bit unsigned integer; value of register `$rA`. 65 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 66 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 67 | 68 | ```json 69 | { 70 | "type": "Return", 71 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 72 | "val": "18446744073709551613", 73 | "pc": "0xffffffffffffffff", 74 | "is": "0xfffffffffffffffe" 75 | } 76 | ``` 77 | 78 | ## `Call` Receipt 79 | 80 | - `type`: `Call`. 81 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context; `null` otherwise. 82 | - `to`: Hexadecimal representation of the 256-bit (32-byte) contract ID of the callee. 83 | - `amount`: Decimal string representation of a 64-bit unsigned integer; amount of coins to forward. 84 | - `asset_id`: Hexadecimal string representation of the 256-bit (32-byte) asset ID of coins to forward. 85 | - `gas`: Decimal string representation of a 64-bit unsigned integer; amount gas to forward; value in register `$rD`. 86 | - `param1`: Hexadecimal string representation of a 64-bit unsigned integer; first parameter, holds the function selector. 87 | - `param2`: Hexadecimal string representation of a 64-bit unsigned integer; second parameter, typically used for the user-specified input to the ABI function being selected. 88 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 89 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 90 | 91 | ```json 92 | { 93 | "type": "Call", 94 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 95 | "to": "0x1c98ff5d121a6d5afc8135821acb3983e460ef0590919266d620bfc7b9b6f24d", 96 | "amount": "10000", 97 | "asset_id": "0xa5149ac6064222922eaa226526b0d853e7871e28c368f6afbcfd60a6ef8d6e61", 98 | "gas": "500", 99 | "param1": "0x28f5c28f5c28f5c", 100 | "param2": "0x68db8bac710cb", 101 | "pc": "0xffffffffffffffff", 102 | "is": "0xfffffffffffffffe" 103 | } 104 | ``` 105 | 106 | ## `Log` Receipt 107 | 108 | - `type`: `Log`. 109 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context. `null` otherwise. 110 | - `ra`: Decimal string representation of a 64-bit unsigned integer; value of register `$rA`. 111 | - `rb`: Decimal string representation of a 64-bit unsigned integer; value of register `$rB`. 112 | - `rc`: Decimal string representation of a 64-bit unsigned integer; value of register `$rC`. 113 | - `rd`: Decimal string representation of a 64-bit unsigned integer; value of register `$rD`. 114 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 115 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 116 | 117 | ```json 118 | { 119 | "type": "Log", 120 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 121 | "ra": "1844674407370", 122 | "rb": "1844674407371", 123 | "rc": "1844674407372", 124 | "rd": "1844674407373", 125 | "pc": "0xffffffffffffffff", 126 | "is": "0xfffffffffffffffe" 127 | } 128 | ``` 129 | 130 | ## `Mint` Receipt 131 | 132 | - `type`: `Mint`. 133 | - `sub_id`: Hexadecimal string representation of the 256-bit (32-byte) asset sub identifier ID; derived from register `$rB`. 134 | - `contract_id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context. 135 | - `val`: Decimal string representation of a 64-bit unsigned integer; value of register `$rA`. 136 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 137 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 138 | 139 | ```json 140 | { 141 | "type": "Mint", 142 | "sub_id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 143 | "contract_id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 144 | "val": "18446744073709551613", 145 | "pc": "0xffffffffffffffff", 146 | "is": "0xfffffffffffffffe" 147 | } 148 | ``` 149 | 150 | ## `Burn` Receipt 151 | 152 | - `type`: `Burn`. 153 | - `sub_id`: Hexadecimal string representation of the 256-bit (32-byte) asset sub identifier ID; derived from register `$rB`. 154 | - `contract_id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context. 155 | - `val`: Decimal string representation of a 64-bit unsigned integer; value of register `$rA`. 156 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 157 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 158 | 159 | ```json 160 | { 161 | "type": "Burn", 162 | "sub_id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 163 | "contract_id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 164 | "val": "18446744073709551613", 165 | "pc": "0xffffffffffffffff", 166 | "is": "0xfffffffffffffffe" 167 | } 168 | ``` 169 | 170 | ## `LogData` Receipt 171 | 172 | - `type`: `LogData`. 173 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context. `null` otherwise. 174 | - `ra`: Decimal string representation of a 64-bit unsigned integer; value of register `$rA` 175 | - `rb`: Decimal string representation of a 64-bit unsigned integer; value of register `$rB` 176 | - `ptr`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$rC`. 177 | - `len`: Decimal string representation of a 64-bit unsigned integer; value of register `$rD`. 178 | - `digest`: Hexadecimal string representation of the 256-bit (32-byte) hash of `MEM[$rC, $rD]`. 179 | - `data`: Hexadecimal string representation of the value of the memory range `MEM[$rC, $rD]`. 180 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 181 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 182 | 183 | ```json 184 | { 185 | "type": "LogData", 186 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 187 | "ra": "1844674407370", 188 | "rb": "1844674407371", 189 | "ptr": "0x1ad7f29abcc", 190 | "len": "66544", 191 | "digest": "0xd28b78894e493c98a196aa51b432b674e4813253257ed9331054ee8d6813b3aa", 192 | "pc": "0xffffffffffffffff", 193 | "data": "0xa7c5ac471b47", 194 | "is": "0xfffffffffffffffe" 195 | } 196 | ``` 197 | 198 | ## `ReturnData` Receipt 199 | 200 | - `type`: `ReturnData`. 201 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context. `null` otherwise. 202 | - `ptr`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$rA`. 203 | - `len`: Decimal string representation of a 64-bit unsigned integer; value of register `$rB`. 204 | - `digest`: Hexadecimal string representation of 256-bit (32-byte), hash of `MEM[$rA, $rB]`. 205 | - `data`: Hexadecimal string representation of the value of the memory range `MEM[$rA, $rB]`. 206 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 207 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 208 | 209 | ```json 210 | { 211 | "type": "ReturnData", 212 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 213 | "ptr": "0x1ad7f29abcc", 214 | "len": "1844", 215 | "digest": "0xd28b78894e493c98a196aa51b432b674e4813253257ed9331054ee8d6813b3aa", 216 | "pc": "0xffffffffffffffff", 217 | "data": "0xa7c5ac471b47", 218 | "is": "0xfffffffffffffffe" 219 | } 220 | ``` 221 | 222 | ## `Revert` Receipt 223 | 224 | - `type`: `Revert`. 225 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context. `null` otherwise. 226 | - `val`: Decimal string representation of a 64-bit unsigned integer; value of register `$rA`. 227 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 228 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 229 | 230 | ```json 231 | { 232 | "type": "Revert", 233 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 234 | "val": "1844674407372", 235 | "pc": "0xffffffffffffffff", 236 | "is": "0xfffffffffffffffe" 237 | } 238 | ``` 239 | 240 | ## `Transfer` Receipt 241 | 242 | - `type`: `Transfer`. 243 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context. `null` otherwise. 244 | - `to`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the recipient contract. 245 | - `amount`: Decimal string representation of a 64-bit unsigned integer; amount of coins to forward. 246 | - `asset_id`: Hexadecimal string representation of the 256-bit (32-byte) asset ID of coins to forward. 247 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 248 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 249 | 250 | ```json 251 | { 252 | "type": "Transfer", 253 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 254 | "to": "0x1c98ff5d121a6d5afc8135821acb3983e460ef0590919266d620bfc7b9b6f24d", 255 | "amount": "10000", 256 | "asset_id": "0xa5149ac6064222922eaa226526b0d853e7871e28c368f6afbcfd60a6ef8d6e61", 257 | "pc": "0xffffffffffffffff", 258 | "is": "0xfffffffffffffffe" 259 | } 260 | ``` 261 | 262 | ## `TransferOut` Receipt 263 | 264 | - `type`: `TransferOut`. 265 | - `id`: Hexadecimal string representation of the 256-bit (32-byte) contract ID of the current context if in an internal context. `null` otherwise. 266 | - `to`: Hexadecimal string representation of the 256-bit (32-byte) _address_ to transfer coins to. 267 | - `amount`: Decimal string representation of a 64-bit unsigned integer; amount of coins to forward. 268 | - `asset_id`: Hexadecimal string representation of the 256-bit (32-byte) asset ID of coins to forward. 269 | - `pc`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$pc`. 270 | - `is`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$is`. 271 | 272 | ```json 273 | { 274 | "type": "TransferOut", 275 | "id": "0x39150017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 276 | "to": "0x1c98ff5d121a6d5afc8135821acb3983e460ef0590919266d620bfc7b9b6f24d", 277 | "amount": "10000", 278 | "asset_id": "0xa5149ac6064222922eaa226526b0d853e7871e28c368f6afbcfd60a6ef8d6e61", 279 | "pc": "0xffffffffffffffff", 280 | "is": "0xfffffffffffffffe" 281 | } 282 | ``` 283 | 284 | ## `ScriptResult` Receipt 285 | 286 | - `type`: `ScriptResult`. 287 | - `result`: Hexadecimal string representation of a 64-bit unsigned integer; `0` if script exited successfully, `any` otherwise. 288 | - `gas_used`: Decimal string representation of a 64-bit unsigned integer; amount of gas consumed by the script. 289 | 290 | ```json 291 | { 292 | "type": "ScriptResult", 293 | "result": "0x00", 294 | "gas_used": "400" 295 | } 296 | ``` 297 | 298 | ## `MessageOut` Receipt 299 | 300 | - `type`: `MessageOut`. 301 | - `sender`: Hexadecimal string representation of the 256-bit (32-byte) address of the message sender: `MEM[$fp, 32]`. 302 | - `recipient`: Hexadecimal string representation of the 256-bit (32-byte) address of the message recipient: `MEM[$rA, 32]`. 303 | - `amount`: Hexadecimal string representation of a 64-bit unsigned integer; value of register `$rD`. 304 | - `nonce`: Hexadecimal string representation of the 256-bit (32-byte) message nonce as described [here](../identifiers/utxo-id.md#message-nonce). 305 | - `len`: Decimal string representation of a 16-bit unsigned integer; value of register `$rC`. 306 | - `digest`: Hexadecimal string representation of 256-bit (32-byte), hash of `MEM[$rB, $rC]`. 307 | - `data`: Hexadecimal string representation of the value of the memory range `MEM[$rB, $rC]`. 308 | 309 | ```json 310 | { 311 | "type": "MessageOut", 312 | "sender": "0x38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff05139150017c9e", 313 | "recipient": "0x4710162c2e3a95a6faff05139150017c9e38e5e280432d546fae345d6ce6d8fe", 314 | "amount": "0xe6d8fe4710162c2e", 315 | "nonce": "0x47101017c9e38e5e280432d546fae345d6ce6d8fe4710162c2e3a95a6faff051", 316 | "len": "65535", 317 | "digest": "0xd28b78894e493c98a196aa51b432b674e4813253257ed9331054ee8d6813b3aa", 318 | "data": "0xa7c5ac471b47" 319 | } 320 | ``` 321 | -------------------------------------------------------------------------------- /src/fuel-vm/index.md: -------------------------------------------------------------------------------- 1 | # Fuel VM Specification 2 | 3 | - [Introduction](#introduction) 4 | - [Parameters](#parameters) 5 | - [Semantics](#semantics) 6 | - [Flags](#flags) 7 | - [Instruction Set](#instruction-set) 8 | - [VM Initialization](#vm-initialization) 9 | - [Contexts](#contexts) 10 | - [Predicate Estimation and Verification](#predicate-estimation-and-verification) 11 | - [Script Execution](#script-execution) 12 | - [Call](#call) 13 | - [Call Frames](#call-frames) 14 | - [Ownership](#ownership) 15 | 16 | ## Introduction 17 | 18 | This document provides the specification for the Fuel Virtual Machine (FuelVM). The specification covers the types, instruction set, and execution semantics. 19 | 20 | ## Parameters 21 | 22 | | name | type | value | note | 23 | |-------------------------|----------|---------|-----------------------------------------| 24 | | `CONTRACT_MAX_SIZE` | `uint64` | | Maximum contract size, in bytes. | 25 | | `VM_MAX_RAM` | `uint64` | `2**26` | 64 MiB. | 26 | | `MESSAGE_MAX_DATA_SIZE` | `uint64` | | Maximum size of message data, in bytes. | 27 | 28 | ## Semantics 29 | 30 | FuelVM instructions are exactly 32 bits (4 bytes) wide and comprise of a combination of: 31 | 32 | - Opcode: 8 bits 33 | - Register/special register (see below) identifier: 6 bits 34 | - Immediate value: 12, 18, or 24 bits, depending on operation 35 | 36 | Of the 64 registers (6-bit register address space), the first `16` are reserved: 37 | 38 | | value | register | name | description | 39 | |--------|----------|---------------------|----------------------------------------------------------------------------------| 40 | | `0x00` | `$zero` | zero | Contains zero (`0`), for convenience. | 41 | | `0x01` | `$one` | one | Contains one (`1`), for convenience. | 42 | | `0x02` | `$of` | overflow | Contains overflow/underflow of addition, subtraction, and multiplication. | 43 | | `0x03` | `$pc` | program counter | The program counter. Memory address of the current instruction. | 44 | | `0x04` | `$ssp` | stack start pointer | Memory address of bottom of current writable stack area. | 45 | | `0x05` | `$sp` | stack pointer | Memory address on top of current writable stack area (points to free memory). | 46 | | `0x06` | `$fp` | frame pointer | Memory address of beginning of current call frame. | 47 | | `0x07` | `$hp` | heap pointer | Memory address below the current bottom of the heap (points to used/OOB memory). | 48 | | `0x08` | `$err` | error | Error codes for particular operations. | 49 | | `0x09` | `$ggas` | global gas | Remaining gas globally. | 50 | | `0x0A` | `$cgas` | context gas | Remaining gas in the context. | 51 | | `0x0B` | `$bal` | balance | Received balance for this context. | 52 | | `0x0C` | `$is` | instructions start | Pointer to the start of the currently-executing code. | 53 | | `0x0D` | `$ret` | return value | Return value or pointer. | 54 | | `0x0E` | `$retl` | return length | Return value length in bytes. | 55 | | `0x0F` | `$flag` | flags | Flags register. | 56 | 57 | Integers are represented in [big-endian](https://en.wikipedia.org/wiki/Endianness) format, and all operations are unsigned. Boolean `false` is `0` and Boolean `true` is `1`. 58 | 59 | Registers are 64 bits (8 bytes) wide. Words are the same width as registers. 60 | 61 | Persistent state (i.e. storage) is a key-value store with 32-byte keys and 32-byte values. Each contract has its own persistent state that is independent of other contracts. This is committed to in a Sparse Binary Merkle Tree. 62 | 63 | ## Flags 64 | 65 | | value | name | description | 66 | |--------|----------------|---------------------------------------------------------------------------| 67 | | `0x01` | `F_UNSAFEMATH` | If set, undefined arithmetic zeroes target and sets `$err` without panic. | 68 | | `0x02` | `F_WRAPPING` | If set, overflowing arithmetic wraps around and sets `$of` without panic. | 69 | 70 | All other flags are reserved, any must be set to zero. 71 | 72 | ## Instruction Set 73 | 74 | A complete instruction set of the Fuel VM is documented in [the following page](./instruction-set.md). 75 | 76 | ## VM Initialization 77 | 78 | Every time the VM runs, a single monolithic memory of size `VM_MAX_RAM` bytes is allocated, indexed by individual byte. A stack and heap memory model is used, allowing for dynamic memory allocation in higher-level languages. The stack begins at `0` and grows upward. The heap begins at `VM_MAX_RAM` and grows downward. 79 | 80 | To initialize the VM, the following is pushed on the stack sequentially: 81 | 82 | 1. Transaction hash (`byte[32]`, word-aligned), computed as defined [here](../identifiers/transaction-id.md). 83 | 1. Base asset ID (`byte[32]`, word-aligned) 84 | 1. [`MAX_INPUTS`](../tx-format/consensus_parameters.md) pairs of `(asset_id: byte[32], balance: uint64)`, of: 85 | 1. For [predicate estimation and verification](#predicate-estimation-and-verification), zeroes. 86 | 1. For [script execution](#script-execution), the free balance for each asset ID seen in the transaction's inputs, ordered in ascending order. If there are fewer than `MAX_INPUTS` asset IDs, the pair has a value of zero. 87 | 1. Transaction length, in bytes (`uint64`, word-aligned). 88 | 1. The [transaction, serialized](../tx-format/index.md). 89 | 90 | Then the following registers are initialized (without explicit initialization, all registers are initialized to zero): 91 | 92 | 1. `$ssp = 32 + 32 + MAX_INPUTS*(32+8) + size(tx))`: the writable stack area starts immediately after the serialized transaction in memory (see above). 93 | 1. `$sp = $ssp`: writable stack area is empty to start. 94 | 1. `$hp = VM_MAX_RAM`: the heap area begins at the top and is empty to start. 95 | 96 | ## Contexts 97 | 98 | There are 4 _contexts_ in the FuelVM: [predicate estimation and verification](#predicate-estimation-and-verification), [scripts](#script-execution), and [calls](#call). A context is an isolated execution environment with defined [memory ownership](#ownership) and can be _external_ or _internal_: 99 | 100 | - External: predicate and script. `$fp` will be zero. 101 | - Internal: call. `$fp` will be non-zero. 102 | 103 | [Returning](./instruction-set.md#return-return-from-call) from a context behaves differently depending on whether the context is external or internal. 104 | 105 | ### Predicate Estimation and Verification 106 | 107 | There are two ways to run predicates on the VM: 108 | 109 | 1. Estimation: runs the predicate and updates the amount of gas used 110 | 1. Verification: runs the predicate and verifies the amount of gas used matches the input 111 | 112 | For any input of type [`InputType.Coin`](../tx-format/input.md#inputcoin) or [`InputType.Message`](../tx-format/input.md#inputmessage), a non-zero `predicateLength` field means the UTXO being spent is a [`P2SH`](https://en.bitcoin.it/P2SH) rather than a [`P2PKH`](https://en.bitcoin.it/P2PKH) output. 113 | 114 | For each such input in the transaction, the VM is [initialized](#vm-initialization), then: 115 | 116 | 1. `$pc` and `$is` are set to the start of the input's `predicate` field. 117 | 1. `$ggas` and `$cgas` are set to `MAX_GAS_PER_PREDICATE` for estimation, and `predicateGasUsed` for verification. 118 | 119 | Predicate execution will fail if gas is exhausted during execution. 120 | 121 | During predicate mode, hitting any [contract instruction](./instruction-set.md#contract-instructions) (except `ldc` with non-contract target) causes predicate verification to halt, returning Boolean `false`. 122 | 123 | A predicate that halts without returning Boolean `true` would not pass verification, making the entire transaction invalid. Note that predicate return value is monotonic with respect to time (i.e. if a predicate evaluates to `true` then it will always evaluate to `true` in the future). 124 | 125 | After successful execution, the run mode is determines the final step: 126 | 127 | 1. Estimation: `predicateGasUsed` is set to `MAX_GAS_PER_PREDICATE - $ggas`. 128 | 1. Verification: if `$ggas` is non-zero, predicate verification fails. 129 | 130 | ### Script Execution 131 | 132 | If script bytecode is present, transaction validation requires execution. 133 | 134 | The VM is [initialized](#vm-initialization), then: 135 | 136 | 1. `$pc` and `$is` are set to the start of the transaction's script bytecode. 137 | 1. `$ggas` and `$cgas` are set to `tx.scriptGasLimit`. 138 | 139 | Following initialization, execution begins. 140 | 141 | For each instruction, its gas cost `gc` is first computed. If `gc > $cgas`, deduct `$cgas` from `$ggas` and `$cgas` (i.e. spend all of `$cgas` and no more), then [revert](./instruction-set.md#rvrt-revert) immediately without actually executing the instruction. Otherwise, deduct `gc` from `$ggas` and `$cgas`. 142 | 143 | After the script has been executed, `tx.receiptsRoot` is updated to contain the Merkle root of the receipts, [as described in the `TransactionScript` spec](../tx-format/transaction.md#`TransactionScript`). 144 | 145 | ### Call 146 | 147 | Call context is entered via [`CALL` instruction](./instruction-set.md#call-call-contract). It's also called _internal context_, or _contract context_. Call context is used to access state of a contract. 148 | 149 | ## Call Frames 150 | 151 | Cross-contract calls push a _call frame_ onto the stack, similar to a stack frame used in regular languages for function calls (which may be used by a high-level language that targets the FuelVM). The distinction is as follows: 152 | 153 | 1. Stack frames: store metadata across trusted internal (i.e. intra-contract) function calls. Not supported natively by the FuelVM, but may be used as an abstraction at a higher layer. 154 | 1. Call frames: store metadata across untrusted external (i.e. inter-contract) calls. Supported natively by the FuelVM. 155 | 156 | Call frames are needed to ensure that the called contract cannot mutate the running state of the current executing contract. They segment access rights for memory: the currently-executing contracts may only write to their own call frame and their own heap. 157 | 158 | A call frame consists of the following, word-aligned: 159 | 160 | | bytes | type | value | description | 161 | |-------|---------------|------------|-------------------------------------------------------------------------------| 162 | | | | | **Unwritable area begins.** | 163 | | 32 | `byte[32]` | `to` | Contract ID for this call. | 164 | | 32 | `byte[32]` | `asset_id` | asset ID of forwarded coins. | 165 | | 8*64 | `byte[8][64]` | `regs` | Saved registers from previous context. | 166 | | 8 | `uint64` | `codesize` | Code size in bytes, padded to the next word boundary. | 167 | | 8 | `byte[8]` | `param1` | First parameter. | 168 | | 8 | `byte[8]` | `param2` | Second parameter. | 169 | | 1* | `byte[]` | `code` | Zero-padded to 8-byte alignment, but individual instructions are not aligned. | 170 | | | | | **Unwritable area ends.** | 171 | | * | | | Call frame's stack. | 172 | 173 | ## Access rights 174 | 175 | Only memory that has been allocated is accessible. 176 | In other words, memory between highest-ever `$sp` value and current `$hp` 177 | is inaccessible. Attempting to read or write 178 | memory that has not been allocated will result in VM panic. 179 | Similarly reads or writes that cross from the stack to the heap 180 | will panic. Note that stack remains readable even after stack 181 | frame has been shrunk. However, if the heap is afterwards expanded 182 | to cover that area, the crossing read prohibition still remains, 183 | while all memory is accessible. 184 | 185 | ### Ownership 186 | 187 | Whenever memory is written to (i.e. with [`SB`](./instruction-set.md#sb-store-byte) or [`SW`](./instruction-set.md#sw-store-word)), or write access is granted (i.e. with [`CALL`](./instruction-set.md#call-call-contract)), ownership must be checked. 188 | 189 | If the context is external, the owned memory range is: 190 | 191 | 1. `[$ssp, $sp)`: the writable stack area. 192 | 1. `[$hp, VM_MAX_RAM)`: the heap area allocated by this script or predicate. 193 | 194 | If the context is internal, the owned memory range for a call frame is: 195 | 196 | 1. `[$ssp, $sp)`: the writable stack area of the call frame. 197 | 1. `[$hp, $fp->$hp)`: the heap area allocated by this call frame. 198 | 199 | ### Executability 200 | 201 | Memory is only executable in range `[$is, $ssp)`. Attempting to execute instructions outside these boundaries will cause a panic. This area never overlaps with writable memory, essentially providing [W^X](https://en.wikipedia.org/wiki/W%5EX) protection. 202 | -------------------------------------------------------------------------------- /src/identifiers/asset.md: -------------------------------------------------------------------------------- 1 | # Asset ID 2 | 3 | The _asset ID_ (also called _asset hash_) of a asset is computed as 4 | the [hash](../protocol/cryptographic-primitives.md#hashing) of the `CONTRACT_ID` and a 256-bit `SUB_IDENTIFIER`. 5 | 6 | ```python 7 | sha256(CONTRACT_ID ++ SUB_IDENTIFIER) 8 | ``` 9 | -------------------------------------------------------------------------------- /src/identifiers/blob-id.md: -------------------------------------------------------------------------------- 1 | # Blob ID 2 | 3 | The _blob ID_ (also called _blob hash_) of a transaction is computed as 4 | the [hash](../protocol/cryptographic-primitives.md#hashing) of the blob data. 5 | 6 | Blob ID calculation doesn't vary between chains. 7 | 8 | ```python 9 | sha256(blob_data) 10 | ``` 11 | -------------------------------------------------------------------------------- /src/identifiers/contract-id.md: -------------------------------------------------------------------------------- 1 | # Contract ID 2 | 3 | For a transaction of type `TransactionType.Create`, `tx`, the contract ID is 4 | `sha256(0x4655454C ++ tx.data.salt ++ root(tx.data.witnesses[bytecodeWitnessIndex].data) ++ root_smt(tx.storageSlots))`, 5 | where `root` is the Merkle root of [the binary Merkle tree](../protocol/cryptographic-primitives.md#binary-merkle-tree) with 6 | each leaf being 16KiB of instructions, and `root_smt` is the 7 | [Sparse Merkle tree](../protocol/cryptographic-primitives.md#sparse-merkle-tree) root of the provided key-value pairs. 8 | If the bytecode is not a multiple of 16 KiB, the final leaf should be zero-padded rounding up to the nearest multiple 9 | of 8 bytes. 10 | -------------------------------------------------------------------------------- /src/identifiers/index.md: -------------------------------------------------------------------------------- 1 | # Identifiers 2 | 3 | This chapter defines how to compute unique identifiers. 4 | 5 | - [Asset ID](./asset.md) 6 | - [Blob ID](./blob-id.md) 7 | - [Contract ID](./contract-id.md) 8 | - [Predicate ID](./predicate-id.md) 9 | - [Transaction ID](./transaction-id.md) 10 | - [UTXO ID](./utxo-id.md) 11 | - [Coin ID](./utxo-id.md#coin-id) 12 | - [Message ID](./utxo-id.md#message-id) 13 | - [Message Nonce](./utxo-id.md#message-nonce) 14 | - [Fee ID](./utxo-id.md#fee-id) 15 | -------------------------------------------------------------------------------- /src/identifiers/predicate-id.md: -------------------------------------------------------------------------------- 1 | # Predicate ID 2 | 3 | For an input of type `InputType.Coin` or `InputType.Message`, `input`, the predicate owner is calculated as: 4 | `sha256(0x4655454C ++ root(input.predicate))`, where `root` is the Merkle root of 5 | [the binary Merkle tree](../protocol/cryptographic-primitives.md#binary-merkle-tree) each leaf being 16KiB of instructions. 6 | If the bytecode is not a multiple of 16 KiB, the final leaf should be zero-padded rounding up to the nearest multiple of 8 bytes. 7 | -------------------------------------------------------------------------------- /src/identifiers/transaction-id.md: -------------------------------------------------------------------------------- 1 | # Transaction ID 2 | 3 | The _transaction ID_ (also called _transaction hash_) of a transaction is computed as 4 | the [hash](../protocol/cryptographic-primitives.md#hashing) of `CHAIN_ID` and the 5 | [serialized transaction](../tx-format/transaction.md) with [fields zeroed out for signing](../tx-format/index.md) 6 | (see different inputs and outputs for which fields are set to zero), and without witness data. In other words, only 7 | all non-witness data is hashed. 8 | 9 | ```python 10 | sha256(CHAIN_ID ++ serialized_tx(tx)) 11 | ``` 12 | -------------------------------------------------------------------------------- /src/identifiers/utxo-id.md: -------------------------------------------------------------------------------- 1 | # UTXO ID 2 | 3 | ## Coin ID 4 | 5 | Is represented as an _outpoint_: a pair of [transaction ID](./transaction-id.md) as `byte[32]` and output index as a `uint16`. 6 | 7 | ## Message ID 8 | 9 | The ID of a message is computed as the [hash](../protocol/cryptographic-primitives.md#hashing) of: 10 | 11 | 1. the sender address as `byte[32]`, 12 | 1. the recipient address as `byte[32]`, 13 | 1. the [Message nonce](#message-nonce) as `byte[32]`, 14 | 1. the amount being sent with the message as `uint64`, 15 | 1. the message data as `byte[]` 16 | 17 | `hash(byte[32] ++ byte[32] ++ byte[32] ++ uint64 ++ byte[])`. The address values are serialized as a byte array of length 32 left-padded with zeroes, and all other value types are serialized according to the standard [transaction serialization](../tx-format/transaction.md). Note that the message data length is not included since there is only one dynamically sized field and can be implicitly determined by the hash preimage size. 18 | 19 | ### Message Nonce 20 | 21 | The nonce value for `InputMessage` is determined by the sending system and is published at the time the message is sent. The nonce value for `OutputMessage` is computed as the [hash](../protocol/cryptographic-primitives.md#hashing) of the [Transaction ID](./transaction-id.md) that emitted the message and the index of the message receipt `uint16` (with canonical encoding): `hash(byte[32] ++ canonical(uint16))`. 22 | 23 | ## Fee ID 24 | 25 | The UTXO ID of collected fees in a block is the block height as a 32-byte big-endian unsigned integer (i.e. the first byte of the 32-byte array is the most significant byte, and so on). 26 | -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | # Fuel Specifications 2 | 3 | 4 | **Fuel: A Secure Decentralized Generalized Massively Scalable Transaction Ledger** 5 | 6 | This book specifies the Fuel protocol, including the Fuel Virtual Machine 7 | (short: FuelVM), a blazingly fast verifiable blockchain virtual machine. 8 | 9 | ## Protocol 10 | 11 | - [**Transaction Format**](./tx-format/index.md) - The Fuel transaction format. 12 | - [**Computing Identifiers**](./identifiers/index.md) - Computing unique IDs for transactions, contracts and UTXOs. 13 | - [**Transaction Validity**](./protocol/tx-validity.md) - Defines transaction validity rules. 14 | - [**Cryptographic Primitives**](./protocol/cryptographic-primitives.md) - Cryptographic primitives used in Fuel. 15 | - [**Application Binary Interface (ABI)**](./abi/index.md) - Low-level details on interfacing with Fuel bytecode. 16 | - [**Storage Slot Initialization**](./protocol/storage-initialization.md) - JSON format for contract storage slot initialization. 17 | - [**Block Header Format**](./protocol/block-header.md) - The Fuel block header format. 18 | - [**Relayer/Bridge**](./protocol/relayer.md) - The Fuel relayer/bridge protocol. 19 | 20 | ## FuelVM 21 | 22 | - [**Overview**](./fuel-vm/index.md) - Describes the FuelVM at a high level, from its architecture to how it is initialized. 23 | - [**Instruction Set**](./fuel-vm/instruction-set.md) - Defines the FuelVM instruction set. 24 | 25 | ## Network-Specific 26 | 27 | - [**Proof of Authority (PoA)**](./networks/poa.md) - The Fuel Proof of Authority Network. 28 | 29 | ## Testing 30 | 31 | - [**Sparse Merkle Tree**](./tests/sparse-merkle-tree-tests.md) - A test suite for verifying correctness of SMT outputs. 32 | -------------------------------------------------------------------------------- /src/networks/index.md: -------------------------------------------------------------------------------- 1 | # Networks 2 | 3 | Specifications for network-specific components of the protocol. 4 | 5 | - [PoA Network](./poa.md) 6 | -------------------------------------------------------------------------------- /src/networks/poa.md: -------------------------------------------------------------------------------- 1 | # PoA Network 2 | 3 | ## Consensus Header 4 | 5 | Wraps the [application header](../protocol/block-header.md#application-header). 6 | 7 | name | type | description 8 | ------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------- 9 | `prevRoot` | `byte[32]` | [Merkle root](../protocol/cryptographic-primitives.md#binary-merkle-tree) of all previous consensus header hashes (i.e. not including this block). 10 | `height` | `uint32` | Height of this block. 11 | `timestamp` | `uint64` | Time this block was created, in [TAI64](https://cr.yp.to/libtai/tai64.html) format. 12 | `applicationHash` | `byte[32]` | [Hash](../protocol/cryptographic-primitives.md#hashing) of serialized [application header](../protocol/block-header.md#application-header) for this block. 13 | 14 | Consensus for the consensus header is a single [signature](../protocol/cryptographic-primitives.md#public-key-cryptography) from the authority over the [hash](../protocol/cryptographic-primitives.md#hashing) of the serialized consensus header. 15 | 16 | Since the system is secure under the assumption the authority is honest, there is no need for committing to the authority signatures in the header. 17 | -------------------------------------------------------------------------------- /src/protocol/block-header.md: -------------------------------------------------------------------------------- 1 | # Block Header 2 | 3 | ## Application Header 4 | 5 | The application header is a network-agnostic block header. Different [networks](../networks/index.md) may wrap the application header in a consensus header, depending on their consensus protocol. 6 | 7 | | name | type | description | 8 | |----------------------------------|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 9 | | `da_height` | `uint64` | Height of the data availability layer up to which (inclusive) input messages are processed. | 10 | | `consensusParametersVersion` | `uint32` | The version of the consensus parameters used to execute this block. | 11 | | `stateTransitionBytecodeVersion` | `uint32` | The version of the state transition bytecode used to execute this block. | 12 | | `txCount` | `uint16` | Number of [transaction](../tx-format/transaction.md)s in this block. | 13 | | `message_receipt_count` | `uint32` | Number of [output message](../abi/receipts.md#messageout-receipt)s in this block. | 14 | | `txRoot` | `byte[32]` | [Merkle root](./cryptographic-primitives.md#binary-merkle-tree) of [transaction](../tx-format/transaction.md)s in this block. | 15 | | `message_outbox_root` | `byte[32]` | [Merkle root](./cryptographic-primitives.md#binary-merkle-tree) of [output message](../abi/receipts.md#messageout-receipt)s [`messageId`](../identifiers/utxo-id.md#message-id) in this block. | 16 | | `event_inbox_root` | `byte[32]` | [Merkle root](./cryptographic-primitives.md#binary-merkle-tree) of all [events](./relayer.md) imported from L1 in this block. The order of the events added to the Merkle tree is the L1 block order, and the index of each event within each block | 17 | -------------------------------------------------------------------------------- /src/protocol/cryptographic-primitives.md: -------------------------------------------------------------------------------- 1 | # Cryptographic Primitives 2 | 3 | - [Hashing](#hashing) 4 | - [Merkle Trees](#merkle-trees) 5 | - [Binary Merkle Tree](#binary-merkle-tree) 6 | - [Sparse Merkle Tree](#sparse-merkle-tree) 7 | - [EcDSA Public-Key Cryptography](#ecdsa-public-key-cryptography) 8 | - [EdDSA Public-Key Cryptography](#eddsa-public-key-cryptography) 9 | 10 | ## Hashing 11 | 12 | All hashing is done with SHA-2-256 (also known as SHA-256), defined in [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf). 13 | 14 | ## `HashDigest` 15 | 16 | Output of the [hashing](#hashing) function. Exactly 256 bits (32 bytes) long. 17 | 18 | ## Merkle Trees 19 | 20 | Two Merkle tree structures are used: a Binary Merkle Tree (to commit to bytecode) and a Sparse Merkle Tree (to commit to contract storage, i.e. state). 21 | 22 | ### Binary Merkle Tree 23 | 24 | Binary Merkle trees are constructed in the same fashion as described in [Certificate Transparency (RFC-6962)](https://tools.ietf.org/html/rfc6962), except for using [a different hashing function](#hashing). Leaves are hashed once to get leaf node values and internal node values are the hash of the concatenation of their children (either leaf nodes or other internal nodes). 25 | 26 | Nodes contain a single field: 27 | 28 | | name | type | description | 29 | |------|---------------------------|-------------| 30 | | `v` | [`HashDigest`](#hashdigest) | Node value. | 31 | 32 | The base case (an empty tree) is defined as the [hash](#hashing) of the empty string: 33 | 34 | ```C++ 35 | node.v = 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 36 | ``` 37 | 38 | For leaf node `node` of leaf data `d`: 39 | 40 | ```C++ 41 | node.v = h(0x00, serialize(d)) 42 | ``` 43 | 44 | For internal node `node` with children `l` and `r`: 45 | 46 | ```C++ 47 | node.v = h(0x01, l.v, r.v) 48 | ``` 49 | 50 | Note that rather than duplicating the last node if there are an odd number of nodes (the [Bitcoin design](https://github.com/bitcoin/bitcoin/blob/5961b23898ee7c0af2626c46d5d70e80136578d3/src/consensus/merkle.cpp#L9-L43)), trees are allowed to be imbalanced. In other words, the height of each leaf may be different. For an example, see Section 2.1.3 of [Certificate Transparency (RFC-6962)](https://tools.ietf.org/html/rfc6962#section-2.1.3). 51 | 52 | Leaves and internal nodes are hashed differently: the one-byte `0x00` is prepended for leaf nodes while `0x01` is prepended for internal nodes. This avoids a second-preimage attack [where internal nodes are presented as leaves](https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack) trees with leaves at different heights. 53 | 54 | #### Binary Merkle Tree Inclusion Proofs 55 | 56 | | name | type | description | 57 | |------------|-------------------------------|-----------------------------------------------------------------| 58 | | `root` | [`HashDigest`](#hashdigest)`[]` | The expected root of the Merkle tree. | 59 | | `data` | Bytes | The data of the leaf (unhashed). | 60 | | `siblings` | [`HashDigest`](#hashdigest)`[]` | Sibling hash values, ordered starting from the leaf's neighbor. | 61 | 62 | A proof for a leaf in a [binary Merkle tree](#binary-merkle-tree), as per Section 2.1.1 of [Certificate Transparency (RFC-6962)](https://tools.ietf.org/html/rfc6962#section-2.1.1). 63 | 64 | In some contexts, the array of sibling hashes is also known as the proof set. Note that proof format prescribes that leaf data be in its original, unhashed state, while the proof set (array of sibling data) uses hashed data. This format precludes the proof set from itself including the leaf data from the leaf undergoing the proof; rather, proof verification explicitly requires hashing the leaf data during the calculation of the proof set root. 65 | 66 | ### Sparse Merkle Tree 67 | 68 | Sparse Merkle Trees (SMTs) are _sparse_, i.e. they contain mostly empty leaves. They can be used as key-value stores for arbitrary data, as each leaf is keyed by its index in the tree. Storage efficiency is achieved through clever use of implicit defaults, avoiding the need to store empty leaves. 69 | 70 | Additional rules are added on top of plain [binary Merkle trees](#binary-merkle-tree): 71 | 72 | 1. Default values are given to leaf nodes with empty leaves. 73 | 1. While the above rule is sufficient to pre-compute the values of intermediate nodes that are roots of empty subtrees, a further simplification is to extend this default value to all nodes that are roots of empty subtrees. The 32-byte zero, i.e. `0x0000000000000000000000000000000000000000000000000000000000000000`, is used as the default value. This rule takes precedence over the above one. 74 | 1. The number of hashing operations can be reduced to be logarithmic in the number of non-empty leaves on average, assuming a uniform distribution of non-empty leaf keys. An internal node that is the root of a subtree that contains exactly one non-empty leaf is replaced by that leaf's leaf node. 75 | 76 | Nodes contain a single field: 77 | 78 | | name | type | description | 79 | |------|---------------------------|-------------| 80 | | `v` | [`HashDigest`](#hashdigest) | Node value. | 81 | 82 | In the base case, where a sparse Merkle tree has `height = 0`, the root of a tree is defined as the [hash](#hashing) of the empty string: 83 | 84 | ```C++ 85 | node.v = 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 86 | ``` 87 | 88 | When a sparse Merkle tree has a height of 0, it can have no leaves, and, therefore, no default value children. The root is then calculated as the hash of the empty string, similar to that of an empty binary Merkle tree. 89 | 90 | For a tree with `height > 0`, the root of an empty tree is defined as the default value: 91 | 92 | ```C++ 93 | node.v = 0x0000000000000000000000000000000000000000000000000000000000000000 94 | ``` 95 | 96 | Note that this is in contrast to the base case of the sparse and binary Merkle trees, where the root is the hash of the empty string. When a sparse Merkle tree has a height greater than 0, a new tree instance is composed of default value leaves. Nodes containing only default value children have the default value as well. Applying these rules recursively percolates the default value up to the tree's root. 97 | 98 | For leaf node `node` of leaf data `d` with key `k`: 99 | 100 | ```C++ 101 | node.v = h(0x00, k, h(serialize(d))) 102 | ``` 103 | 104 | The key of leaf nodes must be prepended, since the index of a leaf node that is not at maximum depth cannot be determined without this information. Leaf values are hashed so that they do not need to be included in full in non-membership proofs. 105 | 106 | For internal node `node` with children `l` and `r`: 107 | 108 | ```C++ 109 | node.v = h(0x01, l.v, r.v) 110 | ``` 111 | 112 | #### Insertion 113 | 114 | Before insertion of the key-value pair, each key of the Sparse Merkle Tree should be hashed with `sha256` to prevent tree structure manipulations. 115 | During the proof verification, the original leaf key should be hashed similarly. Otherwise, the root will not match. 116 | 117 | #### Sparse Merkle Tree Inclusion Proofs 118 | 119 | SMTs can further be extended with _compact_ proofs. Merkle proofs are composed, among other things, of a list of sibling node values. We note that, since nodes that are roots of empty subtrees have known values (the default value), these values do not need to be provided explicitly; it is sufficient to simply identify which siblings in the Merkle branch are roots of empty subtrees, which can be done with one bit per sibling. 120 | 121 | For a Merkle branch of height `h`, an `h`-bit value is appended to the proof. The lowest bit corresponds to the sibling of the leaf node, and each higher bit corresponds to the next parent. A value of `1` indicates that the next value in the list of values provided explicitly in the proof should be used, and a value of `0` indicates that the default value should be used. 122 | 123 | A proof into an SMT is structured as: 124 | 125 | | name | type | description | 126 | |--------------------|-------------------------------|--------------------------------------------------------------------------| 127 | | `depth` | `uint16` | Depth of the leaf node. The root node is at depth `0`. Must be `<= 256`. | 128 | | `siblings` | [`HashDigest`](#hashdigest)`[]` | Sibling hash values, ordered starting from the leaf's neighbor. | 129 | | `includedSiblings` | `byte[32]` | Bitfield of explicitly included sibling hashes. | 130 | 131 | The `includedSiblings` is ordered by most-significant-byte first, with each byte ordered by most-significant-bit first. The lowest bit corresponds to the leaf node level. 132 | 133 | A specification describing a suite of test vectors and outputs of a Sparse Merkle Tree is [here](../tests/sparse-merkle-tree-tests.md). 134 | 135 | ## ECDSA Public-Key Cryptography 136 | 137 | Consensus-critical data is authenticated using [ECDSA](https://www.secg.org/sec1-v2.pdf), with the curve [secp256k1](https://en.bitcoin.it/wiki/Secp256k1). A highly-optimized library is available in [C](https://github.com/bitcoin-core/secp256k1), with wrappers in [Go](https://pkg.go.dev/github.com/ethereum/go-ethereum/crypto/secp256k1) and [Rust](https://docs.rs/crate/secp256k1). 138 | 139 | Public keys are encoded in uncompressed form, as the concatenation of the `x` and `y` values. No prefix is needed to distinguish between encoding schemes as this is the only encoding supported. 140 | 141 | Deterministic signatures ([RFC-6979](https://www.rfc-editor.org/rfc/rfc6979)) should be used when signing, but this is not enforced at the protocol level as it cannot be. 142 | 143 | Signatures are represented as the `r` and `s` (each 32 bytes), and `v` (1-bit) values of the signature. `r` and `s` take on their usual meaning (see: [SEC 1, 4.1.3 Signing Operation](https://www.secg.org/sec1-v2.pdf)), while `v` is used for recovering the public key from a signature more quickly (see: [SEC 1, 4.1.6 Public Key Recovery Operation](https://www.secg.org/sec1-v2.pdf)). Only low-`s` values in signatures are valid (i.e. `s <= secp256k1.n//2`); `s` can be replaced with `-s mod secp256k1.n` during the signing process if it is high. Given this, the first bit of `s` will always be `0`, and can be used to store the 1-bit `v` value. 144 | 145 | `v` represents the parity of the `Y` component of the point, `0` for even and `1` for odd. The `X` component of the point is assumed to always be low, since [the possibility of it being high is negligible](https://bitcoin.stackexchange.com/a/38909). 146 | 147 | Putting it all together, the encoding for signatures is: 148 | 149 | 150 | ``` 151 | | 32 bytes || 32 bytes | 152 | [256-bit r value][1-bit v value][255-bit s value] 153 | ``` 154 | 155 | This encoding scheme is derived from [EIP 2098: Compact Signature Representation](https://eips.ethereum.org/EIPS/eip-2098). 156 | 157 | ## EdDSA Public-Key Cryptography 158 | 159 | [Ed25519](https://datatracker.ietf.org/doc/html/rfc8032) is supported for use by applications built on Fuel. Edwards curve operations are performed by the [ed25519-dalek](https://github.com/dalek-cryptography/ed25519-dalek) Rust library. 160 | 161 | Public keys are encoded in compressed form as specified by the Ed25519 format [RFC-8032 5.1.5](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5). Point compression is performed by replacing the most significant bit in the final octet of the `y` coordinate with the sign bit from the `x` coordinate: 162 | 163 | ```rust 164 | let mut pk = y; 165 | pk ^= x.is_negative().unwrap_u8() << 7; 166 | ``` 167 | 168 | Public keys are required to be strong enough to prevent malleability, and are checked for weakness during signature verification. 169 | 170 | Signatures are 64 bytes, represented as the concatenation of `R` (32 bytes) and `S` (32 bytes) Where `R` and `S` are defined in [RFC-8032 5.1.6](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.6). 171 | 172 | Signatures must conform to strict [verification requirements](https://github.com/dalek-cryptography/ed25519-dalek#validation-criteria) to avoid malleability concerns. While this is not part of the original Ed25519 specification, it has become a growing concern especially in cryptocurrency applications. 173 | -------------------------------------------------------------------------------- /src/protocol/index.md: -------------------------------------------------------------------------------- 1 | # Protocol 2 | 3 | - [Transaction Validity](./tx-validity.md) 4 | - [Cryptographic Primitives](./cryptographic-primitives.md) 5 | - [Storage Slot Initialization](./storage-initialization.md) 6 | - [Block Header Format](./block-header.md) 7 | - [Relayer/Bridge](./relayer.md) 8 | -------------------------------------------------------------------------------- /src/protocol/relayer.md: -------------------------------------------------------------------------------- 1 | # Layer 1 Relayer/Bridge Protocol 2 | 3 | The Fuel relayer/bridge protocol is a set of rules that govern the interaction between the Fuel blockchain and the 4 | Layer 1 (L1) blockchain (e.g. Ethereum). 5 | 6 | The Fuel blockchain can emit messages that will be processed by the smart contract on the L1 blockchain. The smart 7 | contract on the L1 can also emit events that will be processed by the Fuel blockchain. 8 | This is used to move any data between the L1 blockchain and the Fuel blockchain. 9 | 10 | ## Fuel Message Outbox 11 | 12 | The message outbox is the set of messages sent to the L1 blockchain from the Fuel blockchain. 13 | 14 | ## Fuel Event Inbox 15 | 16 | The event inbox is the set of events received from the L1 blockchain by the Fuel blockchain. 17 | 18 | The block producer will receive a list of events from the L1 by some relayer, and then include the 19 | merkle root of the events in the block header. 20 | 21 | There are two types of events that can be received from the L1: 22 | 23 | 1. Messages 24 | 2. Transactions 25 | 26 | ### Messages 27 | 28 | An arbitrary message sent from the L1 to the Fuel blockchain. This can be used to move assets from the L1 29 | to the Fuel blockchain or send other arbitrary information to the Fuel blockchain. 30 | 31 | | name | type | description | 32 | |-------------|---------|---------------------------------------------------------------------| 33 | | `sender` | `bytes[32]` | The identity of the sender of the message on the L1 | 34 | | `recipient` | `bytes[32]` | The recipient of the message on the Fuel Blockchain | 35 | | `nonce` | `bytes[32]` | Unique identifier of the message assigned by the L1 contract | 36 | | `amount` | `uint64` | The amount of the base asset transfer | 37 | | `data` | `byte[]` | Arbitrary message data | 38 | 39 | ### Transactions 40 | 41 | These are transactions that are submitted on the L1 that must be executed on the Fuel blockchain. 42 | This "Forced Transaction Inclusion" is a security feature that allows participants of the Fuel Blockchain to access 43 | their funds in the (unlikely) event that the Fuel blockchain block production is compromised or malicious, e.g. the 44 | block producer is censoring transactions. 45 | 46 | | name | type | description | 47 | |--------------------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------| 48 | | `nonce` | `bytes[32]` | Unique identifier of the transaction assigned by the L1 contract | 49 | | `max_gas` | `uint64` | The maximum amount of gas allowed to use on Fuel Blockchain | 50 | | `serialized_transaction` | `byte[]` | The serialized transaction bytes following canonical serialization | 51 | 52 | The `serialized_transaction` can be any [transaction variant](../tx-format/transaction.md) except the `Mint` transaction, which 53 | is only ever created by the block producer. `Mint` transactions will be rejected by the Fuel blockchain if they are relayed 54 | from the L1. 55 | 56 | ### Ordering 57 | 58 | It is important that the L1 events are ordered correctly when they are relayed to the Fuel blockchain. The events will 59 | be ordered by the L1 block height and then by the index of the event within the block. 60 | 61 | The order is important because a merkle root will be generated each time events from L1 are included in a Fuel block. 62 | This merkle root can later be used to prove that an arbitrary event was included on that block without having to store 63 | every event on the block header explicitly. Just the merkle root will be on the [block header](./block-header.md). 64 | The order of the events affects the value of the merkle root. 65 | -------------------------------------------------------------------------------- /src/protocol/storage-initialization.md: -------------------------------------------------------------------------------- 1 | # JSON Format for Contract Storage Initializers 2 | 3 | Contracts can request that certain storage slots are initialized to specific values. These initialized slots are represented in JSON format as an array where each element represents a storage slot and has the following properties: 4 | 5 | - `"key"`: String, a 32-byte key for a given storage slot; 6 | - `"value"`: String, a 32-byte value that initializes the slot; 7 | 8 | For instance, the following is a JSON object that requests that the 3 storage slots with keys `0x11..11`, `0x22..22`, and `0x33..33`, are respectively initialized to the values indicated. 9 | 10 | ```json 11 | [ 12 | { 13 | "key": "0x1111111111111111111111111111111111111111111111111111111111111111", 14 | "value": "0x1010101010101010101010101010101010101010101010101010101010101010" 15 | }, 16 | { 17 | "key": "0x2222222222222222222222222222222222222222222222222222222222222222", 18 | "value": "0x2020202020202020202020202020202020202020202020202020202020202020" 19 | }, 20 | { 21 | "key": "0x3333333333333333333333333333333333333333333333333333333333333333", 22 | "value": "0x0303030303030303030303030303030303030303030303030303030303030303" 23 | }, 24 | ] 25 | ``` 26 | -------------------------------------------------------------------------------- /src/protocol/tx-validity.md: -------------------------------------------------------------------------------- 1 | # Transaction Validity 2 | 3 | - [Transaction Life Cycle](#transaction-life-cycle) 4 | - [Access Lists](#access-lists) 5 | - [VM Precondition Validity Rules](#vm-precondition-validity-rules) 6 | - [Base Sanity Checks](#base-sanity-checks) 7 | - [Spending UTXOs and Created Contracts](#spending-utxos-and-created-contracts) 8 | - [Sufficient Balance](#sufficient-balance) 9 | - [Valid Signatures](#valid-signatures) 10 | - [Predicate Verification](#predicate-verification) 11 | - [Script Execution](#script-execution) 12 | - [VM Postcondition Validity Rules](#vm-postcondition-validity-rules) 13 | - [Correct Change](#correct-change) 14 | - [State Changes](#state-changes) 15 | 16 | ## Transaction Life Cycle 17 | 18 | Once a transaction is seen, it goes through several stages of validation, in this order: 19 | 20 | 1. [Pre-checks](#vm-precondition-validity-rules) 21 | 1. [Predicate verification](#predicate-verification) 22 | 1. [Script execution](#script-execution) 23 | 1. [Post-checks](#vm-postcondition-validity-rules) 24 | 25 | ## Access Lists 26 | 27 | The validity rules below assume sequential transaction validation for side effects (i.e. state changes). However, by construction, transactions with disjoint write access lists can be validated in parallel, including with overlapping read-only access lists. Transactions with overlapping write access lists must be validated and placed in blocks in topological order. 28 | 29 | UTXOs and contracts in the read-only and write-destroy access lists must exist (i.e. have been created previously) in order for a transaction to be valid. In other words, for a unique state element ID, the write-create must precede the write-destroy. 30 | 31 | Read-only access list: 32 | 33 | Write-destroy access list: 34 | 35 | - For each [input `InputType.Coin`](../tx-format/input.md#inputcoin) 36 | - The [UTXO ID](../identifiers/utxo-id.md) `(txId, outputIndex)` 37 | - For each [input `InputType.Contract`](../tx-format/input.md#inputcontract) 38 | - The [UTXO ID](../identifiers/utxo-id.md) `(txId, outputIndex)` 39 | - For each [input `InputType.Message`](../tx-format/input.md#inputmessage) 40 | - The [message ID](../identifiers/utxo-id.md#message-id) `messageID` 41 | 42 | Write-create access list: 43 | 44 | - For each [output `OutputType.ContractCreated`](../tx-format/output.md#outputcontractcreated) 45 | - The contract ID `contractID` 46 | - For each output 47 | - The [created UTXO ID](../identifiers/utxo-id.md) 48 | 49 | Note that block proposers use the contract ID `contractID` for inputs and outputs of type [`InputType.Contract`](../tx-format/input.md#inputcontract) and [`OutputType.Contract`](../tx-format/output.md#outputcontract) rather than the pair of `txId` and `outputIndex`. 50 | 51 | ## VM Precondition Validity Rules 52 | 53 | This section defines _VM precondition validity rules_ for transactions: the bare minimum required to accept an unconfirmed transaction into a mempool, and preconditions that the VM assumes to hold prior to execution. Chains of unconfirmed transactions are omitted. 54 | 55 | For a transaction `tx`, UTXO set `state`, contract set `contracts`, and message set `messages`, the following checks must pass. 56 | 57 | > **Note:** [`InputMessages`](../tx-format/input.md#inputmessage) where `input.dataLength > 0` are not dropped from the `messages` message set until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit. 58 | 59 | ### Base Sanity Checks 60 | 61 | Base sanity checks are defined in the [transaction format](../tx-format/index.md). 62 | 63 | ### Spending UTXOs and Created Contracts 64 | 65 | ```py 66 | for input in tx.inputs: 67 | if input.type == InputType.Contract: 68 | if not input.contractID in contracts: 69 | return False 70 | elif input.type == InputType.Message: 71 | if not input.nonce in messages: 72 | return False 73 | else: 74 | if not (input.txId, input.outputIndex) in state: 75 | return False 76 | return True 77 | ``` 78 | 79 | If this check passes, the UTXO ID `(txId, outputIndex)` fields of each contract input is set to the UTXO ID of the respective contract. The `txPointer` of each input is also set to the TX pointer of the UTXO with ID `utxoID`. 80 | 81 | ### Sufficient Balance 82 | 83 | For each asset ID `assetId` in the input and output set: 84 | 85 | ```py 86 | def gas_to_fee(gas, gasPrice) -> int: 87 | """ 88 | Converts gas units into a fee amount 89 | """ 90 | return ceil(gas * gasPrice / GAS_PRICE_FACTOR) 91 | 92 | 93 | def sum_data_messages(tx, assetId) -> int: 94 | """ 95 | Returns the total balance available from messages containing data 96 | """ 97 | total: int = 0 98 | if assetId == 0: 99 | for input in tx.inputs: 100 | if input.type == InputType.Message and input.dataLength > 0: 101 | total += input.amount 102 | return total 103 | 104 | 105 | def sum_inputs(tx, assetId) -> int: 106 | total: int = 0 107 | for input in tx.inputs: 108 | if input.type == InputType.Coin and input.assetId == assetId: 109 | total += input.amount 110 | elif input.type == InputType.Message and assetId == 0 and input.dataLength == 0: 111 | total += input.amount 112 | return total 113 | 114 | 115 | def transaction_size_gas_fees(tx) -> int: 116 | """ 117 | Computes the intrinsic gas cost of a transaction based on size in bytes 118 | """ 119 | return size(tx) * GAS_PER_BYTE 120 | 121 | 122 | def minted(tx, assetId) -> int: 123 | """ 124 | Returns any minted amounts by the transaction 125 | """ 126 | if tx.type != TransactionType.Mint or assetId != tx.mintAssetId: 127 | return 0 128 | return tx.mint_amount 129 | 130 | 131 | def sum_outputs(tx, assetId) -> int: 132 | total: int = 0 133 | for output in tx.outputs: 134 | if output.type == OutputType.Coin and output.assetId == assetId: 135 | total += output.amount 136 | return total 137 | 138 | 139 | def input_gas_fees(tx) -> int: 140 | """ 141 | Computes the intrinsic gas cost of verifying input utxos 142 | """ 143 | total: int = 0 144 | witnessIndices = set() 145 | for input in tx.inputs: 146 | if input.type == InputType.Coin or input.type == InputType.Message: 147 | # add fees allocated for predicate execution 148 | if input.predicateLength == 0: 149 | # notate witness index if input is signed 150 | witnessIndices.add(input.witnessIndex) 151 | else: 152 | # add intrinsic gas cost of predicate merkleization based on number of predicate bytes 153 | total += contract_code_root_gas_fee(input.predicateLength) 154 | total += input.predicateGasUsed 155 | # add intrinsic cost of vm initialization 156 | total += vm_initialization_gas_fee() 157 | # add intrinsic cost of verifying witness signatures 158 | total += len(witnessIndices) * eck1_recover_gas_fee() 159 | return total 160 | 161 | 162 | def metadata_gas_fees(tx) -> int: 163 | """ 164 | Computes the intrinsic gas cost of processing transaction outputs 165 | 166 | The `contract_code_root_gas_fee`, `sha256_gas_fee`, and `contract_state_root_gas_fee` 167 | are based on the benchmarked gas costs of these operations. 168 | 169 | Consensus parameters contain definitions of gas costs for all operations and opcodes in the network. 170 | """ 171 | total: int = 0 172 | if tx.type == TransactionType.Create: 173 | for output in tx.outputs: 174 | if output.type == OutputType.OutputContractCreated: 175 | # add intrinsic cost of calculating the code root based on the size of the contract bytecode 176 | total += contract_code_root_gas_fee(tx.witnesses[tx.bytecodeWitnessIndex].dataLength) 177 | # add intrinsic cost of calculating the state root based on the number of sotrage slots 178 | total += contract_state_root_gas_fee(tx.storageSlotCount) 179 | # add intrinsic cost of calculating the contract id 180 | # size = 4 byte seed + 32 byte salt + 32 byte code root + 32 byte state root 181 | total += sha256_gas_fee(100) 182 | elif tx.type == TransactionType.Upgrade: 183 | if tx.upgradePurpose.type == UpgradePurposeType.ConsensusParameters: 184 | # add intrinsic cost of calculating the consensus parameters hash 185 | total += sha256_gas_fee(size(tx.witnesses[tx.upgradePurpose.witnessIndex].data)) 186 | elif tx.type == TransactionType.Upload: 187 | # add intrinsic cost of calculating the root based on the number of bytecode subsections 188 | total += contract_state_root_gas_fee(tx.subsectionsNumber) 189 | # add intrinsic cost of hashing the subsection for verification of the connection with Binary Merkle tree root 190 | total += sha256_gas_fee(size(tx.witnesses[tx.witnessIndex])) 191 | 192 | if tx.type != TransactionType.Mint: 193 | # add intrinsic cost of calculating the transaction id 194 | total += sha256_gas_fee(size(tx)) 195 | return total 196 | 197 | 198 | def intrinsic_gas_fees(tx) -> int: 199 | """ 200 | Computes intrinsic costs for a transaction 201 | """ 202 | fees: int = 0 203 | # add the cost of initializing a vm for the script 204 | if tx.type == TransactionType.Create or tx.type == TransactionType.Script: 205 | fees += vm_initialization_gas_fee() 206 | fees += metadata_gas_fees(tx) 207 | fees += intrinsic_input_gas_fees(tx) 208 | return fees 209 | 210 | 211 | def min_gas(tx) -> int: 212 | """ 213 | Comutes the minimum amount of gas required for a transaction to begin processing. 214 | """ 215 | gas = transaction_size_gas_fees(tx) + intrinsic_gas_fees(tx) 216 | if tx.type == TransactionType.Upload 217 | # charge additionally for storing bytecode on chain 218 | gas += transaction_size_gas_fees(size(tx.witnesses[tx.witnessIndex])) 219 | 220 | return gas 221 | 222 | 223 | def max_gas(tx) -> int: 224 | """ 225 | Computes the amount of gas required to process a transaction. 226 | """ 227 | gas = min_gas(tx) 228 | gas = gas + (tx.witnessBytesLimit - tx.witnessBytes) * GAS_PER_BYTE 229 | if tx.type == TransactionType.Script: 230 | gas += tx.gasLimit 231 | return gas 232 | 233 | 234 | def maxFee(tx, assetId, gasPrice) -> int: 235 | """ 236 | Computes the maximum potential amount of fees that may need to be charged to process a transaction. 237 | """ 238 | maxGas = max_gas(tx) 239 | feeBalance = gas_to_fee(maxGas, gasPrice) 240 | # Only base asset can be used to pay for gas 241 | if assetId == 0: 242 | return feeBalance 243 | else: 244 | return 0 245 | 246 | 247 | def available_balance(tx, assetId) -> int: 248 | """ 249 | Make the data message balance available to the script 250 | """ 251 | availableBalance = sum_inputs(tx, assetId) + sum_data_messages(tx, assetId) + minted(tx, assetId) 252 | return availableBalance 253 | 254 | 255 | def unavailable_balance(tx, assetId) -> int: 256 | sentBalance = sum_outputs(tx, assetId) 257 | # Total fee balance 258 | feeBalance = tx.policies.max_fee 259 | # Only base asset can be used to pay for gas 260 | if assetId == 0: 261 | return sentBalance + feeBalance 262 | return sentBalance 263 | 264 | 265 | # The sum_data_messages total is not included in the unavailable_balance since it is spendable as long as there 266 | # is enough base asset amount to cover gas costs without using data messages. Messages containing data can't 267 | # cover gas costs since they are retryable. 268 | return available_balance(tx, assetId) >= (unavailable_balance(tx, assetId) + sum_data_messages(tx, assetId)) 269 | ``` 270 | 271 | ### Valid Signatures 272 | 273 | ```py 274 | def address_from(pubkey: bytes) -> bytes: 275 | return sha256(pubkey)[0:32] 276 | 277 | for input in tx.inputs: 278 | if (input.type == InputType.Coin or input.type == InputType.Message) and input.predicateLength == 0: 279 | # ECDSA signatures must be 64 bytes 280 | if tx.witnesses[input.witnessIndex].dataLength != 64: 281 | return False 282 | # Signature must be from owner 283 | if address_from(ecrecover_k1(txhash(), tx.witnesses[input.witnessIndex].data)) != input.owner: 284 | return False 285 | return True 286 | ``` 287 | 288 | Signatures and signature verification are specified [here](./cryptographic-primitives.md#public-key-cryptography). 289 | 290 | The transaction hash is computed as defined [here](../identifiers/transaction-id.md). 291 | 292 | ## Predicate Verification 293 | 294 | For each input of type `InputType.Coin` or `InputType.Message`, and `predicateLength > 0`, [verify its predicate](../fuel-vm/index.md#predicate-verification). 295 | 296 | ## Script Execution 297 | 298 | Given transaction `tx`, the following checks must pass: 299 | 300 | If `tx.scriptLength == 0`, there is no script and the transaction defines a simple balance transfer, so no further checks are required. 301 | 302 | If `tx.scriptLength > 0`, the script must be executed. For each asset ID `assetId` in the input set, the free balance available to be moved around by the script and called contracts is `freeBalance[assetId]`. The initial message balance available to be moved around by the script and called contracts is `messageBalance`: 303 | 304 | ```py 305 | freeBalance[assetId] = available_balance(tx, assetId) - unavailable_balance(tx, assetId) 306 | messageBalance = sum_data_messages(tx, 0) 307 | ``` 308 | 309 | Once the free balances are computed, the [script is executed](../fuel-vm/index.md#script-execution). After execution, the following is extracted: 310 | 311 | 1. The transaction in-memory on VM termination is used as the final transaction which is included in the block. 312 | 1. The unspent free balance `unspentBalance` for each asset ID. 313 | 1. The unspent gas `unspentGas` from the `$ggas` register. 314 | 315 | `size(tx)` encompasses the entire transaction serialized according to the transaction format, including witness data. 316 | This ensures every byte of block space either on Fuel or corresponding DA layer can be accounted for. 317 | 318 | If the transaction as included in a block does not match this final transaction, the block is invalid. 319 | 320 | ### Fees 321 | 322 | The cost of a transaction can be described by: 323 | 324 | ```py 325 | def cost(tx, gasPrice) -> int: 326 | return gas_to_fee(min_gas(tx) + tx.gasLimit - unspentGas, gasPrice) 327 | ``` 328 | 329 | where: 330 | 331 | - `min_gas(tx)` is the minimum cost of the transaction in gas, including intrinsic gas fees incurred from: 332 | - The number of bytes comprising the transaction 333 | - Processing inputs, including predicates 334 | - Processing outputs 335 | - VM initialization 336 | - `unspentGas` is the amount gas left over after intrinsic fees and execution of the transaction, extracted from the `$ggas` register. Converting unspent gas to a fee describes how much "change" is left over from the user's payment; the block producer collects this unspent gas as reward. 337 | - `gas_to_fee` is a function that converts gas to a concrete fee based on a given gas price. 338 | 339 | Fees incurred by transaction processing outside the context of execution are collectively referred to as intrinsic fees. Intrinsic fees include the cost of storing the transaction, calculated on a per-byte basis, the cost of processing inputs and outputs, including predicates and signature verification, and initialization of the VM prior to any predicate or script execution. Because intrinsic fees are independent of execution, they can be determined _a priori_ and represent the bare minimum cost of the transaction. 340 | 341 | A naturally occurring result of a variable gas limit is the concept of minimum and maximum fees. The minimum fee is, thus, the exact fee required to pay the fee balance, while the maximum fee is the minimum fee plus the gas limit: 342 | 343 | ```py 344 | min_gas = min_gas(tx) 345 | max_gas = min_gas + (tx.witnessBytesLimit - tx.witnessBytes) * GAS_PER_BYTE + tx.gasLimit 346 | min_fee = gas_to_fee(min_gas, gasPrice) 347 | max_fee = gas_to_fee(max_gas, gasPrice) 348 | ``` 349 | 350 | The cost of the transaction `cost(tx)` must lie within the range defined by [`min_fee`, `max_fee`]. `min_gas` is defined as the sum of all intrinsic costs of the transaction known prior to execution. The definition of `max_gas` illustrates that the delta between minimum gas and maximum gas is the sum of: 351 | 352 | - The remaining allocation of witness bytes, converted to gas 353 | - The user-defined `tx.gasLimit` 354 | 355 | Note that `gasLimit` applies to transactions of type `Script`. `gasLimit` is not applicable for transactions of type `Create` and is defined to equal `0` in the above formula. 356 | 357 | A transaction cost `cost(tx)`, in gas, greater than `max_gas` is invalid and must be rejected; this signifies that the user must provide a higher gas limit for the given transaction. `min_fee` is the minimum reward the producer is guaranteed to collect, and `max_fee` is the maximum reward the producer is potentially eligible to collect. In practice, the user is always charged intrinsic fees; thus, `unspentGas` is the remainder of `max_gas` after intrinsic fees and the variable cost of execution. Calculating a conversion from `unspentGas` to an unspent fee describes the reward the producer will collect in addition to `min_fee`. 358 | 359 | ## VM Postcondition Validity Rules 360 | 361 | This section defines _VM postcondition validity rules_ for transactions: the requirements for a transaction to be valid after it has been executed. 362 | 363 | Given transaction `tx`, state `state`, and contract set `contracts`, the following checks must pass. 364 | 365 | ### Correct Change 366 | 367 | If change outputs are present, they must have: 368 | 369 | - if the transaction does not revert; 370 | - if the asset ID is `0`; an `amount` of `unspentBalance + floor((unspentGas * gasPrice) / GAS_PRICE_FACTOR)` 371 | - otherwise; an `amount` of the unspent free balance for that asset ID after VM execution is complete 372 | - if the transaction reverts; 373 | - if the asset ID is `0`; an `amount` of the initial free balance plus `(unspentGas * gasPrice) - messageBalance` 374 | - otherwise; an `amount` of the initial free balance for that asset ID. 375 | 376 | ### State Changes 377 | 378 | Transaction processing is completed by removing spent UTXOs from the state and adding created UTXOs to the state. 379 | 380 | ### Coinbase Transaction 381 | 382 | The coinbase transaction is a mechanism for block creators to collect transaction fees. 383 | 384 | In order for a coinbase transaction to be valid: 385 | 386 | 1. It must be a [Mint](../tx-format/transaction.md#TransactionMint) transaction. 387 | 1. The coinbase transaction must be the last transaction within a block, even if there are no other transactions in the block and the fee is zero. 388 | 1. The `mintAmount` doesn't exceed the total amount of fees processed from all other transactions within the same block. 389 | 1. The `mintAssetId` matches the `assetId` that fees are paid in (`assetId == 0`). 390 | 391 | The minted amount of the coinbase transaction intrinsically increases the balance corresponding to the `inputContract`. 392 | This means the balance of `mintAssetId` is directly increased by `mintAmount` on the input contract, 393 | without requiring any VM execution. Compared to coin outputs, intrinsically increasing a contract balance to collect 394 | coinbase amounts prevents the accumulation of dust during low-usage periods. 395 | -------------------------------------------------------------------------------- /src/tests/index.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | Test suites for verifying the correctness of a Fuel implementation. 4 | 5 | - [Sparse Merkle Tree Tests](./sparse-merkle-tree-tests.md) 6 | -------------------------------------------------------------------------------- /src/tx-format/consensus_parameters.md: -------------------------------------------------------------------------------- 1 | # Consensus Parameters 2 | 3 | | name | type | description | 4 | |-----------------------------|-----------|----------------------------------------------------------------| 5 | | `GAS_PER_BYTE` | `uint64` | Gas charged per byte of the transaction. | 6 | | `GAS_PRICE_FACTOR` | `uint64` | Unit factor for gas price. | 7 | | `MAX_GAS_PER_TX` | `uint64` | Maximum gas per transaction. | 8 | | `MAX_INPUTS` | `uint64` | Maximum number of inputs. | 9 | | `MAX_OUTPUTS` | `uint64` | Maximum number of outputs. | 10 | | `MAX_PREDICATE_LENGTH` | `uint64` | Maximum length of predicate, in instructions. | 11 | | `MAX_GAS_PER_PREDICATE` | `uint64` | Maximum gas per predicate. | 12 | | `MAX_PREDICATE_DATA_LENGTH` | `uint64` | Maximum length of predicate data, in bytes. | 13 | | `MAX_SCRIPT_LENGTH` | `uint64` | Maximum length of script, in instructions. | 14 | | `MAX_SCRIPT_DATA_LENGTH` | `uint64` | Maximum length of script data, in bytes. | 15 | | `MAX_MESSAGE_DATA_LENGTH` | `uint64` | Maximum length of message data, in bytes. | 16 | | `MAX_STORAGE_SLOTS` | `uint64` | Maximum number of initial storage slots. | 17 | | `MAX_TRANSACTION_SIZE` | `uint64` | Maximum size of a transaction, in bytes. | 18 | | `MAX_WITNESSES` | `uint64` | Maximum number of witnesses. | 19 | | `MAX_BYTECODE_SUBSECTIONS` | `uint64` | Maximum number of bytecode subsections. | 20 | | `CHAIN_ID` | `uint64` | A unique per-chain identifier. | 21 | | `BASE_ASSET_ID` | `bytes32` | The base asset of the chain. | 22 | | `PRIVILEGED_ADDRESS` | `bytes32` | The privileged address of the network who can perform upgrade. | 23 | -------------------------------------------------------------------------------- /src/tx-format/index.md: -------------------------------------------------------------------------------- 1 | # Transaction Format 2 | 3 | The Fuel Transaction Format. 4 | 5 | - [Consensus Parameters](./consensus_parameters.md) 6 | - [Transaction](./transaction.md) 7 | - [`TransactionScript`](./transaction.md#transactionscript) 8 | - [`TransactionCreate`](./transaction.md#transactioncreate) 9 | - [`TransactionMint`](./transaction.md#transactionmint) 10 | - [`TransactionUpgrade`](./transaction.md#transactionupgrade) 11 | - [`TransactionUpload`](./transaction.md#transactionupload) 12 | - [`TransactionBlob`](./transaction.md#transactionblob) 13 | - [Input](./input.md) 14 | - [`InputCoin`](./input.md#inputcoin) 15 | - [`InputContract`](./input.md#inputcontract) 16 | - [`InputMessage`](./input.md#inputmessage) 17 | - [Output](./output.md) 18 | - [`OutputCoin`](./output.md#outputcoin) 19 | - [`OutputContract`](./output.md#outputcontract) 20 | - [`OutputChange`](./output.md#outputchange) 21 | - [`OutputVariable`](./output.md#outputvariable) 22 | - [`OutputContractCreated`](./output.md#outputcontractcreated) 23 | - [`Witness`](./witness.md) 24 | - [`Policy`](./policy.md) 25 | - [`TXPointer`](./tx-pointer.md) 26 | -------------------------------------------------------------------------------- /src/tx-format/input.md: -------------------------------------------------------------------------------- 1 | # Input 2 | 3 | ```c++ 4 | enum InputType : uint8 { 5 | Coin = 0, 6 | Contract = 1, 7 | Message = 2, 8 | } 9 | ``` 10 | 11 | | name | type | description | 12 | |--------|---------------------------------------------------------------------------------------------------|----------------| 13 | | `type` | [`InputType`](#input) | Type of input. | 14 | | `data` | One of [`InputCoin`](#inputcoin), [`InputContract`](#inputcontract), or [`InputMessage`](#inputmessage) | Input data. | 15 | 16 | Transaction is invalid if: 17 | 18 | - `type > InputType.Message` 19 | 20 | ## `InputCoin` 21 | 22 | | name | type | description | 23 | |-----------------------|------------------------------|------------------------------------------------------------------------| 24 | | `txID` | `byte[32]` | Hash of transaction. | 25 | | `outputIndex` | `uint16` | Index of transaction output. | 26 | | `owner` | `byte[32]` | Owning address or predicate root. | 27 | | `amount` | `uint64` | Amount of coins. | 28 | | `asset_id` | `byte[32]` | Asset ID of the coins. | 29 | | `txPointer` | [`TXPointer`](./tx-pointer.md) | Points to the TX whose output is being spent. | 30 | | `witnessIndex` | `uint16` | Index of witness that authorizes spending the coin. | 31 | | `predicateGasUsed` | `uint64` | Gas used by predicate. | 32 | | `predicateLength` | `uint64` | Length of predicate, in instructions. | 33 | | `predicateDataLength` | `uint64` | Length of predicate input data, in bytes. | 34 | | `predicate` | `byte[]` | Predicate bytecode. | 35 | | `predicateData` | `byte[]` | Predicate input data (parameters). | 36 | 37 | Given helper `len()` that returns the number of bytes of a field. 38 | 39 | Transaction is invalid if: 40 | 41 | - `witnessIndex >= tx.witnessesCount` 42 | - `predicateLength > MAX_PREDICATE_LENGTH` 43 | - `predicateDataLength > MAX_PREDICATE_DATA_LENGTH` 44 | - If `predicateLength > 0`; the computed predicate root (see below) is not equal `owner` 45 | - `predicateLength * 4 != len(predicate)` 46 | - `predicateDataLength != len(predicateData)` 47 | - `predicateGasUsed > MAX_GAS_PER_PREDICATE` 48 | 49 | > **Note:** when signing a transaction, `txPointer` and `predicateGasUsed` are set to zero. 50 | > 51 | > **Note:** when verifying and estimating a predicate or executing a script, `txPointer` and `predicateGasUsed` are initialized to zero. 52 | 53 | The predicate root is computed [here](../identifiers/predicate-id.md). 54 | 55 | ## `InputContract` 56 | 57 | | name | type | description | 58 | |---------------|------------------------------|-------------------------------------------------------------------------| 59 | | `txID` | `byte[32]` | Hash of transaction. | 60 | | `outputIndex` | `uint16` | Index of transaction output. | 61 | | `balanceRoot` | `byte[32]` | Root of amount of coins owned by contract before transaction execution. | 62 | | `stateRoot` | `byte[32]` | State root of contract before transaction execution. | 63 | | `txPointer` | [`TXPointer`](./tx-pointer.md) | Points to the TX whose output is being spent. | 64 | | `contractID` | `byte[32]` | Contract ID. | 65 | 66 | Transaction is invalid if: 67 | 68 | - there is not exactly one output of type `OutputType.Contract` with `inputIndex` equal to this input's index 69 | 70 | > **Note:** when signing a transaction, `txID`, `outputIndex`, `balanceRoot`, `stateRoot`, and `txPointer` are set to zero. 71 | > 72 | > **Note:** when verifying a predicate or executing a script, `txID`, `outputIndex`, `balanceRoot`, `stateRoot`, and `txPointer` are initialized to zero. 73 | 74 | ## `InputMessage` 75 | 76 | | name | type | description | 77 | |-----------------------|------------|---------------------------------------------------------| 78 | | `sender` | `byte[32]` | The address of the message sender. | 79 | | `recipient` | `byte[32]` | The address or predicate root of the message recipient. | 80 | | `amount` | `uint64` | Amount of base asset coins sent with message. | 81 | | `nonce` | `byte[32]` | The message nonce. | 82 | | `witnessIndex` | `uint16` | Index of witness that authorizes spending the coin. | 83 | | `predicateGasUsed` | `uint64` | Gas used by predicate execution. | 84 | | `dataLength` | `uint64` | Length of message data, in bytes. | 85 | | `predicateLength` | `uint64` | Length of predicate, in instructions. | 86 | | `predicateDataLength` | `uint64` | Length of predicate input data, in bytes. | 87 | | `data` | `byte[]` | The message data. | 88 | | `predicate` | `byte[]` | Predicate bytecode. | 89 | | `predicateData` | `byte[]` | Predicate input data (parameters). | 90 | 91 | Given helper `len()` that returns the number of bytes of a field. 92 | 93 | Transaction is invalid if: 94 | 95 | - `witnessIndex >= tx.witnessesCount` 96 | - `dataLength > MAX_MESSAGE_DATA_LENGTH` 97 | - `predicateLength > MAX_PREDICATE_LENGTH` 98 | - `predicateDataLength > MAX_PREDICATE_DATA_LENGTH` 99 | - If `predicateLength > 0`; the computed predicate root (see below) is not equal `recipient` 100 | - `dataLength != len(data)` 101 | - `predicateLength * 4 != len(predicate)` 102 | - `predicateDataLength != len(predicateData)` 103 | - `predicateGasUsed > MAX_GAS_PER_PREDICATE` 104 | 105 | The predicate root is computed [here](../identifiers/predicate-id.md). 106 | 107 | > **Note:** `InputMessages` with data length greater than zero are not considered spent until they are included in a transaction of type `TransactionType.Script` with a `ScriptResult` receipt where `result` is equal to `0` indicating a successful script exit 108 | > 109 | > **Note:** when signing a transaction, `predicateGasUsed` is set to zero. 110 | > 111 | > **Note:** when verifying and estimating a predicate, `predicateGasUsed` is initialized to zero. 112 | -------------------------------------------------------------------------------- /src/tx-format/output.md: -------------------------------------------------------------------------------- 1 | # Output 2 | 3 | ```c++ 4 | enum OutputType : uint8 { 5 | Coin = 0, 6 | Contract = 1, 7 | Change = 2, 8 | Variable = 3, 9 | ContractCreated = 4, 10 | } 11 | ``` 12 | 13 | | name | type | description | 14 | |--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------| 15 | | `type` | [`OutputType`](#output) | Type of output. | 16 | | `data` | One of [`OutputCoin`](#outputcoin), [`OutputContract`](#outputcontract), [`OutputChange`](#outputchange), [`OutputVariable`](#outputvariable), or [`OutputContractCreated`](#outputcontractcreated). | Output data. | 17 | 18 | Transaction is invalid if: 19 | 20 | - `type > OutputType.ContractCreated` 21 | 22 | ## `OutputCoin` 23 | 24 | | name | type | description | 25 | |------------|------------|--------------------------------------| 26 | | `to` | `byte[32]` | Receiving address or predicate root. | 27 | | `amount` | `uint64` | Amount of coins to send. | 28 | | `asset_id` | `byte[32]` | Asset ID of coins. | 29 | 30 | ## `OutputContract` 31 | 32 | | name | type | description | 33 | |---------------|------------|------------------------------------------------------------------------| 34 | | `inputIndex` | `uint16` | Index of input contract. | 35 | | `balanceRoot` | `byte[32]` | Root of amount of coins owned by contract after transaction execution. | 36 | | `stateRoot` | `byte[32]` | State root of contract after transaction execution. | 37 | 38 | Transaction is invalid if: 39 | 40 | - `inputIndex >= tx.inputsCount` 41 | - `tx.inputs[inputIndex].type != InputType.Contract` 42 | 43 | > **Note:** when signing a transaction, `balanceRoot` and `stateRoot` are set to zero. 44 | > 45 | > **Note:** when verifying a predicate or executing a script, `balanceRoot` and `stateRoot` are initialized to zero. 46 | 47 | The balance root `balanceRoot` is the root of the [SMT](../protocol/cryptographic-primitives.md#sparse-merkle-tree) of balance leaves. Each balance is a `uint64`, keyed by asset ID (a `byte[32]`). 48 | 49 | The state root `stateRoot` is the root of the [SMT](../protocol/cryptographic-primitives.md#sparse-merkle-tree) of storage slots. Each storage slot is a `byte[32]`, keyed by a `byte[32]`. 50 | 51 | ## `OutputChange` 52 | 53 | | name | type | description | 54 | |------------|------------|--------------------------------------| 55 | | `to` | `byte[32]` | Receiving address or predicate root. | 56 | | `amount` | `uint64` | Amount of coins to send. | 57 | | `asset_id` | `byte[32]` | Asset ID of coins. | 58 | 59 | Transaction is invalid if: 60 | 61 | - any other output has type `OutputType.OutputChange` and asset ID `asset_id` (i.e. only one change output per asset ID is allowed) 62 | 63 | > **Note:** when signing a transaction, `amount` is set to zero. 64 | > 65 | > **Note:** when verifying a predicate or executing a script, `amount` is initialized to zero. 66 | 67 | This output type indicates that the output's amount may vary based on transaction execution, but is otherwise identical to a [Coin](#outputcoin) output. An `amount` of zero after transaction execution indicates that the output is unspendable and can be pruned from the UTXO set. 68 | 69 | ## `OutputVariable` 70 | 71 | | name | type | description | 72 | |------------|------------|--------------------------------------| 73 | | `to` | `byte[32]` | Receiving address or predicate root. | 74 | | `amount` | `uint64` | Amount of coins to send. | 75 | | `asset_id` | `byte[32]` | Asset ID of coins. | 76 | 77 | > **Note:** when signing a transaction, `to`, `amount`, and `asset_id` are set to zero. 78 | > 79 | > **Note:** when verifying a predicate or executing a script, `to`, `amount`, and `asset_id` are initialized to zero. 80 | 81 | This output type indicates that the output's amount and owner may vary based on transaction execution, but is otherwise identical to a [Coin](#outputcoin) output. An `amount` of zero after transaction execution indicates that the output is unspendable and can be pruned from the UTXO set. 82 | 83 | ## `OutputContractCreated` 84 | 85 | | name | type | description | 86 | |--------------|------------|---------------------------------| 87 | | `contractID` | `byte[32]` | Contract ID. | 88 | | `stateRoot` | `byte[32]` | Initial state root of contract. | 89 | -------------------------------------------------------------------------------- /src/tx-format/policy.md: -------------------------------------------------------------------------------- 1 | # Policy 2 | 3 | ```c++ 4 | // index using powers of 2 for efficient bitmasking 5 | enum PolicyType : uint32 { 6 | Tip = 1, 7 | WitnessLimit = 2, 8 | Maturity = 4, 9 | MaxFee = 8, 10 | Expiration = 16, 11 | } 12 | ``` 13 | 14 | | name | type | description | 15 | |--------|-----------------------------------------------------------------------------------|--------------| 16 | | `data` | One of [`Tip`](#tip), [`WitnessLimit`](#witnesslimit), [`Maturity`](#maturity) or [`Expiration`](#expiration) | Policy data. | 17 | 18 | ## `Tip` 19 | 20 | | name | type | description | 21 | |------------|----------|-----------------------------------------------------------------------------------------------| 22 | | `tip` | `uint64` | Additional, optional fee in `BASE_ASSET` to incentivize block producer to include transaction | 23 | 24 | ## `WitnessLimit` 25 | 26 | | name | type | description | 27 | |----------------|----------|----------------------------------------------------------------| 28 | | `witnessLimit` | `uint64` | The maximum amount of witness data allowed for the transaction | 29 | 30 | Given helper `len()` that returns the number of bytes of a field. 31 | 32 | Transaction is invalid if: 33 | 34 | - `len(tx.witnesses) > witnessLimit` 35 | 36 | ## `Maturity` 37 | 38 | | name | type | description | 39 | |------------|----------|------------------------------------------| 40 | | `maturity` | `uint32` | Block until which the transaction cannot be included. | 41 | 42 | Transaction is invalid if: 43 | 44 | - `blockheight() < maturity` 45 | 46 | ## `Expiration` 47 | 48 | | name | type | description | 49 | |--------------|----------|------------------------------------------| 50 | | `expiration` | `uint32` | Block after which the transaction cannot be included. | 51 | 52 | Transaction is invalid if: 53 | 54 | - `blockheight() > expiration` 55 | 56 | ## `MaxFee` 57 | 58 | | name | type | description | 59 | |-----------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| 60 | | `max_fee` | `uint64` | Required policy to specify the maximum fee payable by this transaction using `BASE_ASSET`. This is used to check transactions before the actual `gas_price` is known. | 61 | 62 | Transaction is invalid if: 63 | 64 | - `max_fee > sum_inputs(tx, BASE_ASSET_ID) - sum_outputs(tx, BASE_ASSET_ID)` 65 | - `max_fee < max_fee(tx, BASE_ASSET_ID, gas_price)` 66 | -------------------------------------------------------------------------------- /src/tx-format/transaction.md: -------------------------------------------------------------------------------- 1 | # Transaction 2 | 3 | ```c++ 4 | enum TransactionType : uint8 { 5 | Script = 0, 6 | Create = 1, 7 | Mint = 2, 8 | Upgrade = 3, 9 | Upload = 4, 10 | Blob = 5, 11 | } 12 | ``` 13 | 14 | | name | type | description | 15 | |--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------| 16 | | `type` | [`TransactionType`](#transaction) | Transaction type. | 17 | | `data` | One of [`TransactionScript`](#transactionscript), [`TransactionCreate`](#transactioncreate), [`TransactionMint`](#transactionmint), [`TransactionUpgrade`](#transactionupgrade), or [`TransactionUpload`](#transactionupload) | Transaction data. | 18 | 19 | Given helper `max_gas()` returns the maximum gas that the transaction can use. 20 | Given helper `count_ones()` that returns the number of ones in the binary representation of a field. 21 | Given helper `count_variants()` that returns the number of variants in an enum. 22 | Given helper `sum_variants()` that sums all variants of an enum. 23 | 24 | Transaction is invalid if: 25 | 26 | - `type` is not valid `TransactionType` value 27 | - `inputsCount > MAX_INPUTS` 28 | - `outputsCount > MAX_OUTPUTS` 29 | - `witnessesCount > MAX_WITNESSES` 30 | - `size > MAX_TRANSACTION_SIZE`. The size of a transaction is calculated as the sum of the sizes of its static and dynamic parts, as determined by canonical serialization. 31 | - No inputs are of type `InputType.Coin` or `InputType.Message` with `input.dataLength` == 0 32 | - More than one output is of type `OutputType.Change` for any asset ID in the input set 33 | - More than one output is of type `OutputType.Change` with identical `asset_id` fields. 34 | - Any output is of type `OutputType.Change` for any asset ID not in the input set 35 | - More than one input of type `InputType.Coin` for any [Coin ID](../identifiers/utxo-id.md#coin-id) in the input set 36 | - More than one input of type `InputType.Contract` for any [Contract ID](../identifiers/utxo-id.md#contract-id) in the input set 37 | - More than one input of type `InputType.Message` for any [Message ID](../identifiers/utxo-id.md#message-id) in the input set 38 | - if `type != TransactionType.Mint` 39 | - `max_gas(tx) > MAX_GAS_PER_TX` 40 | - No policy of type `PolicyType.MaxFee` is set 41 | - `count_ones(policyTypes) > count_variants(PolicyType)` 42 | - `policyTypes > sum_variants(PolicyType)` 43 | - `len(policies) > count_ones(policyTypes)` 44 | 45 | When serializing a transaction, fields are serialized as follows (with inner structs serialized recursively): 46 | 47 | 1. `uint8`, `uint16`, `uint32`, `uint64`: big-endian right-aligned to 8 bytes. 48 | 1. `byte[32]`: as-is. 49 | 1. `byte[]`: as-is, with padding zeroes aligned to 8 bytes. 50 | 51 | When deserializing a transaction, the reverse is done. If there are insufficient bytes or too many bytes, the transaction is invalid. 52 | 53 | ## `TransactionScript` 54 | 55 | ```c++ 56 | enum ReceiptType : uint8 { 57 | Call = 0, 58 | Return = 1, 59 | ReturnData = 2, 60 | Panic = 3, 61 | Revert = 4, 62 | Log = 5, 63 | LogData = 6, 64 | Transfer = 7, 65 | TransferOut = 8, 66 | ScriptResult = 9, 67 | MessageOut = 10, 68 | Mint = 11, 69 | Burn = 12, 70 | } 71 | ``` 72 | 73 | | name | type | description | 74 | |--------------------|-----------------------------|-----------------------------------------| 75 | | `scriptGasLimit` | `uint64` | Gas limits the script execution. | 76 | | `receiptsRoot` | `byte[32]` | Merkle root of receipts. | 77 | | `scriptLength` | `uint64` | Script length, in instructions. | 78 | | `scriptDataLength` | `uint64` | Length of script input data, in bytes. | 79 | | `policyTypes` | `uint32` | Bitfield of used policy types. | 80 | | `inputsCount` | `uint16` | Number of inputs. | 81 | | `outputsCount` | `uint16` | Number of outputs. | 82 | | `witnessesCount` | `uint16` | Number of witnesses. | 83 | | `script` | `byte[]` | Script to execute. | 84 | | `scriptData` | `byte[]` | Script input data (parameters). | 85 | | `policies` | [Policy](./policy.md)`[]` | List of policies, sorted by `PolicyType`. | 86 | | `inputs` | [Input](./input.md)`[]` | List of inputs. | 87 | | `outputs` | [Output](./output.md)`[]` | List of outputs. | 88 | | `witnesses` | [Witness](./witness.md)`[]` | List of witnesses. | 89 | 90 | Given helper `len()` that returns the number of bytes of a field. 91 | 92 | Transaction is invalid if: 93 | 94 | - Any output is of type `OutputType.ContractCreated` 95 | - `scriptLength > MAX_SCRIPT_LENGTH` 96 | - `scriptDataLength > MAX_SCRIPT_DATA_LENGTH` 97 | - `scriptLength * 4 != len(script)` 98 | - `scriptDataLength != len(scriptData)` 99 | 100 | > **Note:** when signing a transaction, `receiptsRoot` is set to zero. 101 | > 102 | > **Note:** when verifying a predicate or executing a script, `receiptsRoot` is initialized to zero. 103 | 104 | The receipts root `receiptsRoot` is the root of the [binary Merkle tree](../protocol/cryptographic-primitives.md#binary-merkle-tree) of receipts. If there are no receipts, its value is set to the root of the empty tree, i.e. `0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`. 105 | 106 | ## `TransactionCreate` 107 | 108 | | name | type | description | 109 | |------------------------|-----------------------------|---------------------------------------------------| 110 | | `bytecodeWitnessIndex` | `uint16` | Witness index of contract bytecode to create. | 111 | | `salt` | `byte[32]` | Salt. | 112 | | `storageSlotsCount` | `uint64` | Number of storage slots to initialize. | 113 | | `policyTypes` | `uint32` | Bitfield of used policy types. | 114 | | `inputsCount` | `uint16` | Number of inputs. | 115 | | `outputsCount` | `uint16` | Number of outputs. | 116 | | `witnessesCount` | `uint16` | Number of witnesses. | 117 | | `storageSlots` | `(byte[32], byte[32]])[]` | List of storage slots to initialize (key, value). | 118 | | `policies` | [Policy](./policy.md)`[]` | List of policies. | 119 | | `inputs` | [Input](./input.md)`[]` | List of inputs. | 120 | | `outputs` | [Output](./output.md)`[]` | List of outputs. | 121 | | `witnesses` | [Witness](./witness.md)`[]` | List of witnesses. | 122 | 123 | Transaction is invalid if: 124 | 125 | - Any input is of type `InputType.Contract` or `InputType.Message` where `input.dataLength > 0` 126 | - Any input uses non-base asset. 127 | - Any output is of type `OutputType.Contract` or `OutputType.Variable` or `OutputType.Message` 128 | - Any output is of type `OutputType.Change` with non-base `asset_id` 129 | - It does not have exactly one output of type `OutputType.ContractCreated` 130 | - `tx.data.witnesses[bytecodeWitnessIndex].dataLength > CONTRACT_MAX_SIZE` 131 | - `bytecodeWitnessIndex >= tx.witnessesCount` 132 | - The keys of `storageSlots` are not in ascending lexicographic order 133 | - The computed contract ID (see below) is not equal to the `contractID` of the one `OutputType.ContractCreated` output 134 | - `storageSlotsCount > MAX_STORAGE_SLOTS` 135 | - The [Sparse Merkle tree](../protocol/cryptographic-primitives.md#sparse-merkle-tree) root of `storageSlots` is not equal to the `stateRoot` of the one `OutputType.ContractCreated` output 136 | 137 | Creates a contract with contract ID as computed [here](../identifiers/contract-id.md). 138 | 139 | ## `TransactionMint` 140 | 141 | The transaction is created by the block producer and is not signed. Since it is not usable outside of block creation or execution, all fields must be fully set upon creation without any zeroing. 142 | This means that the transaction ID must also include the correct `txPointer` value, not zeroed out. 143 | 144 | | name | type | description | 145 | |------------------|---------------------------------|----------------------------------------------------------------------------| 146 | | `txPointer` | [`TXPointer`](./tx-pointer.md) | The location of the `Mint` transaction in the block. | 147 | | `inputContract` | [`InputContract`](./input.md) | The contract UTXO that assets are minted to. | 148 | | `outputContract` | [`OutputContract`](./output.md) | The contract UTXO that assets are being minted to. | 149 | | `mintAmount` | `uint64` | The amount of funds minted. | 150 | | `mintAssetId` | `byte[32]` | The asset IDs corresponding to the minted amount. | 151 | | `gasPrice` | `uint64` | The gas price to be used in calculating all fees for transactions on block | 152 | 153 | Transaction is invalid if: 154 | 155 | - `txPointer` is zero or doesn't match the block. 156 | - `outputContract.inputIndex` is not zero 157 | 158 | ## `TransactionUpgrade` 159 | 160 | The `Upgrade` transaction allows upgrading either consensus parameters or state transition function used by the network to produce future blocks. The `Upgrade Purpose` type defines the purpose of the upgrade. 161 | 162 | The `Upgrade` transaction is chargeable, and the sender should pay for it. Transaction inputs should contain only base assets. 163 | 164 | Only the privileged address from [`ConsensusParameters`](./consensus_parameters.md) can upgrade the network. The privileged address can be either a real account or a predicate. 165 | 166 | When the upgrade type is `UpgradePurposeType.ConsensusParameters` serialized consensus parameters are available in the witnesses and the `Upgrade` transaction is self-contained because it has all the required information. 167 | 168 | When the upgrade type is `UpgradePurposeType.StateTransition`, the `bytecodeRoot` field contains the Merkle root of the new bytecode of the state transition function. The bytecode should already be available on the blockchain at the upgrade point; otherwise, the upgrade will fail. The bytecode can be part of the genesis block or can be uploaded via the `TransactionUpload` transaction. 169 | 170 | The block header contains information about which versions of consensus parameters and state transition function are used to produce a block, and the `Upgrade` transaction defines behavior corresponding to the version. When the block executes the `Upgrade` transaction, it defines new behavior for either `BlockHeader.consensusParametersVersion + 1` or `BlockHeader.stateTransitionBytecodeVersion + 1`(it depends on the purpose of the upgrade). 171 | 172 | When the `Upgrade` transaction is included in the block, it doesn't affect the current block execution. Since behavior is now defined, the inclusion of the `Upgrade` transaction allows the production of the next block with a new version. The block producer can still continue to use the previous version and start using a new version later unless the state transition function forbids it. 173 | 174 | The behavior is set once per version. It is forbidden to override the behavior of the network. Each behavior should have its own version. The version should grow monotonically without jumps. 175 | 176 | The `BlockHeader.consensusParametersVersion` and `BlockHeader.stateTransitionBytecodeVersion` are independent and can grow at different speeds. 177 | 178 | | name | type | description | 179 | |------------------|----------------------------------------|--------------------------------| 180 | | `upgradePurpose` | [UpgradePurpose](./upgrade_purpose.md) | The purpose of the upgrade. | 181 | | `policyTypes` | `uint32` | Bitfield of used policy types. | 182 | | `inputsCount` | `uint16` | Number of inputs. | 183 | | `outputsCount` | `uint16` | Number of outputs. | 184 | | `witnessesCount` | `uint16` | Number of witnesses. | 185 | | `policies` | [Policy](./policy.md)`[]` | List of policies. | 186 | | `inputs` | [Input](./input.md)`[]` | List of inputs. | 187 | | `outputs` | [Output](./output.md)`[]` | List of outputs. | 188 | | `witnesses` | [Witness](./witness.md)`[]` | List of witnesses. | 189 | 190 | Transaction is invalid if: 191 | 192 | - Any input is of type `InputType.Contract` or `InputType.Message` where `input.dataLength > 0` 193 | - Any input uses non-base asset. 194 | - Any output is of type `OutputType.Contract` or `OutputType.Variable` or `OutputType.Message` or `OutputType.ContractCreated` 195 | - Any output is of type `OutputType.Change` with non-base `asset_id` 196 | - No input where `InputType.Message.owner == PRIVILEGED_ADDRESS` or `InputType.Coint.owner == PRIVILEGED_ADDRESS` 197 | - The `UpgradePurpose` is invalid 198 | 199 | ## `TransactionUpload` 200 | 201 | The `Upload` transaction allows the huge bytecode to be divided into subsections and uploaded slowly to the chain. The [Binary Merkle root](../protocol/cryptographic-primitives.md#binary-merkle-tree) built on top of subsections is an identifier of the bytecode. 202 | 203 | Each transaction uploads a subsection of the code and must contain proof of connection to the root. All subsections should be uploaded sequentially, which allows the concatenation of previously uploaded subsections with new subsection. The bytecode is considered final when the last subsection is uploaded, and future `Upload` transactions with the same `root` fields should be rejected. 204 | 205 | When the bytecode is completed it can be used to upgrade the network. 206 | 207 | The size of each subsection can be arbitrary; the only limit is the maximum number of subsections allowed by the network. The combination of the transaction gas limit and the number of subsections limits the final maximum size of the bytecode. 208 | 209 | | name | type | description | 210 | |---------------------|-----------------------------|-----------------------------------------------------------------------------------------| 211 | | `root` | `byte[32]` | The root of the Merkle tree is created over the bytecode. | 212 | | `witnessIndex` | `uint16` | The witness index of the subsection of the bytecode. | 213 | | `subsectionIndex` | `uint16` | The index of the subsection of the bytecode. | 214 | | `subsectionsNumber` | `uint16` | The total number of subsections on which bytecode was divided. | 215 | | `proofSetCount` | `uint16` | Number of Merkle nodes in the proof. | 216 | | `policyTypes` | `uint32` | Bitfield of used policy types. | 217 | | `inputsCount` | `uint16` | Number of inputs. | 218 | | `outputsCount` | `uint16` | Number of outputs. | 219 | | `witnessesCount` | `uint16` | Number of witnesses. | 220 | | `proofSet` | `byte[32][]` | The proof set of Merkle nodes to verify the connection of the subsection to the `root`. | 221 | | `policies` | [Policy](./policy.md)`[]` | List of policies. | 222 | | `inputs` | [Input](./input.md)`[]` | List of inputs. | 223 | | `outputs` | [Output](./output.md)`[]` | List of outputs. | 224 | | `witnesses` | [Witness](./witness.md)`[]` | List of witnesses. | 225 | 226 | Transaction is invalid if: 227 | 228 | - Any input is of type `InputType.Contract` or `InputType.Message` where `input.dataLength > 0` 229 | - Any input uses non-base asset. 230 | - Any output is of type `OutputType.Contract` or `OutputType.Variable` or `OutputType.Message` or `OutputType.ContractCreated` 231 | - Any output is of type `OutputType.Change` with non-base `asset_id` 232 | - `witnessIndex >= tx.witnessesCount` 233 | - `subsectionIndex` >= `subsectionsNumber` 234 | - `subsectionsNumber > MAX_BYTECODE_SUBSECTIONS` 235 | - The [Binary Merkle tree](../protocol/cryptographic-primitives.md#binary-merkle-tree) root calculated from `(witnesses[witnessIndex], subsectionIndex, subsectionsNumber, proofSet)` is not equal to the `root`. Root calculation is affected by all fields, so modification of one of them invalidates the proof. 236 | 237 | ## `TransactionBlob` 238 | 239 | The `Blob` inserts a simple binary blob in the chain. It's raw immutable data that can be cheaply loaded by the VM and used as instructions or just data. Unlike `Create`, it doesn't hold any state or balances. 240 | 241 | `Blob`s are content-addressed, i.e. the they are uniquely identified by hash of the data field. Programs running on the VM can load an already-posted blob just by the hash, without having to specify it in contract inputs. 242 | 243 | | name | type | description | 244 | |---------------------|-----------------------------|----------------------------------| 245 | | `id` | `byte[32]` | Blob id, i.e. hash of the data. | 246 | | `witnessIndex` | `uint16` | The witness index of the data. | 247 | | `policyTypes` | `uint32` | Bitfield of used policy types. | 248 | | `inputsCount` | `uint16` | Number of inputs. | 249 | | `outputsCount` | `uint16` | Number of outputs. | 250 | | `witnessesCount` | `uint16` | Number of witnesses. | 251 | | `policies` | [Policy](./policy.md)`[]` | List of policies. | 252 | | `inputs` | [Input](./input.md)`[]` | List of inputs. | 253 | | `outputs` | [Output](./output.md)`[]` | List of outputs. | 254 | | `witnesses` | [Witness](./witness.md)`[]` | List of witnesses. | 255 | 256 | Transaction is invalid if: 257 | 258 | - Any input is of type `InputType.Contract` or `InputType.Message` where `input.dataLength > 0` 259 | - Any input uses non-base asset. 260 | - Any output is of type `OutputType.Contract` or `OutputType.Variable` or `OutputType.Message` or `OutputType.ContractCreated` 261 | - Any output is of type `OutputType.Change` with non-base `asset_id` 262 | - `witnessIndex >= tx.witnessesCount` 263 | - `sha256(witnesses[witnessIndex]) != id` 264 | -------------------------------------------------------------------------------- /src/tx-format/tx-pointer.md: -------------------------------------------------------------------------------- 1 | # `TXPointer` 2 | 3 | The location of the transaction in the block. It can be used by UTXOs as a reference to the transaction or by the transaction itself to make it unique. 4 | 5 | | name | type | description | 6 | |---------------|----------|--------------------| 7 | | `blockHeight` | `uint32` | Block height. | 8 | | `txIndex` | `uint16` | Transaction index. | 9 | -------------------------------------------------------------------------------- /src/tx-format/upgrade_purpose.md: -------------------------------------------------------------------------------- 1 | # `UpgradePurposeType` 2 | 3 | ```c++ 4 | enum UpgradePurposeType : uint8 { 5 | ConsensusParameters = 0, 6 | StateTransition = 1, 7 | } 8 | ``` 9 | 10 | | name | type | description | 11 | |--------|---------------------------------------------------------------------------------------------|--------------------------| 12 | | `type` | [`UpgradePurposeType`](#upgradepurposetype) | Type of upgrade purpose. | 13 | | `data` | One of [`ConsensusParameters`](#consensusparameters), [`StateTransition`](#statetransition) | Upgrade purposes. | 14 | 15 | Transaction is invalid if: 16 | 17 | - `type` is not valid `UpgradePurposeType` value` 18 | 19 | ## `ConsensusParameters` 20 | 21 | | name | type | description | 22 | |----------------|------------|-------------------------------------------------------------------------------------------------------------------------------| 23 | | `witnessIndex` | `uint16` | Index of witness that contains a serialized(with [postcard](https://docs.rs/postcard/latest/postcard/)) consensus parameters. | 24 | | `checksum` | `byte[32]` | The hash of the serialized consensus parameters. | 25 | 26 | Given helper `deserialize_consensus_parameters()` that deserializes the consensus parameters from a witness by using [postcard](https://docs.rs/postcard/latest/postcard/) algorithm. 27 | 28 | Transaction is invalid if: 29 | 30 | - `witnessIndex >= tx.witnessesCount` 31 | - `checksum != sha256(tx.data.witnesses[witnessIndex])` 32 | - `deserialize_consensus_parameters(tx.data.witnesses[witnessIndex])` returns an error. 33 | 34 | ## `StateTransition` 35 | 36 | | name | type | description | 37 | |----------------|------------|----------------------------------------------------------------| 38 | | `bytecodeRoot` | `byte[32]` | The root of the new bytecode of the state transition function. | 39 | -------------------------------------------------------------------------------- /src/tx-format/witness.md: -------------------------------------------------------------------------------- 1 | # Witness 2 | 3 | | name | type | description | 4 | |--------------|----------|-----------------------------------| 5 | | `dataLength` | `uint64` | Length of witness data, in bytes. | 6 | | `data` | `byte[]` | Witness data. | 7 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Delete Non-existent Key.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 108f731f2414e33ae57e584dc26bd276db07874436b2264ca6e520c658185c6b 4 | name: Test Delete Non-existent Key 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 41 | - action: delete 42 | key: 43 | encoding: hex 44 | value: 72034de8a594b12de51205feba7ade26899d8425e81eac7f8c296bf974a51c60 45 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Delete Sparse Union.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: e912e97abc67707b2e6027338292943b53d01a7fbd7b244674128c7e468dd696 4 | name: Test Delete Sparse Union 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 41 | - action: update 42 | data: 43 | encoding: utf-8 44 | value: DATA 45 | key: 46 | encoding: hex 47 | value: 221f8af2372a95064f2ef7d7712216a9ab46e7ef98482fd237e106f83eaa7569 48 | - action: update 49 | data: 50 | encoding: utf-8 51 | value: DATA 52 | key: 53 | encoding: hex 54 | value: b253668f6b59f1ff28522831931e4d3c5a3de533965af22e961735437c0172cb 55 | - action: update 56 | data: 57 | encoding: utf-8 58 | value: DATA 59 | key: 60 | encoding: hex 61 | value: 1561ade0621c5acf44b780521f95a1e0b19b4e5032945b860c4032fc28a3a23b 62 | - action: update 63 | data: 64 | encoding: utf-8 65 | value: DATA 66 | key: 67 | encoding: hex 68 | value: 17eb70034b5b71092521d184c5e7b069d47de657e51aef2be11a00c115036943 69 | - action: update 70 | data: 71 | encoding: utf-8 72 | value: DATA 73 | key: 74 | encoding: hex 75 | value: 3b28a6c3766c6295adad976d349705ef49393fbfdebe4facb5862d2cdfa285d3 76 | - action: delete 77 | key: 78 | encoding: hex 79 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 80 | - action: delete 81 | key: 82 | encoding: hex 83 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 84 | - action: delete 85 | key: 86 | encoding: hex 87 | value: 221f8af2372a95064f2ef7d7712216a9ab46e7ef98482fd237e106f83eaa7569 88 | - action: delete 89 | key: 90 | encoding: hex 91 | value: 1561ade0621c5acf44b780521f95a1e0b19b4e5032945b860c4032fc28a3a23b 92 | - action: delete 93 | key: 94 | encoding: hex 95 | value: 3b28a6c3766c6295adad976d349705ef49393fbfdebe4facb5862d2cdfa285d3 96 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Empty Root.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: "0000000000000000000000000000000000000000000000000000000000000000" 4 | name: Test Empty Root 5 | steps: [] 6 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Interleaved Update Delete.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 7e6643325042cfe0fc76626c043b97062af51c7e9fc56665f12b479034bce326 4 | name: Test Interleaved Update Delete 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 41 | - action: update 42 | data: 43 | encoding: utf-8 44 | value: DATA 45 | key: 46 | encoding: hex 47 | value: 221f8af2372a95064f2ef7d7712216a9ab46e7ef98482fd237e106f83eaa7569 48 | - action: update 49 | data: 50 | encoding: utf-8 51 | value: DATA 52 | key: 53 | encoding: hex 54 | value: b253668f6b59f1ff28522831931e4d3c5a3de533965af22e961735437c0172cb 55 | - action: update 56 | data: 57 | encoding: utf-8 58 | value: DATA 59 | key: 60 | encoding: hex 61 | value: 1561ade0621c5acf44b780521f95a1e0b19b4e5032945b860c4032fc28a3a23b 62 | - action: update 63 | data: 64 | encoding: utf-8 65 | value: DATA 66 | key: 67 | encoding: hex 68 | value: 17eb70034b5b71092521d184c5e7b069d47de657e51aef2be11a00c115036943 69 | - action: update 70 | data: 71 | encoding: utf-8 72 | value: DATA 73 | key: 74 | encoding: hex 75 | value: 3b28a6c3766c6295adad976d349705ef49393fbfdebe4facb5862d2cdfa285d3 76 | - action: delete 77 | key: 78 | encoding: hex 79 | value: 221f8af2372a95064f2ef7d7712216a9ab46e7ef98482fd237e106f83eaa7569 80 | - action: delete 81 | key: 82 | encoding: hex 83 | value: b253668f6b59f1ff28522831931e4d3c5a3de533965af22e961735437c0172cb 84 | - action: delete 85 | key: 86 | encoding: hex 87 | value: 1561ade0621c5acf44b780521f95a1e0b19b4e5032945b860c4032fc28a3a23b 88 | - action: delete 89 | key: 90 | encoding: hex 91 | value: 17eb70034b5b71092521d184c5e7b069d47de657e51aef2be11a00c115036943 92 | - action: delete 93 | key: 94 | encoding: hex 95 | value: 3b28a6c3766c6295adad976d349705ef49393fbfdebe4facb5862d2cdfa285d3 96 | - action: delete 97 | key: 98 | encoding: hex 99 | value: e084a105a7b7d599b8346d3cba5ac51b756d7e29c7ef77fd9eff31fdeae31389 100 | - action: delete 101 | key: 102 | encoding: hex 103 | value: 390b36a09502b05d4f8c27aea2636c6b7fd05b27d742ed32074ffea1f888ebe4 104 | - action: delete 105 | key: 106 | encoding: hex 107 | value: c22ceee66b8ab104483c83053173b33f992dd4fcb457284c60ef9d699a1c7059 108 | - action: delete 109 | key: 110 | encoding: hex 111 | value: 8092fe01b9ce31a49ce380fc2fe1ee6b6b7d5c15c5f1ecb6ad98c60c4273a435 112 | - action: delete 113 | key: 114 | encoding: hex 115 | value: 7fde8eebf388fcff667a89be60430cc6e198b1a78cb603a39cdd09885a3336e3 116 | - action: update 117 | data: 118 | encoding: utf-8 119 | value: DATA 120 | key: 121 | encoding: hex 122 | value: e084a105a7b7d599b8346d3cba5ac51b756d7e29c7ef77fd9eff31fdeae31389 123 | - action: update 124 | data: 125 | encoding: utf-8 126 | value: DATA 127 | key: 128 | encoding: hex 129 | value: 390b36a09502b05d4f8c27aea2636c6b7fd05b27d742ed32074ffea1f888ebe4 130 | - action: update 131 | data: 132 | encoding: utf-8 133 | value: DATA 134 | key: 135 | encoding: hex 136 | value: c22ceee66b8ab104483c83053173b33f992dd4fcb457284c60ef9d699a1c7059 137 | - action: update 138 | data: 139 | encoding: utf-8 140 | value: DATA 141 | key: 142 | encoding: hex 143 | value: 8092fe01b9ce31a49ce380fc2fe1ee6b6b7d5c15c5f1ecb6ad98c60c4273a435 144 | - action: update 145 | data: 146 | encoding: utf-8 147 | value: DATA 148 | key: 149 | encoding: hex 150 | value: 7fde8eebf388fcff667a89be60430cc6e198b1a78cb603a39cdd09885a3336e3 151 | - action: update 152 | data: 153 | encoding: utf-8 154 | value: DATA 155 | key: 156 | encoding: hex 157 | value: 9246be1e9ba9f5de5baf766a256eb725e9a7551fb93d7faa793c938e0f41de35 158 | - action: update 159 | data: 160 | encoding: utf-8 161 | value: DATA 162 | key: 163 | encoding: hex 164 | value: 5085cb99dbe1e374ccd321e5b58182d2c42cf4840c68cfab17b0618a8285e7d6 165 | - action: update 166 | data: 167 | encoding: utf-8 168 | value: DATA 169 | key: 170 | encoding: hex 171 | value: 8e00d1c0c8ffe94540e534e256d4589be3e3865dc0559a732697aef38a364e83 172 | - action: update 173 | data: 174 | encoding: utf-8 175 | value: DATA 176 | key: 177 | encoding: hex 178 | value: e9f3440e5518839aa600db07b5400f8ec287ce0321fad602afd103ce447a1c98 179 | - action: update 180 | data: 181 | encoding: utf-8 182 | value: DATA 183 | key: 184 | encoding: hex 185 | value: 14236fe421fe9ddb8377a19b60ce71dd655704bcefc225c9287fb11127ba6569 186 | - action: delete 187 | key: 188 | encoding: hex 189 | value: 9246be1e9ba9f5de5baf766a256eb725e9a7551fb93d7faa793c938e0f41de35 190 | - action: delete 191 | key: 192 | encoding: hex 193 | value: 5085cb99dbe1e374ccd321e5b58182d2c42cf4840c68cfab17b0618a8285e7d6 194 | - action: delete 195 | key: 196 | encoding: hex 197 | value: 8e00d1c0c8ffe94540e534e256d4589be3e3865dc0559a732697aef38a364e83 198 | - action: delete 199 | key: 200 | encoding: hex 201 | value: e9f3440e5518839aa600db07b5400f8ec287ce0321fad602afd103ce447a1c98 202 | - action: delete 203 | key: 204 | encoding: hex 205 | value: 14236fe421fe9ddb8377a19b60ce71dd655704bcefc225c9287fb11127ba6569 206 | - action: delete 207 | key: 208 | encoding: hex 209 | value: a7911cdfdc28e6a1867e359ba426081aacfa692fdeb3e978d2a68dd924fa8c3e 210 | - action: delete 211 | key: 212 | encoding: hex 213 | value: 21548c66b44347d877e7b405a250121cda87cd494b122f0324f7df3b6cd75f86 214 | - action: delete 215 | key: 216 | encoding: hex 217 | value: bc2d9ddc9857e53598677dbea82a2583879e89ce6c032c77d825187bf3f1a943 218 | - action: delete 219 | key: 220 | encoding: hex 221 | value: 58ec452ede72799baf21664edc953297b592ad9e95f2381710593ad7a32f31ef 222 | - action: delete 223 | key: 224 | encoding: hex 225 | value: 79a881f99a636d0ad75f16f53668982b59f8bb96c3fbb449155fe7a08dba9cb1 226 | - action: update 227 | data: 228 | encoding: utf-8 229 | value: DATA 230 | key: 231 | encoding: hex 232 | value: a7911cdfdc28e6a1867e359ba426081aacfa692fdeb3e978d2a68dd924fa8c3e 233 | - action: update 234 | data: 235 | encoding: utf-8 236 | value: DATA 237 | key: 238 | encoding: hex 239 | value: 21548c66b44347d877e7b405a250121cda87cd494b122f0324f7df3b6cd75f86 240 | - action: update 241 | data: 242 | encoding: utf-8 243 | value: DATA 244 | key: 245 | encoding: hex 246 | value: bc2d9ddc9857e53598677dbea82a2583879e89ce6c032c77d825187bf3f1a943 247 | - action: update 248 | data: 249 | encoding: utf-8 250 | value: DATA 251 | key: 252 | encoding: hex 253 | value: 58ec452ede72799baf21664edc953297b592ad9e95f2381710593ad7a32f31ef 254 | - action: update 255 | data: 256 | encoding: utf-8 257 | value: DATA 258 | key: 259 | encoding: hex 260 | value: 79a881f99a636d0ad75f16f53668982b59f8bb96c3fbb449155fe7a08dba9cb1 261 | - action: update 262 | data: 263 | encoding: utf-8 264 | value: DATA 265 | key: 266 | encoding: hex 267 | value: 282a163f3e6f52ab35cf838079369bce33cf5a1f151d2822846095a6d07e1ae2 268 | - action: update 269 | data: 270 | encoding: utf-8 271 | value: DATA 272 | key: 273 | encoding: hex 274 | value: c1c3c8fdf22e3a4adef796c8fdaf739d7d3b222f995891eb8f495ca71fb932a8 275 | - action: update 276 | data: 277 | encoding: utf-8 278 | value: DATA 279 | key: 280 | encoding: hex 281 | value: 688e94a51ee508a95e761294afb7a6004b432c15d9890c80ddf23bde8caa4c26 282 | - action: update 283 | data: 284 | encoding: utf-8 285 | value: DATA 286 | key: 287 | encoding: hex 288 | value: c006af35e3b4ca022ab986593a148b4f196f186168ee96604eeaa7e338e66ac1 289 | - action: update 290 | data: 291 | encoding: utf-8 292 | value: DATA 293 | key: 294 | encoding: hex 295 | value: c1a9fae908008d34f389b1dba2a1a8e8301f7a942412ef6e6299c9e27e89dfaa 296 | - action: delete 297 | key: 298 | encoding: hex 299 | value: 282a163f3e6f52ab35cf838079369bce33cf5a1f151d2822846095a6d07e1ae2 300 | - action: delete 301 | key: 302 | encoding: hex 303 | value: c1c3c8fdf22e3a4adef796c8fdaf739d7d3b222f995891eb8f495ca71fb932a8 304 | - action: delete 305 | key: 306 | encoding: hex 307 | value: 688e94a51ee508a95e761294afb7a6004b432c15d9890c80ddf23bde8caa4c26 308 | - action: delete 309 | key: 310 | encoding: hex 311 | value: c006af35e3b4ca022ab986593a148b4f196f186168ee96604eeaa7e338e66ac1 312 | - action: delete 313 | key: 314 | encoding: hex 315 | value: c1a9fae908008d34f389b1dba2a1a8e8301f7a942412ef6e6299c9e27e89dfaa 316 | - action: delete 317 | key: 318 | encoding: hex 319 | value: 560231689713a5933b6c8ac3e6b2f243730e49e1c6b0c610c41e8e8dad26044c 320 | - action: delete 321 | key: 322 | encoding: hex 323 | value: fe5b0deca006174e2151088e1a7d60fe91819467db5d709ae5a19c01a3cd3e3f 324 | - action: delete 325 | key: 326 | encoding: hex 327 | value: 2de44621c76edf2debbc2df62ccb52c5036b1919dca3af0c0a886cc48dbfaeba 328 | - action: delete 329 | key: 330 | encoding: hex 331 | value: 83440636eff7b2ec0f78ef7b8e480a033e8aeb67e6ecb657ce9bcdfdb21aa744 332 | - action: delete 333 | key: 334 | encoding: hex 335 | value: eaaf1805f2ec6a18eee5a7909f79908651341965d9f0b9de8d45d9262e5735ae 336 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 1 Delete 1.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: "0000000000000000000000000000000000000000000000000000000000000000" 4 | name: Test Update 1 Delete 1 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: delete 14 | key: 15 | encoding: hex 16 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 17 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 1.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 39f36a7cb4dfb1b46f03d044265df6a491dffc1034121bc1071a34ddce9bb14b 4 | name: Test Update 1 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 10 Delete 5.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 108f731f2414e33ae57e584dc26bd276db07874436b2264ca6e520c658185c6b 4 | name: Test Update 10 Delete 5 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 41 | - action: update 42 | data: 43 | encoding: utf-8 44 | value: DATA 45 | key: 46 | encoding: hex 47 | value: 221f8af2372a95064f2ef7d7712216a9ab46e7ef98482fd237e106f83eaa7569 48 | - action: update 49 | data: 50 | encoding: utf-8 51 | value: DATA 52 | key: 53 | encoding: hex 54 | value: b253668f6b59f1ff28522831931e4d3c5a3de533965af22e961735437c0172cb 55 | - action: update 56 | data: 57 | encoding: utf-8 58 | value: DATA 59 | key: 60 | encoding: hex 61 | value: 1561ade0621c5acf44b780521f95a1e0b19b4e5032945b860c4032fc28a3a23b 62 | - action: update 63 | data: 64 | encoding: utf-8 65 | value: DATA 66 | key: 67 | encoding: hex 68 | value: 17eb70034b5b71092521d184c5e7b069d47de657e51aef2be11a00c115036943 69 | - action: update 70 | data: 71 | encoding: utf-8 72 | value: DATA 73 | key: 74 | encoding: hex 75 | value: 3b28a6c3766c6295adad976d349705ef49393fbfdebe4facb5862d2cdfa285d3 76 | - action: delete 77 | key: 78 | encoding: hex 79 | value: 221f8af2372a95064f2ef7d7712216a9ab46e7ef98482fd237e106f83eaa7569 80 | - action: delete 81 | key: 82 | encoding: hex 83 | value: b253668f6b59f1ff28522831931e4d3c5a3de533965af22e961735437c0172cb 84 | - action: delete 85 | key: 86 | encoding: hex 87 | value: 1561ade0621c5acf44b780521f95a1e0b19b4e5032945b860c4032fc28a3a23b 88 | - action: delete 89 | key: 90 | encoding: hex 91 | value: 17eb70034b5b71092521d184c5e7b069d47de657e51aef2be11a00c115036943 92 | - action: delete 93 | key: 94 | encoding: hex 95 | value: 3b28a6c3766c6295adad976d349705ef49393fbfdebe4facb5862d2cdfa285d3 96 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 10.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 21ca4917e99da99a61de93deaf88c400d4c082991cb95779e444d43dd13e8849 4 | name: Test Update 10 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 41 | - action: update 42 | data: 43 | encoding: utf-8 44 | value: DATA 45 | key: 46 | encoding: hex 47 | value: 221f8af2372a95064f2ef7d7712216a9ab46e7ef98482fd237e106f83eaa7569 48 | - action: update 49 | data: 50 | encoding: utf-8 51 | value: DATA 52 | key: 53 | encoding: hex 54 | value: b253668f6b59f1ff28522831931e4d3c5a3de533965af22e961735437c0172cb 55 | - action: update 56 | data: 57 | encoding: utf-8 58 | value: DATA 59 | key: 60 | encoding: hex 61 | value: 1561ade0621c5acf44b780521f95a1e0b19b4e5032945b860c4032fc28a3a23b 62 | - action: update 63 | data: 64 | encoding: utf-8 65 | value: DATA 66 | key: 67 | encoding: hex 68 | value: 17eb70034b5b71092521d184c5e7b069d47de657e51aef2be11a00c115036943 69 | - action: update 70 | data: 71 | encoding: utf-8 72 | value: DATA 73 | key: 74 | encoding: hex 75 | value: 3b28a6c3766c6295adad976d349705ef49393fbfdebe4facb5862d2cdfa285d3 76 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 100.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 82bf747d455a55e2f7044a03536fc43f1f55d43b855e72c0110c986707a23e4d 4 | name: Test Update 100 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 41 | - action: update 42 | data: 43 | encoding: utf-8 44 | value: DATA 45 | key: 46 | encoding: hex 47 | value: 221f8af2372a95064f2ef7d7712216a9ab46e7ef98482fd237e106f83eaa7569 48 | - action: update 49 | data: 50 | encoding: utf-8 51 | value: DATA 52 | key: 53 | encoding: hex 54 | value: b253668f6b59f1ff28522831931e4d3c5a3de533965af22e961735437c0172cb 55 | - action: update 56 | data: 57 | encoding: utf-8 58 | value: DATA 59 | key: 60 | encoding: hex 61 | value: 1561ade0621c5acf44b780521f95a1e0b19b4e5032945b860c4032fc28a3a23b 62 | - action: update 63 | data: 64 | encoding: utf-8 65 | value: DATA 66 | key: 67 | encoding: hex 68 | value: 17eb70034b5b71092521d184c5e7b069d47de657e51aef2be11a00c115036943 69 | - action: update 70 | data: 71 | encoding: utf-8 72 | value: DATA 73 | key: 74 | encoding: hex 75 | value: 3b28a6c3766c6295adad976d349705ef49393fbfdebe4facb5862d2cdfa285d3 76 | - action: update 77 | data: 78 | encoding: utf-8 79 | value: DATA 80 | key: 81 | encoding: hex 82 | value: e084a105a7b7d599b8346d3cba5ac51b756d7e29c7ef77fd9eff31fdeae31389 83 | - action: update 84 | data: 85 | encoding: utf-8 86 | value: DATA 87 | key: 88 | encoding: hex 89 | value: 390b36a09502b05d4f8c27aea2636c6b7fd05b27d742ed32074ffea1f888ebe4 90 | - action: update 91 | data: 92 | encoding: utf-8 93 | value: DATA 94 | key: 95 | encoding: hex 96 | value: c22ceee66b8ab104483c83053173b33f992dd4fcb457284c60ef9d699a1c7059 97 | - action: update 98 | data: 99 | encoding: utf-8 100 | value: DATA 101 | key: 102 | encoding: hex 103 | value: 8092fe01b9ce31a49ce380fc2fe1ee6b6b7d5c15c5f1ecb6ad98c60c4273a435 104 | - action: update 105 | data: 106 | encoding: utf-8 107 | value: DATA 108 | key: 109 | encoding: hex 110 | value: 7fde8eebf388fcff667a89be60430cc6e198b1a78cb603a39cdd09885a3336e3 111 | - action: update 112 | data: 113 | encoding: utf-8 114 | value: DATA 115 | key: 116 | encoding: hex 117 | value: 9246be1e9ba9f5de5baf766a256eb725e9a7551fb93d7faa793c938e0f41de35 118 | - action: update 119 | data: 120 | encoding: utf-8 121 | value: DATA 122 | key: 123 | encoding: hex 124 | value: 5085cb99dbe1e374ccd321e5b58182d2c42cf4840c68cfab17b0618a8285e7d6 125 | - action: update 126 | data: 127 | encoding: utf-8 128 | value: DATA 129 | key: 130 | encoding: hex 131 | value: 8e00d1c0c8ffe94540e534e256d4589be3e3865dc0559a732697aef38a364e83 132 | - action: update 133 | data: 134 | encoding: utf-8 135 | value: DATA 136 | key: 137 | encoding: hex 138 | value: e9f3440e5518839aa600db07b5400f8ec287ce0321fad602afd103ce447a1c98 139 | - action: update 140 | data: 141 | encoding: utf-8 142 | value: DATA 143 | key: 144 | encoding: hex 145 | value: 14236fe421fe9ddb8377a19b60ce71dd655704bcefc225c9287fb11127ba6569 146 | - action: update 147 | data: 148 | encoding: utf-8 149 | value: DATA 150 | key: 151 | encoding: hex 152 | value: a7911cdfdc28e6a1867e359ba426081aacfa692fdeb3e978d2a68dd924fa8c3e 153 | - action: update 154 | data: 155 | encoding: utf-8 156 | value: DATA 157 | key: 158 | encoding: hex 159 | value: 21548c66b44347d877e7b405a250121cda87cd494b122f0324f7df3b6cd75f86 160 | - action: update 161 | data: 162 | encoding: utf-8 163 | value: DATA 164 | key: 165 | encoding: hex 166 | value: bc2d9ddc9857e53598677dbea82a2583879e89ce6c032c77d825187bf3f1a943 167 | - action: update 168 | data: 169 | encoding: utf-8 170 | value: DATA 171 | key: 172 | encoding: hex 173 | value: 58ec452ede72799baf21664edc953297b592ad9e95f2381710593ad7a32f31ef 174 | - action: update 175 | data: 176 | encoding: utf-8 177 | value: DATA 178 | key: 179 | encoding: hex 180 | value: 79a881f99a636d0ad75f16f53668982b59f8bb96c3fbb449155fe7a08dba9cb1 181 | - action: update 182 | data: 183 | encoding: utf-8 184 | value: DATA 185 | key: 186 | encoding: hex 187 | value: 282a163f3e6f52ab35cf838079369bce33cf5a1f151d2822846095a6d07e1ae2 188 | - action: update 189 | data: 190 | encoding: utf-8 191 | value: DATA 192 | key: 193 | encoding: hex 194 | value: c1c3c8fdf22e3a4adef796c8fdaf739d7d3b222f995891eb8f495ca71fb932a8 195 | - action: update 196 | data: 197 | encoding: utf-8 198 | value: DATA 199 | key: 200 | encoding: hex 201 | value: 688e94a51ee508a95e761294afb7a6004b432c15d9890c80ddf23bde8caa4c26 202 | - action: update 203 | data: 204 | encoding: utf-8 205 | value: DATA 206 | key: 207 | encoding: hex 208 | value: c006af35e3b4ca022ab986593a148b4f196f186168ee96604eeaa7e338e66ac1 209 | - action: update 210 | data: 211 | encoding: utf-8 212 | value: DATA 213 | key: 214 | encoding: hex 215 | value: c1a9fae908008d34f389b1dba2a1a8e8301f7a942412ef6e6299c9e27e89dfaa 216 | - action: update 217 | data: 218 | encoding: utf-8 219 | value: DATA 220 | key: 221 | encoding: hex 222 | value: 560231689713a5933b6c8ac3e6b2f243730e49e1c6b0c610c41e8e8dad26044c 223 | - action: update 224 | data: 225 | encoding: utf-8 226 | value: DATA 227 | key: 228 | encoding: hex 229 | value: fe5b0deca006174e2151088e1a7d60fe91819467db5d709ae5a19c01a3cd3e3f 230 | - action: update 231 | data: 232 | encoding: utf-8 233 | value: DATA 234 | key: 235 | encoding: hex 236 | value: 2de44621c76edf2debbc2df62ccb52c5036b1919dca3af0c0a886cc48dbfaeba 237 | - action: update 238 | data: 239 | encoding: utf-8 240 | value: DATA 241 | key: 242 | encoding: hex 243 | value: 83440636eff7b2ec0f78ef7b8e480a033e8aeb67e6ecb657ce9bcdfdb21aa744 244 | - action: update 245 | data: 246 | encoding: utf-8 247 | value: DATA 248 | key: 249 | encoding: hex 250 | value: eaaf1805f2ec6a18eee5a7909f79908651341965d9f0b9de8d45d9262e5735ae 251 | - action: update 252 | data: 253 | encoding: utf-8 254 | value: DATA 255 | key: 256 | encoding: hex 257 | value: 6870f86f6560dd5b0d0a47d0ae89df6a96b6a47a6258940060d75ff759634158 258 | - action: update 259 | data: 260 | encoding: utf-8 261 | value: DATA 262 | key: 263 | encoding: hex 264 | value: e882dd6a247f4ada1f700f1918bd23b7c730ad62af15f5cec8de976cbad09691 265 | - action: update 266 | data: 267 | encoding: utf-8 268 | value: DATA 269 | key: 270 | encoding: hex 271 | value: 51be0458d20b1ce2ff5316e7e473109c26f5d8b457037edf8c4529f6ff82bddb 272 | - action: update 273 | data: 274 | encoding: utf-8 275 | value: DATA 276 | key: 277 | encoding: hex 278 | value: 0f65dd2d76efb602f9554514892751d5cf336a56c3888aa8cb122e970016949a 279 | - action: update 280 | data: 281 | encoding: utf-8 282 | value: DATA 283 | key: 284 | encoding: hex 285 | value: b9098fe78517adc23218f8cd7d804f55c977fb22185a4d8e752ab7e82e5c1d89 286 | - action: update 287 | data: 288 | encoding: utf-8 289 | value: DATA 290 | key: 291 | encoding: hex 292 | value: 95534981420d9a1e5d3cd3b567c6e21f920742087ecf44c187e077cdc8497ac2 293 | - action: update 294 | data: 295 | encoding: utf-8 296 | value: DATA 297 | key: 298 | encoding: hex 299 | value: c8d26116ed30f9816a05fdf061b2535145472f388d9814e96f33f08369dbcbd0 300 | - action: update 301 | data: 302 | encoding: utf-8 303 | value: DATA 304 | key: 305 | encoding: hex 306 | value: ae3c8b8d99a39542f78af83dbbb42c81cd94199ec1b5f60a0801063e95842570 307 | - action: update 308 | data: 309 | encoding: utf-8 310 | value: DATA 311 | key: 312 | encoding: hex 313 | value: d596e806d34bd7d4304b9f00ec340f02fa90c4faa17fe39729cb15c76e0de77f 314 | - action: update 315 | data: 316 | encoding: utf-8 317 | value: DATA 318 | key: 319 | encoding: hex 320 | value: 552d7d672c5bbbccfb210a425e36a1d65bc663d3d3c395114c8ebc9c7cf28394 321 | - action: update 322 | data: 323 | encoding: utf-8 324 | value: DATA 325 | key: 326 | encoding: hex 327 | value: 5a05f87d329a8321f2006f4f3b11b810aeddcd21cb383b61df03824074eaffc9 328 | - action: update 329 | data: 330 | encoding: utf-8 331 | value: DATA 332 | key: 333 | encoding: hex 334 | value: daceee899cdb68711b2b16b1708d684b193062163a2ef8ca80e5a3f002212822 335 | - action: update 336 | data: 337 | encoding: utf-8 338 | value: DATA 339 | key: 340 | encoding: hex 341 | value: 6b0e4bfa8dc9b19ccc121b2bd0d22da7298d7a4d72b4ba1df1bbec5d56800a66 342 | - action: update 343 | data: 344 | encoding: utf-8 345 | value: DATA 346 | key: 347 | encoding: hex 348 | value: 2c19fc328bfccab923ee092d9123a9ccc9fb37bbf0d2c65d2fe12b6684ff4857 349 | - action: update 350 | data: 351 | encoding: utf-8 352 | value: DATA 353 | key: 354 | encoding: hex 355 | value: cc74c0c353fe2c007aff8dc7db556638f52260fea1dc0bce2f04002db6ad90ce 356 | - action: update 357 | data: 358 | encoding: utf-8 359 | value: DATA 360 | key: 361 | encoding: hex 362 | value: 1fc244af2b96d0169a177e2559af29e0484744e4b8501d1044d76c9f7b3cf307 363 | - action: update 364 | data: 365 | encoding: utf-8 366 | value: DATA 367 | key: 368 | encoding: hex 369 | value: 8ef3b0d7c4476e2c0a91ccc5867740a0549313b585345c1d12587ca2ed04e9f5 370 | - action: update 371 | data: 372 | encoding: utf-8 373 | value: DATA 374 | key: 375 | encoding: hex 376 | value: 46cecbeaa7de6866910a4856ef1f7378f9dd9dfa698578637ce4ecb33e7f7bac 377 | - action: update 378 | data: 379 | encoding: utf-8 380 | value: DATA 381 | key: 382 | encoding: hex 383 | value: 0d21caa7d0c6f1ff692603abec4315c560792923a6cfa5729ef8dd6d8220e0a1 384 | - action: update 385 | data: 386 | encoding: utf-8 387 | value: DATA 388 | key: 389 | encoding: hex 390 | value: 0cc6a4ccca98a6360d42fde83780517edbfc32b300cd3ba0e0a5453a8166697a 391 | - action: update 392 | data: 393 | encoding: utf-8 394 | value: DATA 395 | key: 396 | encoding: hex 397 | value: 683babc0c420c80a762490d4d73b271876ab07f11c80553f6e9125fb82c734f0 398 | - action: update 399 | data: 400 | encoding: utf-8 401 | value: DATA 402 | key: 403 | encoding: hex 404 | value: f8de494d620f85b1cfed002bb1ea4fbf93f7eaa4b4b8a5c7f145b3cab041c0d3 405 | - action: update 406 | data: 407 | encoding: utf-8 408 | value: DATA 409 | key: 410 | encoding: hex 411 | value: 75ce1f4e6c052ea6fec089042a96928fda84ea969c99b35f6894a1819226ac5e 412 | - action: update 413 | data: 414 | encoding: utf-8 415 | value: DATA 416 | key: 417 | encoding: hex 418 | value: e696a8ec6b7f294aa56059125664931f12997987bb52fffefc209d35492adc3c 419 | - action: update 420 | data: 421 | encoding: utf-8 422 | value: DATA 423 | key: 424 | encoding: hex 425 | value: af0ff5439963767457709e63313da23382a6292190e2de1ba9c6c87dc6a1927e 426 | - action: update 427 | data: 428 | encoding: utf-8 429 | value: DATA 430 | key: 431 | encoding: hex 432 | value: 4082763076bdaee3a85e52eb5893169d45d057397616251e0e699e6403238e66 433 | - action: update 434 | data: 435 | encoding: utf-8 436 | value: DATA 437 | key: 438 | encoding: hex 439 | value: 15b165510f75144be8633336a97ac62c664d5c436db297fc13fb4d3ac147d7fd 440 | - action: update 441 | data: 442 | encoding: utf-8 443 | value: DATA 444 | key: 445 | encoding: hex 446 | value: 31b67dba7cfd6e2d7540f9c96d90a45b8f2d44956620723024d4e1beeacd4602 447 | - action: update 448 | data: 449 | encoding: utf-8 450 | value: DATA 451 | key: 452 | encoding: hex 453 | value: d99e58435243d9fef9c88273b8d553b4fba4d0baf8009d29eae74fa99e0d9f57 454 | - action: update 455 | data: 456 | encoding: utf-8 457 | value: DATA 458 | key: 459 | encoding: hex 460 | value: d88c86f15bbea365d658ad95a81d45367c465f7af6f7264fb077f01747ddc77d 461 | - action: update 462 | data: 463 | encoding: utf-8 464 | value: DATA 465 | key: 466 | encoding: hex 467 | value: 03e3c2420f5066a5fa6e36735ed8cc4f6a251046263e1a6024f009deeee3b952 468 | - action: update 469 | data: 470 | encoding: utf-8 471 | value: DATA 472 | key: 473 | encoding: hex 474 | value: 825ac1bb838d399fb1ba55a6247e2c8c7a0c3ec25898f3c94dbfb51fa6e73951 475 | - action: update 476 | data: 477 | encoding: utf-8 478 | value: DATA 479 | key: 480 | encoding: hex 481 | value: ad286c64373644140ff927b256b8415467b5d27645ff997010b15519d022631b 482 | - action: update 483 | data: 484 | encoding: utf-8 485 | value: DATA 486 | key: 487 | encoding: hex 488 | value: 03a88c8867b3fbcfeefc3270af46afbeb74a27e12cad758e188154cb4aa923dc 489 | - action: update 490 | data: 491 | encoding: utf-8 492 | value: DATA 493 | key: 494 | encoding: hex 495 | value: 569ce7ffc5ab3343d40276040602bb1e6d9a9f9aeb5c25e2c65f2d3c1b867ff4 496 | - action: update 497 | data: 498 | encoding: utf-8 499 | value: DATA 500 | key: 501 | encoding: hex 502 | value: 514970ce425bbbe11b969e5cd683f4c1b7722f7f026b45006c53a8031b2fc32e 503 | - action: update 504 | data: 505 | encoding: utf-8 506 | value: DATA 507 | key: 508 | encoding: hex 509 | value: 719b774d7d3b2ebd5e2ce1cde4f59a2ebb8f1f7069daa0baecc564a83abd5bc6 510 | - action: update 511 | data: 512 | encoding: utf-8 513 | value: DATA 514 | key: 515 | encoding: hex 516 | value: a5e537813128ccca735d65a9027cd5057d164fc78f25e55128e17a501851d585 517 | - action: update 518 | data: 519 | encoding: utf-8 520 | value: DATA 521 | key: 522 | encoding: hex 523 | value: 3f08f60bf2a0754139d918d80882ef46cd0257bd2f62ef5d8a1e28175c4360cc 524 | - action: update 525 | data: 526 | encoding: utf-8 527 | value: DATA 528 | key: 529 | encoding: hex 530 | value: 5d6941b983cd61008a67cd3865fe78cc6a4f0966f2c3fb27e1a3ec6667a545dd 531 | - action: update 532 | data: 533 | encoding: utf-8 534 | value: DATA 535 | key: 536 | encoding: hex 537 | value: 90a21fd1ef7b2ead7bf8b13df631f94dd0b1c0ab174a64fb9ea5d37fdad4b150 538 | - action: update 539 | data: 540 | encoding: utf-8 541 | value: DATA 542 | key: 543 | encoding: hex 544 | value: dbf8f061b38993c8d7dc1f521c3df09f31359d1fb947e19efac98362f99d46de 545 | - action: update 546 | data: 547 | encoding: utf-8 548 | value: DATA 549 | key: 550 | encoding: hex 551 | value: 0a62d0f80072eafa5d94b92a01043d978e9ec6a473f4d4c883db99221a78fe2f 552 | - action: update 553 | data: 554 | encoding: utf-8 555 | value: DATA 556 | key: 557 | encoding: hex 558 | value: b310919be4d5c7892739294545b85928746fa6b90e568f04af5fb6c48379c3a9 559 | - action: update 560 | data: 561 | encoding: utf-8 562 | value: DATA 563 | key: 564 | encoding: hex 565 | value: 4149d67891c7efddad38eb590d537d3f33a25d6454ffba671e1c20cf5824a22c 566 | - action: update 567 | data: 568 | encoding: utf-8 569 | value: DATA 570 | key: 571 | encoding: hex 572 | value: 16ab79353cdbc2bef69a106f68d5f6b5adc70bce130df5a523212826ef117d3f 573 | - action: update 574 | data: 575 | encoding: utf-8 576 | value: DATA 577 | key: 578 | encoding: hex 579 | value: d8063c1eafe3b5fd49d4c8e8737316ba79a8729f7364426382c575422af3f84d 580 | - action: update 581 | data: 582 | encoding: utf-8 583 | value: DATA 584 | key: 585 | encoding: hex 586 | value: 59310b9b2c75881cf3edca5da5a755ed36ed737945a84c6e50c657de0c513c7e 587 | - action: update 588 | data: 589 | encoding: utf-8 590 | value: DATA 591 | key: 592 | encoding: hex 593 | value: 800b108f968347f00ac77eb6511893e19dde9e8aba637d28efceb636369a817c 594 | - action: update 595 | data: 596 | encoding: utf-8 597 | value: DATA 598 | key: 599 | encoding: hex 600 | value: acdcbc039caf8f6b1cbc24d2f87a03785d8f60ed23be607d17950d62ea8c33f5 601 | - action: update 602 | data: 603 | encoding: utf-8 604 | value: DATA 605 | key: 606 | encoding: hex 607 | value: dfe4224c822504739c7efea90fd28bf76a31a68ecb99096166eab251f5535a17 608 | - action: update 609 | data: 610 | encoding: utf-8 611 | value: DATA 612 | key: 613 | encoding: hex 614 | value: eb23c65a4244616063b70d7502b960e5d5d07b51a02472ab8a01e7482da34e47 615 | - action: update 616 | data: 617 | encoding: utf-8 618 | value: DATA 619 | key: 620 | encoding: hex 621 | value: 97efc1907815f13e6a02d4149a09e9a5389388ed6def2c1260cfec26d3b19f3f 622 | - action: update 623 | data: 624 | encoding: utf-8 625 | value: DATA 626 | key: 627 | encoding: hex 628 | value: 3523d19074cac2abcc3ace63b121eefa537c8e4070e30875ba5685f46bb010ef 629 | - action: update 630 | data: 631 | encoding: utf-8 632 | value: DATA 633 | key: 634 | encoding: hex 635 | value: b16a7efa6c4b528ecbe9db04df4d2bb4e555efe819233c9134311fa0a463e5f5 636 | - action: update 637 | data: 638 | encoding: utf-8 639 | value: DATA 640 | key: 641 | encoding: hex 642 | value: 702a137706cb2ef04842c238c2b37fed632682838b99b0a6f504cf6b0188dafd 643 | - action: update 644 | data: 645 | encoding: utf-8 646 | value: DATA 647 | key: 648 | encoding: hex 649 | value: b70aeff402d30d7d55ee164fd109ce3942fe50343ae513b3c3f7be9db96ea46d 650 | - action: update 651 | data: 652 | encoding: utf-8 653 | value: DATA 654 | key: 655 | encoding: hex 656 | value: 32fc4a6ccd676bae363546309128ef7c88d983c78688d2d53584af11c8a0be9c 657 | - action: update 658 | data: 659 | encoding: utf-8 660 | value: DATA 661 | key: 662 | encoding: hex 663 | value: 43b728ce5e336e2e48a38a61805a73c094e7c1e6bbd6f85bedd679986aea5bfb 664 | - action: update 665 | data: 666 | encoding: utf-8 667 | value: DATA 668 | key: 669 | encoding: hex 670 | value: 920218ce21e9b273c4110f07c5803f74266a7b9ca388285752a3924acfb96cf6 671 | - action: update 672 | data: 673 | encoding: utf-8 674 | value: DATA 675 | key: 676 | encoding: hex 677 | value: b894454077582b5d5aad1f58872264afc2ddb8d95683fb8c005e3f98c2aa26f8 678 | - action: update 679 | data: 680 | encoding: utf-8 681 | value: DATA 682 | key: 683 | encoding: hex 684 | value: ca3076acbb6ec2b695ebf174caa57ef3f8421707948a72029cc3836b9572c9d7 685 | - action: update 686 | data: 687 | encoding: utf-8 688 | value: DATA 689 | key: 690 | encoding: hex 691 | value: d2febf3079d64fcc48205885b66974fbecac6162a3e75761b082c228e364dd7e 692 | - action: update 693 | data: 694 | encoding: utf-8 695 | value: DATA 696 | key: 697 | encoding: hex 698 | value: 0f471c818c185f9c35ddd6c05738371e15c29a8f9d9a3b244f30652f48c2aa69 699 | - action: update 700 | data: 701 | encoding: utf-8 702 | value: DATA 703 | key: 704 | encoding: hex 705 | value: a40fb80ad4287819ecda5efac01c74c78d7cb00ca5f9eb5f6c0f19bd09936ac1 706 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 2 Delete 1.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 39f36a7cb4dfb1b46f03d044265df6a491dffc1034121bc1071a34ddce9bb14b 4 | name: Test Update 2 Delete 1 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: delete 21 | key: 22 | encoding: hex 23 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 24 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 2.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 8d0ae412ca9ca0afcb3217af8bcd5a673e798bd6fd1dfacad17711e883f494cb 4 | name: Test Update 2 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 3.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 52295e42d8de2505fdc0cc825ff9fead419cbcf540d8b30c7c4b9c9b94c268b7 4 | name: Test Update 3 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update 5.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 108f731f2414e33ae57e584dc26bd276db07874436b2264ca6e520c658185c6b 4 | name: Test Update 5 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 41 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update Overwrite Key.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: dd97174c80e5e5aa3a31c61b05e279c1495c8a07b2a08bca5dbc9fb9774f9457 4 | name: Test Update Overwrite Key 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: CHANGE 17 | key: 18 | encoding: hex 19 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 20 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update Sparse Union.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: e912e97abc67707b2e6027338292943b53d01a7fbd7b244674128c7e468dd696 4 | name: Test Update Sparse Union 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: b253668f6b59f1ff28522831931e4d3c5a3de533965af22e961735437c0172cb 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 17eb70034b5b71092521d184c5e7b069d47de657e51aef2be11a00c115036943 41 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update Union.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 7e6643325042cfe0fc76626c043b97062af51c7e9fc56665f12b479034bce326 4 | name: Test Update Union 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: b40711a88c7039756fb8a73827eabe2c0fe5a0346ca7e0a104adc0fc764f528d 20 | - action: update 21 | data: 22 | encoding: utf-8 23 | value: DATA 24 | key: 25 | encoding: hex 26 | value: 433ebf5bc03dffa38536673207a21281612cef5faa9bc7a4d5b9be2fdb12cf1a 27 | - action: update 28 | data: 29 | encoding: utf-8 30 | value: DATA 31 | key: 32 | encoding: hex 33 | value: 88185d128d9922e0e6bcd32b07b6c7f20f27968eab447a1d8d1cdf250f79f7d3 34 | - action: update 35 | data: 36 | encoding: utf-8 37 | value: DATA 38 | key: 39 | encoding: hex 40 | value: 1bc5d0e3df0ea12c4d0078668d14924f95106bbe173e196de50fe13a900b0937 41 | - action: update 42 | data: 43 | encoding: utf-8 44 | value: DATA 45 | key: 46 | encoding: hex 47 | value: e084a105a7b7d599b8346d3cba5ac51b756d7e29c7ef77fd9eff31fdeae31389 48 | - action: update 49 | data: 50 | encoding: utf-8 51 | value: DATA 52 | key: 53 | encoding: hex 54 | value: 390b36a09502b05d4f8c27aea2636c6b7fd05b27d742ed32074ffea1f888ebe4 55 | - action: update 56 | data: 57 | encoding: utf-8 58 | value: DATA 59 | key: 60 | encoding: hex 61 | value: c22ceee66b8ab104483c83053173b33f992dd4fcb457284c60ef9d699a1c7059 62 | - action: update 63 | data: 64 | encoding: utf-8 65 | value: DATA 66 | key: 67 | encoding: hex 68 | value: 8092fe01b9ce31a49ce380fc2fe1ee6b6b7d5c15c5f1ecb6ad98c60c4273a435 69 | - action: update 70 | data: 71 | encoding: utf-8 72 | value: DATA 73 | key: 74 | encoding: hex 75 | value: 7fde8eebf388fcff667a89be60430cc6e198b1a78cb603a39cdd09885a3336e3 76 | - action: update 77 | data: 78 | encoding: utf-8 79 | value: DATA 80 | key: 81 | encoding: hex 82 | value: a7911cdfdc28e6a1867e359ba426081aacfa692fdeb3e978d2a68dd924fa8c3e 83 | - action: update 84 | data: 85 | encoding: utf-8 86 | value: DATA 87 | key: 88 | encoding: hex 89 | value: 21548c66b44347d877e7b405a250121cda87cd494b122f0324f7df3b6cd75f86 90 | - action: update 91 | data: 92 | encoding: utf-8 93 | value: DATA 94 | key: 95 | encoding: hex 96 | value: bc2d9ddc9857e53598677dbea82a2583879e89ce6c032c77d825187bf3f1a943 97 | - action: update 98 | data: 99 | encoding: utf-8 100 | value: DATA 101 | key: 102 | encoding: hex 103 | value: 58ec452ede72799baf21664edc953297b592ad9e95f2381710593ad7a32f31ef 104 | - action: update 105 | data: 106 | encoding: utf-8 107 | value: DATA 108 | key: 109 | encoding: hex 110 | value: 79a881f99a636d0ad75f16f53668982b59f8bb96c3fbb449155fe7a08dba9cb1 111 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update With Empty Data Performs Delete.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: "0000000000000000000000000000000000000000000000000000000000000000" 4 | name: Test Update With Empty Data Performs Delete 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: "" 17 | key: 18 | encoding: hex 19 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 20 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update With Empty Data.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: "0000000000000000000000000000000000000000000000000000000000000000" 4 | name: Test Update With Empty Data 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: "" 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | -------------------------------------------------------------------------------- /test_vectors/sparse_merkle_tree/Test Update With Repeated Inputs.yaml: -------------------------------------------------------------------------------- 1 | expected_root: 2 | encoding: hex 3 | value: 39f36a7cb4dfb1b46f03d044265df6a491dffc1034121bc1071a34ddce9bb14b 4 | name: Test Update With Repeated Inputs 5 | steps: 6 | - action: update 7 | data: 8 | encoding: utf-8 9 | value: DATA 10 | key: 11 | encoding: hex 12 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 13 | - action: update 14 | data: 15 | encoding: utf-8 16 | value: DATA 17 | key: 18 | encoding: hex 19 | value: df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119 20 | --------------------------------------------------------------------------------